vortex_scalar/bigint/
bigcast.rs1use crate::i256;
2
3pub trait ToPrimitive: num_traits::ToPrimitive {
7 fn to_i256(&self) -> Option<i256>;
10}
11
12macro_rules! impl_toprimitive_lossless {
14 ($typ:ty) => {
15 impl ToPrimitive for $typ {
16 #[inline]
17 fn to_i256(&self) -> Option<i256> {
18 Some(i256::from_i128(*self as i128))
19 }
20 }
21 };
22}
23
24impl_toprimitive_lossless!(u8);
26impl_toprimitive_lossless!(u16);
27impl_toprimitive_lossless!(u32);
28impl_toprimitive_lossless!(u64);
29
30impl_toprimitive_lossless!(i8);
32impl_toprimitive_lossless!(i16);
33impl_toprimitive_lossless!(i32);
34impl_toprimitive_lossless!(i64);
35impl_toprimitive_lossless!(i128);
36
37impl ToPrimitive for u128 {
39 fn to_i256(&self) -> Option<i256> {
40 Some(i256::from_parts(*self, 0))
41 }
42}
43
44impl ToPrimitive for i256 {
46 fn to_i256(&self) -> Option<i256> {
47 Some(*self)
48 }
49}
50
51pub trait BigCast: Sized + ToPrimitive {
55 fn from<T: ToPrimitive>(n: T) -> Option<Self>;
58}
59
60macro_rules! impl_big_cast {
61 ($T:ty, $conv:ident) => {
62 impl BigCast for $T {
63 fn from<T: ToPrimitive>(n: T) -> Option<Self> {
64 n.$conv()
65 }
66 }
67 };
68}
69
70impl_big_cast!(u8, to_u8);
71impl_big_cast!(u16, to_u16);
72impl_big_cast!(u32, to_u32);
73impl_big_cast!(u64, to_u64);
74impl_big_cast!(u128, to_u128);
75impl_big_cast!(i8, to_i8);
76impl_big_cast!(i16, to_i16);
77impl_big_cast!(i32, to_i32);
78impl_big_cast!(i64, to_i64);
79impl_big_cast!(i128, to_i128);
80impl_big_cast!(i256, to_i256);
81
82#[cfg(test)]
83mod tests {
84 use std::fmt::Debug;
85
86 use rstest::rstest;
87
88 use crate::{BigCast, i256};
89
90 #[rstest]
92 #[case(u8::MAX)]
93 #[case(u16::MAX)]
94 #[case(u32::MAX)]
95 #[case(u64::MAX)]
96 #[case(u128::MAX)]
97 #[case(i8::MAX)]
98 #[case(i16::MAX)]
99 #[case(i32::MAX)]
100 #[case(i64::MAX)]
101 #[case(i128::MAX)]
102 #[case(i256::MAX)]
103 fn test_big_cast_identity<T: BigCast + Eq + Debug + Copy>(#[case] n: T) {
104 assert_eq!(<T as BigCast>::from(n).unwrap(), n);
105 }
106
107 macro_rules! test_big_cast_overflow {
108 ($name:ident, $src:ty => $dst:ty, $max:expr, $one:expr) => {
109 #[test]
110 fn $name() {
111 let v = <$dst as BigCast>::from($max).unwrap();
113 assert_eq!(<$src as BigCast>::from(v), Some($max));
115
116 let v = v + $one;
118 assert_eq!(<$src as BigCast>::from(v), None);
119 }
120 };
121 }
122
123 test_big_cast_overflow!(test_i8_overflow, i8 => i16, i8::MAX, 1i16);
124 test_big_cast_overflow!(test_i16_overflow, i16 => i32, i16::MAX, 1i32);
125 test_big_cast_overflow!(test_i32_overflow, i32 => i64, i32::MAX, 1i64);
126 test_big_cast_overflow!(test_i64_overflow, i64 => i128, i64::MAX, 1i128);
127 test_big_cast_overflow!(test_i128_overflow, i128 => i256, i128::MAX, i256::ONE);
128}