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