Skip to main content

cbor_core/value/
int.rs

1use crate::{Value, tag};
2// --------- From unsigned ints ---------
3
4macro_rules! try_from_uint {
5    ($type:ty) => {
6        impl From<$type> for Value {
7            fn from(value: $type) -> Self {
8                Self::Unsigned(value.into())
9            }
10        }
11    };
12}
13
14try_from_uint!(u8);
15try_from_uint!(u16);
16try_from_uint!(u32);
17try_from_uint!(u64);
18
19impl From<u128> for Value {
20    fn from(value: u128) -> Self {
21        if value <= u64::MAX as u128 {
22            Self::Unsigned(value as u64)
23        } else {
24            let bytes: Vec<u8> = value.to_be_bytes().into_iter().skip_while(|&byte| byte == 0).collect();
25            debug_assert!(bytes.len() > 8);
26            Self::tag(tag::POS_BIG_INT, bytes)
27        }
28    }
29}
30
31#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
32impl From<usize> for Value {
33    fn from(value: usize) -> Self {
34        Self::Unsigned(value as u64)
35    }
36}
37
38// --------- From signed ints ---------
39
40macro_rules! try_from_sint {
41    ($type:ty) => {
42        impl From<$type> for Value {
43            fn from(value: $type) -> Self {
44                if value >= 0 {
45                    Self::Unsigned(value as u64)
46                } else {
47                    Self::Negative((!value) as u64)
48                }
49            }
50        }
51    };
52}
53
54try_from_sint!(i8);
55try_from_sint!(i16);
56try_from_sint!(i32);
57try_from_sint!(i64);
58
59impl From<i128> for Value {
60    fn from(value: i128) -> Self {
61        if value >= 0 {
62            Self::from(value as u128)
63        } else {
64            let complement = (!value) as u128;
65
66            if complement <= u64::MAX as u128 {
67                Self::Negative(complement as u64)
68            } else {
69                let bytes: Vec<u8> = complement
70                    .to_be_bytes()
71                    .into_iter()
72                    .skip_while(|&byte| byte == 0)
73                    .collect();
74                debug_assert!(bytes.len() > 8);
75                Self::tag(tag::NEG_BIG_INT, bytes)
76            }
77        }
78    }
79}
80
81#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
82impl From<isize> for Value {
83    fn from(value: isize) -> Self {
84        Self::from(value as i64)
85    }
86}
87
88// --------- TryFrom Value ---------
89
90macro_rules! try_from_value {
91    ($type:ty, $to_x:ident) => {
92        impl TryFrom<Value> for $type {
93            type Error = crate::Error;
94            fn try_from(value: Value) -> crate::Result<Self> {
95                value.$to_x()
96            }
97        }
98
99        impl TryFrom<&Value> for $type {
100            type Error = crate::Error;
101            fn try_from(value: &Value) -> crate::Result<Self> {
102                value.$to_x()
103            }
104        }
105    };
106}
107
108try_from_value!(u8, to_u8);
109try_from_value!(u16, to_u16);
110try_from_value!(u32, to_u32);
111try_from_value!(u64, to_u64);
112try_from_value!(u128, to_u128);
113try_from_value!(usize, to_usize);
114
115try_from_value!(i8, to_i8);
116try_from_value!(i16, to_i16);
117try_from_value!(i32, to_i32);
118try_from_value!(i64, to_i64);
119try_from_value!(i128, to_i128);
120try_from_value!(isize, to_isize);