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