takia 0.15.1

Glory-maintained Taffy fork with corrected fractional flex gap layout
Documentation
//! Allocator-flexible data types

// When std is enabled, prefer those types
#[cfg(feature = "std")]
pub(crate) use self::std::*;

// Otherwise, use the types from the alloc crate
#[cfg(not(feature = "std"))]
pub(crate) use self::alloc::*;

/// For when `std` is enabled
#[cfg(feature = "std")]
mod std {
    /// A string
    pub(crate) type String = std::string::String;
    /// The default type for representing strings in Takia styles
    pub(crate) type DefaultCheapStr = String;
    /// A map
    pub(crate) type Map<K, V> = std::collections::HashMap<K, V, std::collections::hash_map::RandomState>;
    /// An allocation-backend agnostic vector type
    pub(crate) type Vec<A> = std::vec::Vec<A>;
    /// An allocation-backend agnostic boxed pointer type
    pub(crate) type Box<A> = std::boxed::Box<A>;
    /// A vector of child nodes
    pub(crate) type ChildrenVec<A> = std::vec::Vec<A>;
    #[cfg(feature = "grid")]
    /// A vector of grid tracks
    pub(crate) type GridTrackVec<A> = std::vec::Vec<A>;

    /// Creates a new vector with the capacity for the specified number of items before it must be resized
    #[must_use]
    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
        Vec::with_capacity(capacity)
    }

    /// Creates a new empty `ChildrenVec` in a const context
    #[must_use]
    pub(crate) const fn new_const_children_vec<A>() -> ChildrenVec<A> {
        Vec::new()
    }

    /// Rounds to the nearest whole number
    #[must_use]
    #[inline(always)]
    pub(crate) fn round(value: f32) -> f32 {
        (value + 0.5).floor()
    }

    /// Rounds up to the nearest whole number
    #[must_use]
    #[inline(always)]
    pub(crate) fn ceil(value: f32) -> f32 {
        value.ceil()
    }

    /// Rounds down to the nearest whole number
    #[must_use]
    #[inline(always)]
    pub(crate) fn floor(value: f32) -> f32 {
        value.floor()
    }

    /// Computes the absolute value
    #[must_use]
    #[inline(always)]
    pub(crate) fn abs(value: f32) -> f32 {
        value.abs()
    }

    /// Copies the sign of another value
    #[must_use]
    #[inline(always)]
    pub(crate) fn copysign(value: f32, sign: f32) -> f32 {
        value.copysign(sign)
    }

    /// Returns the largest of two f32 values
    #[inline(always)]
    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
        a.max(b)
    }

    /// Returns the smallest of two f32 values
    #[inline(always)]
    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
        a.min(b)
    }
}

/// For when `std` is not enabled
#[cfg(not(feature = "std"))]
mod alloc {
    extern crate alloc;

    /// A string
    pub(crate) type String = alloc::string::String;
    /// The default type for representing strings in Takia styles
    pub(crate) type DefaultCheapStr = String;
    /// A map
    // TODO: consider using hashbrown
    pub(crate) type Map<K, V> = alloc::collections::BTreeMap<K, V>;
    /// An allocation-backend agnostic vector type
    pub(crate) type Vec<A> = alloc::vec::Vec<A>;
    /// An allocation-backend agnostic boxed pointer type
    pub(crate) type Box<A> = alloc::boxed::Box<A>;
    /// A vector of child nodes
    pub(crate) type ChildrenVec<A> = alloc::vec::Vec<A>;
    #[cfg(feature = "grid")]
    /// A vector of grid tracks
    pub(crate) type GridTrackVec<A> = alloc::vec::Vec<A>;

    /// Creates a new vector with the capacity for the specified number of items before it must be resized
    #[must_use]
    pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
        Vec::with_capacity(capacity)
    }

    /// Creates a new empty `ChildrenVec` in a const context
    #[must_use]
    pub(crate) const fn new_const_children_vec<A>() -> ChildrenVec<A> {
        Vec::new()
    }

    /// Rounds to the nearest whole number
    pub(crate) use super::polyfill::round;

    /// Rounds up to the nearest whole number
    pub(crate) use super::polyfill::ceil;

    /// Rounds down to the nearest whole number
    pub(crate) use super::polyfill::floor;

    /// Computes the absolute value
    pub(crate) use super::polyfill::abs;

    /// Copies the sign of another value
    pub(crate) use super::polyfill::copysign;

    /// Returns the largest of two f32 values
    #[inline(always)]
    pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
        a.max(b)
    }

    /// Returns the smallest of two f32 values
    #[inline(always)]
    pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
        a.min(b)
    }
}

/// Implementations of float functions for no_std builds
/// Copied from `num-traits` crate
#[cfg(not(feature = "std"))]
mod polyfill {
    #[must_use]
    #[inline(always)]
    fn fract(value: f32) -> f32 {
        if value == 0.0 {
            0.0
        } else {
            value % 1.0
        }
    }

    #[must_use]
    #[inline(always)]
    pub(crate) fn round(value: f32) -> f32 {
        let f = fract(value);
        if f.is_nan() || f == 0.0 {
            value
        } else if value > 0.0 {
            if f < 0.5 {
                value - f
            } else {
                value - f + 1.0
            }
        } else if -f < 0.5 {
            value - f
        } else {
            value - f - 1.0
        }
    }

    #[must_use]
    #[inline(always)]
    pub(crate) fn floor(value: f32) -> f32 {
        let f = fract(value);
        if f.is_nan() || f == 0.0 {
            value
        } else if value < 0.0 {
            value - f - 1.0
        } else {
            value - f
        }
    }

    #[must_use]
    #[inline(always)]
    pub(crate) fn ceil(value: f32) -> f32 {
        let f = fract(value);
        if f.is_nan() || f == 0.0 {
            value
        } else if value > 0.0 {
            value - f + 1.0
        } else {
            value - f
        }
    }

    /// Computes the absolute value
    #[must_use]
    #[inline(always)]
    pub(crate) fn abs(value: f32) -> f32 {
        f32::from_bits(value.to_bits() & 0x7fff_ffff)
    }

    /// Copies the sign of another value
    #[must_use]
    #[inline(always)]
    pub(crate) fn copysign(value: f32, sign: f32) -> f32 {
        f32::from_bits((value.to_bits() & 0x7fff_ffff) | (sign.to_bits() & 0x8000_0000))
    }
}

#[cfg(test)]
mod tests {
    use super::{abs, copysign};

    #[test]
    fn float_sign_helpers_preserve_bits() {
        for bits in [0, 0x8000_0000, 0x3fc0_0000, 0xbfc0_0000, 0x7f80_0000, 0xff80_0000, 0x7fc0_1234, 0xffc0_1234] {
            let value = f32::from_bits(bits);
            assert_eq!(abs(value).to_bits(), bits & 0x7fff_ffff);
            for sign_bits in [0, 0x8000_0000, 0x3f80_0000, 0xbf80_0000, 0x7fc0_1234, 0xffc0_1234] {
                let sign = f32::from_bits(sign_bits);
                assert_eq!(copysign(value, sign).to_bits(), (bits & 0x7fff_ffff) | (sign_bits & 0x8000_0000));
            }
        }
    }
}