Skip to main content

taffy/util/
sys.rs

1//! Allocator-flexible data types
2
3// When std is enabled, prefer those types
4#[cfg(feature = "std")]
5pub(crate) use self::std::*;
6
7// When alloc but not std is enabled, use those types
8#[cfg(all(feature = "alloc", not(feature = "std")))]
9pub(crate) use self::alloc::*;
10
11// When neither alloc or std is enabled, use a heapless fallback
12#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
13pub(crate) use self::core::*;
14
15/// For when `std` is enabled
16#[cfg(feature = "std")]
17mod std {
18    // // Re-exporting a macro_rules macro doesn't work properly, so we wrap
19    // // it in a trivial new macro that just forwards it's input to the underlying
20    // // std/alloc macro
21    // macro_rules! format {
22    //     ($($tokens:tt)*) => {
23    //         ::std::format!($($tokens)*)
24    //     };
25    // }
26    // pub(crate) use format;
27
28    pub(crate) use std::format;
29
30    /// A string
31    pub(crate) type String = std::string::String;
32    /// The default type for representing strings in Taffy styles
33    pub(crate) type DefaultCheapStr = String;
34    /// A map
35    pub(crate) type Map<K, V> = std::collections::HashMap<K, V, std::collections::hash_map::RandomState>;
36    /// An allocation-backend agnostic vector type
37    pub(crate) type Vec<A> = std::vec::Vec<A>;
38    /// A vector of child nodes
39    pub(crate) type ChildrenVec<A> = std::vec::Vec<A>;
40    #[cfg(feature = "grid")]
41    /// A vector of grid tracks
42    pub(crate) type GridTrackVec<A> = std::vec::Vec<A>;
43
44    /// Creates a new vector with the capacity for the specified number of items before it must be resized
45    #[must_use]
46    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
47        Vec::with_capacity(capacity)
48    }
49
50    /// Rounds to the nearest whole number
51    #[must_use]
52    #[inline(always)]
53    pub(crate) fn round(value: f32) -> f32 {
54        (value + 0.5).floor()
55    }
56
57    /// Rounds up to the nearest whole number
58    #[must_use]
59    #[inline(always)]
60    pub(crate) fn ceil(value: f32) -> f32 {
61        value.ceil()
62    }
63
64    /// Rounds down to the nearest whole number
65    #[must_use]
66    #[inline(always)]
67    pub(crate) fn floor(value: f32) -> f32 {
68        value.floor()
69    }
70
71    /// Computes the absolute value
72    #[must_use]
73    #[inline(always)]
74    pub(crate) fn abs(value: f32) -> f32 {
75        value.abs()
76    }
77
78    /// Returns the largest of two f32 values
79    #[inline(always)]
80    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
81        a.max(b)
82    }
83
84    /// Returns the smallest of two f32 values
85    #[inline(always)]
86    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
87        a.min(b)
88    }
89}
90
91/// For when `alloc` but not `std` is enabled
92#[cfg(all(feature = "alloc", not(feature = "std")))]
93mod alloc {
94    extern crate alloc;
95    use core::cmp::Ordering;
96
97    // // Re-exporting a macro_rules macro doesn't work properly, so we wrap
98    // // it in a trivial new macro that just forwards it's input to the underlying
99    // // std/alloc macro
100    // macro_rules! format {
101    //     ($($tokens:tt)*) => {
102    //         ::alloc::fmt::format!($($tokens)*)
103    //     };
104    // }
105    // pub(crate) use format;
106
107    pub(crate) use alloc::format;
108
109    /// A string
110    pub(crate) type String = alloc::string::String;
111    /// The default type for representing strings in Taffy styles
112    pub(crate) type DefaultCheapStr = String;
113    /// A map
114    // TODO: consider using hashbrown
115    pub(crate) type Map<K, V> = alloc::collections::BTreeMap<K, V>;
116    /// An allocation-backend agnostic vector type
117    pub(crate) type Vec<A> = alloc::vec::Vec<A>;
118    /// A vector of child nodes
119    pub(crate) type ChildrenVec<A> = alloc::vec::Vec<A>;
120    #[cfg(feature = "grid")]
121    /// A vector of grid tracks
122    pub(crate) type GridTrackVec<A> = alloc::vec::Vec<A>;
123
124    /// Creates a new vector with the capacity for the specified number of items before it must be resized
125    #[must_use]
126    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
127        Vec::with_capacity(capacity)
128    }
129
130    /// Rounds to the nearest whole number
131    pub(crate) use super::polyfill::round;
132
133    /// Rounds up to the nearest whole number
134    pub(crate) use super::polyfill::ceil;
135
136    /// Rounds down to the nearest whole number
137    pub(crate) use super::polyfill::floor;
138
139    /// Computes the absolute value
140    pub(crate) use super::polyfill::abs;
141
142    /// Returns the largest of two f32 values
143    #[inline(always)]
144    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
145        a.max(b)
146    }
147
148    /// Returns the smallest of two f32 values
149    #[inline(always)]
150    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
151        a.min(b)
152    }
153}
154
155/// For when neither `alloc` nor `std` is enabled
156#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
157mod core {
158    use core::cmp::Ordering;
159
160    /// The maximum number of nodes in the tree
161    pub const MAX_NODE_COUNT: usize = 256;
162    /// The maximum number of children of any given node
163    pub const MAX_CHILD_COUNT: usize = 16;
164    #[cfg(feature = "grid")]
165    /// The maximum number of children of any given node
166    pub const MAX_GRID_TRACKS: usize = 16;
167
168    /// A string
169    pub(crate) type String = &'static str;
170    /// The default type for representing strings in Taffy styles
171    pub(crate) type DefaultCheapStr = &'static str;
172
173    /// An allocation-backend agnostic vector type
174    pub(crate) type Vec<A> = arrayvec::ArrayVec<A, MAX_NODE_COUNT>;
175    /// A vector of child nodes, whose length cannot exceed [`MAX_CHILD_COUNT`]
176    pub(crate) type ChildrenVec<A> = arrayvec::ArrayVec<A, MAX_CHILD_COUNT>;
177    #[cfg(feature = "grid")]
178    /// A vector of grid tracks
179    pub(crate) type GridTrackVec<A> = arrayvec::ArrayVec<A, MAX_GRID_TRACKS>;
180
181    /// Creates a new map with the capacity for the specified number of items before it must be resized
182    ///
183    /// This vector cannot be resized.
184    #[must_use]
185    pub(crate) fn new_vec_with_capacity<A, const CAP: usize>(_capacity: usize) -> arrayvec::ArrayVec<A, CAP> {
186        arrayvec::ArrayVec::new()
187    }
188
189    /// Rounds to the nearest whole number
190    pub(crate) use super::polyfill::round;
191
192    /// Computes the absolute value
193    pub(crate) use super::polyfill::abs;
194
195    /// Returns the largest of two f32 values
196    #[inline(always)]
197    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
198        a.max(b)
199    }
200
201    /// Returns the smallest of two f32 values
202    #[inline(always)]
203    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
204        a.min(b)
205    }
206}
207
208/// Implementations of float functions for no_std and alloc builds
209/// Copied from `num-traits` crate
210#[cfg(not(feature = "std"))]
211mod polyfill {
212    #[must_use]
213    #[inline(always)]
214    fn fract(value: f32) -> f32 {
215        if value == 0.0 {
216            0.0
217        } else {
218            value % 1.0
219        }
220    }
221
222    #[must_use]
223    #[inline(always)]
224    pub(crate) fn round(value: f32) -> f32 {
225        let f = fract(value);
226        if f.is_nan() || f == 0.0 {
227            value
228        } else if value > 0.0 {
229            if f < 0.5 {
230                value - f
231            } else {
232                value - f + 1.0
233            }
234        } else if -f < 0.5 {
235            value - f
236        } else {
237            value - f - 1.0
238        }
239    }
240
241    #[must_use]
242    #[inline(always)]
243    pub(crate) fn floor(value: f32) -> f32 {
244        let f = fract(value);
245        if f.is_nan() || f == 0.0 {
246            value
247        } else if value < 0.0 {
248            value - f - 1.0
249        } else {
250            value - f
251        }
252    }
253
254    #[must_use]
255    #[inline(always)]
256    pub(crate) fn ceil(value: f32) -> f32 {
257        let f = fract(value);
258        if f.is_nan() || f == 0.0 {
259            value
260        } else if value > 0.0 {
261            value - f + 1.0
262        } else {
263            value - f
264        }
265    }
266
267    /// Computes the absolute value
268    #[must_use]
269    #[inline(always)]
270    pub(crate) fn abs(value: f32) -> f32 {
271        if value.is_sign_positive() {
272            return value;
273        } else if value.is_sign_negative() {
274            return -value;
275        } else {
276            f32::NAN
277        }
278    }
279}