diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3dadef4..00b642c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,3 +16,6 @@ jobs: - name: Run tests run: RUSTFLAGS="-D warnings" cargo test --workspace + + - name: Run tests with no defaults + run: RUSTFLAGS="-D warnings" cargo test --workspace --no-default-features diff --git a/Cargo.toml b/Cargo.toml index 41969be..af32e78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,7 @@ keywords = ["texture", "atlas", "bin", "box", "packer"] description = "A general purpose, deterministic bin packer designed to conform to any two or three dimensional use case." license = "MIT/Apache-2.0" repository = "https://github.com/chinedufn/rectangle-pack" + +[features] +default = ["std"] +std = [] diff --git a/src/bin_section.rs b/src/bin_section.rs index b7316fd..940c612 100644 --- a/src/bin_section.rs +++ b/src/bin_section.rs @@ -1,7 +1,10 @@ use crate::packed_location::RotatedBy; use crate::{BoxSizeHeuristicFn, PackedLocation, RectToInsert, WidthHeightDepth}; -use std::cmp::Ordering; -use std::fmt::{Display, Formatter}; + +use core::{ + cmp::Ordering, + fmt::{Debug, Display, Error as ErrorFmt, Formatter}, +}; mod overlaps; @@ -57,7 +60,7 @@ pub enum BinSectionError { } impl Display for BinSectionError { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), ErrorFmt> { let err = match self { BinSectionError::PlacementWiderThanBinSection => { "Can not place a rectangle inside of a bin that is wider than that rectangle." diff --git a/src/grouped_rects_to_place.rs b/src/grouped_rects_to_place.rs index d22bcb7..04bf387 100644 --- a/src/grouped_rects_to_place.rs +++ b/src/grouped_rects_to_place.rs @@ -1,8 +1,16 @@ use crate::RectToInsert; -use std::collections::btree_map::Entry; -use std::collections::{BTreeMap, HashMap}; -use std::fmt::Debug; -use std::hash::Hash; + +#[cfg(std)] +use crate::Vec; +#[cfg(not(std))] +use alloc::collections::BTreeMap as KeyValMap; +use alloc::{ + collections::{btree_map::Entry, BTreeMap}, + vec::Vec, +}; +use core::{fmt::Debug, hash::Hash}; +#[cfg(std)] +use std::collections::HashMap as KeyValMap; /// Groups of rectangles that need to be placed into bins. /// @@ -19,9 +27,10 @@ where { // FIXME: inbound_id_to_group_id appears to be unused. If so, remove it. Also remove the // Hash and Eq constraints on RectToPlaceId if we remove this map - pub(crate) inbound_id_to_group_ids: HashMap>>, + pub(crate) inbound_id_to_group_ids: + KeyValMap>>, pub(crate) group_id_to_inbound_ids: BTreeMap, Vec>, - pub(crate) rects: HashMap, + pub(crate) rects: KeyValMap, } /// A group of rectangles that need to be placed together diff --git a/src/lib.rs b/src/lib.rs index fa8580a..1841e93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,20 @@ //! `rectangle-pack` is a library focused on laying out any number of smaller rectangles //! (both 2d rectangles and 3d rectangular prisms) inside any number of larger rectangles. - +#![cfg_attr(not(std), no_std)] #![deny(missing_docs)] -use std::collections::{BTreeMap, HashMap}; -use std::fmt::{Debug, Display, Formatter}; -use std::hash::Hash; +#[macro_use] +extern crate alloc; + +#[cfg(not(std))] +use alloc::collections::BTreeMap as KeyValMap; +use alloc::{collections::BTreeMap, vec::Vec}; +use core::{ + fmt::{Debug, Display, Error as ErrorFmt, Formatter}, + hash::Hash, +}; +#[cfg(std)] +use std::collections::HashMap as KeyValMap; pub use crate::bin_section::contains_smallest_box; pub use crate::bin_section::BinSection; @@ -128,7 +137,7 @@ pub fn pack_rects< box_size_heuristic: &BoxSizeHeuristicFn, more_suitable_containers_fn: &ComparePotentialContainersFn, ) -> Result, RectanglePackError> { - let mut packed_locations = HashMap::new(); + let mut packed_locations = KeyValMap::new(); let mut target_bins: Vec<(&BinId, &mut TargetBin)> = target_bins.iter_mut().collect(); sort_bins_smallest_to_largest(&mut target_bins, box_size_heuristic); @@ -254,7 +263,7 @@ where /// Information about successfully packed rectangles. #[derive(Debug, PartialEq)] pub struct RectanglePackOk { - packed_locations: HashMap, + packed_locations: KeyValMap, // TODO: Other information such as information about how the bins were packed // (perhaps percentage filled) } @@ -263,7 +272,7 @@ impl RectanglePackOk { /// Indicates where every incoming rectangle was placed - pub fn packed_locations(&self) -> &HashMap { + pub fn packed_locations(&self) -> &KeyValMap { &self.packed_locations } } @@ -276,7 +285,7 @@ pub enum RectanglePackError { } impl Display for RectanglePackError { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), ErrorFmt> { match self { RectanglePackError::NotEnoughBinSpace => { f.write_str("Not enough space to place all of the rectangles.") @@ -284,7 +293,7 @@ impl Display for RectanglePackError { } } } - +#[cfg(std)] impl std::error::Error for RectanglePackError {} fn sort_bins_smallest_to_largest( @@ -349,7 +358,6 @@ mod tests { use super::*; use crate::packed_location::RotatedBy; - use std::path::PathBuf; /// If the provided rectangles can't fit into the provided bins. #[test] @@ -787,7 +795,8 @@ mod tests { let mut previous_packed = None; for _ in 0..5 { - let mut rects_to_place: GroupedRectsToPlace = GroupedRectsToPlace::new(); + let mut rects_to_place: GroupedRectsToPlace<&'static str, &str> = + GroupedRectsToPlace::new(); let mut target_bins = BTreeMap::new(); for bin_id in 0..5 { @@ -803,7 +812,7 @@ mod tests { ]; for rect_id in rectangles.iter() { - rects_to_place.push_rect(PathBuf::from(rect_id), None, RectToInsert::new(4, 4, 1)); + rects_to_place.push_rect(rect_id, None, RectToInsert::new(4, 4, 1)); } let packed = pack_rects( diff --git a/src/target_bin.rs b/src/target_bin.rs index e75ebd4..4543906 100644 --- a/src/target_bin.rs +++ b/src/target_bin.rs @@ -1,5 +1,6 @@ use crate::bin_section::BinSection; use crate::width_height_depth::WidthHeightDepth; +use alloc::vec::Vec; mod coalesce; mod push_available_bin_section; diff --git a/src/target_bin/coalesce.rs b/src/target_bin/coalesce.rs index a69ad77..bf89192 100644 --- a/src/target_bin/coalesce.rs +++ b/src/target_bin/coalesce.rs @@ -1,5 +1,6 @@ use crate::TargetBin; -use std::ops::Range; + +use core::ops::Range; impl TargetBin { /// Over time as you use [`TargetBin.push_available_bin_section`] to return remove packed @@ -78,7 +79,10 @@ impl TargetBin { // Tests cases should have a rectangle and then a neighbor (above, below, left, right) and // verify that they get combined, but only if the comparison indices are correct and only if // the neighbor has the same width (uf above/below) or height (if left/right). - pub fn coalesce_available_sections(_bin_section_index: usize, _compare_to_indices: Range) { + pub fn coalesce_available_sections( + _bin_section_index: usize, + _compare_to_indices: Range, + ) { unimplemented!() } } diff --git a/src/target_bin/push_available_bin_section.rs b/src/target_bin/push_available_bin_section.rs index 9173234..8ceea40 100644 --- a/src/target_bin/push_available_bin_section.rs +++ b/src/target_bin/push_available_bin_section.rs @@ -8,7 +8,7 @@ use crate::bin_section::BinSection; use crate::TargetBin; -use std::fmt::{Display, Formatter}; +use core::fmt::{Display, Formatter, Result as ResultFmt}; impl TargetBin { /// Push a [`BinSection`] to the list of remaining [`BinSection`]'s that rectangles can be @@ -77,7 +77,7 @@ pub enum PushBinSectionError { } impl Display for PushBinSectionError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> ResultFmt { match self { PushBinSectionError::OutOfBounds(oob) => { f.debug_tuple("BinSection").field(oob).finish()