fixed_bigint/fixeduint/
num_traits_casts.rs

1use super::{FixedUInt, MachineWord};
2
3use num_traits::{Bounded, FromPrimitive, ToPrimitive};
4
5impl<T: MachineWord, const N: usize> num_traits::NumCast for FixedUInt<T, N> {
6    fn from<X>(arg: X) -> Option<Self>
7    where
8        X: ToPrimitive,
9    {
10        Self::from_u64(arg.to_u64()?)
11    }
12}
13
14impl<T: MachineWord, const N: usize> num_traits::ToPrimitive for FixedUInt<T, N> {
15    fn to_i64(&self) -> Option<i64> {
16        None
17    }
18    fn to_u64(&self) -> Option<u64> {
19        let mut ret: u64 = 0;
20        let iter: usize = core::cmp::min(8 / Self::WORD_SIZE, N);
21        for (word, bits) in (0..iter).map(|x| (x, x as u64 * Self::WORD_SIZE as u64 * 8)) {
22            ret += T::to_u64(&self.array[word])? << bits;
23        }
24        Some(ret)
25    }
26}
27
28impl<T: MachineWord, const N: usize> num_traits::FromPrimitive for FixedUInt<T, N> {
29    fn from_i64(_: i64) -> Option<Self> {
30        None
31    }
32    fn from_u64(input: u64) -> Option<Self> {
33        // If max_value() fits in a u64, verify the input does not exceed it.
34        // When to_u64() returns `None`, the target type is wider than 64 bits
35        // and therefore any u64 value will fit.
36        if let Some(max) = Self::max_value().to_u64() {
37            if input > max {
38                return None;
39            }
40        }
41        Some(Self::from_le_bytes(&input.to_le_bytes()))
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    fn cast<T: num_traits::NumCast + PartialEq>(a: u32, b: u8) -> bool {
50        let my_a = T::from(a).unwrap();
51        let my_b = T::from(b).unwrap();
52        my_a == my_b
53    }
54
55    type Fixed = FixedUInt<u8, 1>;
56    // Test numcast
57    #[test]
58    fn test_numcast() {
59        assert!(cast::<Fixed>(123, 123));
60        assert!(cast::<Fixed>(225, 225));
61    }
62}