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// Otherwise, use the types from the alloc crate
8#[cfg(not(feature = "std"))]
9pub(crate) use self::alloc::*;
10
11/// For when `std` is enabled
12#[cfg(feature = "std")]
13mod std {
14    /// A string
15    pub(crate) type String = std::string::String;
16    /// The default type for representing strings in Taffy styles
17    pub(crate) type DefaultCheapStr = String;
18    /// A map
19    pub(crate) type Map<K, V> = std::collections::HashMap<K, V, std::collections::hash_map::RandomState>;
20    /// An allocation-backend agnostic vector type
21    pub(crate) type Vec<A> = std::vec::Vec<A>;
22    /// An allocation-backend agnostic boxed pointer type
23    pub(crate) type Box<A> = std::boxed::Box<A>;
24    /// A vector of child nodes
25    pub(crate) type ChildrenVec<A> = std::vec::Vec<A>;
26    #[cfg(feature = "grid")]
27    /// A vector of grid tracks
28    pub(crate) type GridTrackVec<A> = std::vec::Vec<A>;
29
30    /// Creates a new vector with the capacity for the specified number of items before it must be resized
31    #[must_use]
32    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
33        Vec::with_capacity(capacity)
34    }
35
36    /// Creates a new empty `ChildrenVec` in a const context
37    #[must_use]
38    pub(crate) const fn new_const_children_vec<A>() -> ChildrenVec<A> {
39        Vec::new()
40    }
41
42    /// Rounds to the nearest whole number
43    #[must_use]
44    #[inline(always)]
45    pub(crate) fn round(value: f32) -> f32 {
46        (value + 0.5).floor()
47    }
48
49    /// Rounds up to the nearest whole number
50    #[must_use]
51    #[inline(always)]
52    pub(crate) fn ceil(value: f32) -> f32 {
53        value.ceil()
54    }
55
56    /// Rounds down to the nearest whole number
57    #[must_use]
58    #[inline(always)]
59    pub(crate) fn floor(value: f32) -> f32 {
60        value.floor()
61    }
62
63    /// Computes the absolute value
64    #[must_use]
65    #[inline(always)]
66    pub(crate) fn abs(value: f32) -> f32 {
67        value.abs()
68    }
69
70    /// Returns the largest of two f32 values
71    #[inline(always)]
72    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
73        a.max(b)
74    }
75
76    /// Returns the smallest of two f32 values
77    #[inline(always)]
78    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
79        a.min(b)
80    }
81}
82
83/// For when `std` is not enabled
84#[cfg(not(feature = "std"))]
85mod alloc {
86    extern crate alloc;
87
88    /// A string
89    pub(crate) type String = alloc::string::String;
90    /// The default type for representing strings in Taffy styles
91    pub(crate) type DefaultCheapStr = String;
92    /// A map
93    // TODO: consider using hashbrown
94    pub(crate) type Map<K, V> = alloc::collections::BTreeMap<K, V>;
95    /// An allocation-backend agnostic vector type
96    pub(crate) type Vec<A> = alloc::vec::Vec<A>;
97    /// An allocation-backend agnostic boxed pointer type
98    pub(crate) type Box<A> = alloc::boxed::Box<A>;
99    /// A vector of child nodes
100    pub(crate) type ChildrenVec<A> = alloc::vec::Vec<A>;
101    #[cfg(feature = "grid")]
102    /// A vector of grid tracks
103    pub(crate) type GridTrackVec<A> = alloc::vec::Vec<A>;
104
105    /// Creates a new vector with the capacity for the specified number of items before it must be resized
106    #[must_use]
107    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
108        Vec::with_capacity(capacity)
109    }
110
111    /// Creates a new empty `ChildrenVec` in a const context
112    #[must_use]
113    pub(crate) const fn new_const_children_vec<A>() -> ChildrenVec<A> {
114        Vec::new()
115    }
116
117    /// Rounds to the nearest whole number
118    pub(crate) use super::polyfill::round;
119
120    /// Rounds up to the nearest whole number
121    pub(crate) use super::polyfill::ceil;
122
123    /// Rounds down to the nearest whole number
124    pub(crate) use super::polyfill::floor;
125
126    /// Computes the absolute value
127    pub(crate) use super::polyfill::abs;
128
129    /// Returns the largest of two f32 values
130    #[inline(always)]
131    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
132        a.max(b)
133    }
134
135    /// Returns the smallest of two f32 values
136    #[inline(always)]
137    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
138        a.min(b)
139    }
140}
141
142/// Implementations of float functions for no_std builds
143/// Copied from `num-traits` crate
144#[cfg(not(feature = "std"))]
145mod polyfill {
146    #[must_use]
147    #[inline(always)]
148    fn fract(value: f32) -> f32 {
149        if value == 0.0 {
150            0.0
151        } else {
152            value % 1.0
153        }
154    }
155
156    #[must_use]
157    #[inline(always)]
158    pub(crate) fn round(value: f32) -> f32 {
159        let f = fract(value);
160        if f.is_nan() || f == 0.0 {
161            value
162        } else if value > 0.0 {
163            if f < 0.5 {
164                value - f
165            } else {
166                value - f + 1.0
167            }
168        } else if -f < 0.5 {
169            value - f
170        } else {
171            value - f - 1.0
172        }
173    }
174
175    #[must_use]
176    #[inline(always)]
177    pub(crate) fn floor(value: f32) -> f32 {
178        let f = fract(value);
179        if f.is_nan() || f == 0.0 {
180            value
181        } else if value < 0.0 {
182            value - f - 1.0
183        } else {
184            value - f
185        }
186    }
187
188    #[must_use]
189    #[inline(always)]
190    pub(crate) fn ceil(value: f32) -> f32 {
191        let f = fract(value);
192        if f.is_nan() || f == 0.0 {
193            value
194        } else if value > 0.0 {
195            value - f + 1.0
196        } else {
197            value - f
198        }
199    }
200
201    /// Computes the absolute value
202    #[must_use]
203    #[inline(always)]
204    pub(crate) fn abs(value: f32) -> f32 {
205        if value.is_sign_positive() {
206            return value;
207        } else if value.is_sign_negative() {
208            return -value;
209        } else {
210            f32::NAN
211        }
212    }
213}