1use crate::smallint::{SmallIntType, SmallUintType};
2use crate::SmallInt;
3use crate::SmallIntError;
4use crate::SmallUint;
5use core::mem::ManuallyDrop;
6
7macro_rules! int_impl {
8 ($itype:ty, $rt:tt, $rtt:tt, $n:tt) => {
9 impl From<$itype> for $rt {
10 fn from(a: $itype) -> Self {
11 Self(<$rtt>::Inline($n::from(a)))
12 }
13 }
14
15 impl TryFrom<$rt> for $itype {
16 type Error = SmallIntError;
17
18 fn try_from(s: $rt) -> Result<Self, Self::Error> {
19 match s.0 {
20 $rtt::Inline(i) => {
21 <$itype>::try_from(i).map_err(|_| SmallIntError::ConversionError)
22 }
23 $rtt::Heap((_, _)) => Err(SmallIntError::ConversionError),
24 }
25 }
26 }
27 };
28}
29
30int_impl!(u8, SmallInt, SmallIntType, i128);
31int_impl!(u16, SmallInt, SmallIntType, i128);
32int_impl!(u32, SmallInt, SmallIntType, i128);
33int_impl!(u64, SmallInt, SmallIntType, i128);
34int_impl!(i8, SmallInt, SmallIntType, i128);
35int_impl!(i16, SmallInt, SmallIntType, i128);
36int_impl!(i32, SmallInt, SmallIntType, i128);
37int_impl!(i64, SmallInt, SmallIntType, i128);
38int_impl!(i128, SmallInt, SmallIntType, i128);
39
40int_impl!(u8, SmallUint, SmallUintType, u128);
41int_impl!(u16, SmallUint, SmallUintType, u128);
42int_impl!(u32, SmallUint, SmallUintType, u128);
43int_impl!(u64, SmallUint, SmallUintType, u128);
44int_impl!(u128, SmallUint, SmallUintType, u128);
45
46macro_rules! try_from_itou {
47 ($itype:ty) => {
48 impl TryFrom<$itype> for SmallUint {
49 type Error = SmallIntError;
50
51 fn try_from(a: $itype) -> Result<Self, Self::Error> {
52 Ok(Self(SmallUintType::Inline(
53 u128::try_from(a).map_err(|_| SmallIntError::ConversionError)?,
54 )))
55 }
56 }
57
58 impl TryFrom<SmallUint> for $itype {
59 type Error = SmallIntError;
60
61 fn try_from(s: SmallUint) -> Result<Self, Self::Error> {
62 match s.0 {
63 SmallUintType::Inline(i) => {
64 <$itype>::try_from(i).map_err(|_| SmallIntError::ConversionError)
65 }
66 SmallUintType::Heap((_, _)) => Err(SmallIntError::ConversionError),
67 }
68 }
69 }
70 };
71}
72
73try_from_itou!(i8);
74try_from_itou!(i16);
75try_from_itou!(i32);
76try_from_itou!(i64);
77try_from_itou!(i128);
78
79impl From<u128> for SmallInt {
80 fn from(a: u128) -> Self {
81 match i128::try_from(a) {
82 Ok(i) => Self(SmallIntType::Inline(i)),
83 Err(_) => {
84 let mut v = a;
85 let mut vec = Vec::with_capacity(4);
86 while v != 0 {
87 vec.push(v as u32);
88
89 v >>= 32;
90 }
91 let mut slice = ManuallyDrop::new(vec.into_boxed_slice());
92 Self(SmallIntType::Heap((
93 slice.as_mut_ptr(),
94 isize::try_from(slice.len()).unwrap(),
95 )))
96 }
97 }
98 }
99}
100
101impl TryFrom<SmallInt> for u128 {
102 type Error = SmallIntError;
103
104 fn try_from(s: SmallInt) -> Result<Self, Self::Error> {
105 match s.0 {
106 SmallIntType::Inline(i) => {
107 u128::try_from(i).map_err(|_| SmallIntError::ConversionError)
108 }
109 SmallIntType::Heap((r, s)) => {
110 let mut ret: u128 = 0;
111 let mut bits = 0;
112 let size = usize::try_from(s.abs()).unwrap();
113 let slice = unsafe { core::slice::from_raw_parts(r, size) };
114 for i in slice {
115 if bits >= 128 {
116 return Err(SmallIntError::ConversionError);
117 }
118 ret |= u128::from(*i) << bits;
119 bits += 32;
120 }
121
122 Ok(ret)
123 }
124 }
125 }
126}
127
128impl From<SmallUint> for SmallInt {
129 fn from(s: SmallUint) -> Self {
130 match s.0 {
131 SmallUintType::Inline(i) => SmallInt::from(i),
132 SmallUintType::Heap((r, s)) => {
133 let slice = unsafe { core::slice::from_raw_parts(r, s) };
134 let mut ret = vec![0; s];
135 ret.clone_from_slice(slice);
136 let mut val = ManuallyDrop::new(ret.into_boxed_slice());
137 SmallInt(SmallIntType::Heap((
138 val.as_mut_ptr(),
139 isize::try_from(s).unwrap(),
140 )))
141 }
142 }
143 }
144}
145
146impl TryFrom<SmallInt> for SmallUint {
147 type Error = SmallIntError;
148
149 fn try_from(value: SmallInt) -> Result<Self, Self::Error> {
150 match value.0 {
151 SmallIntType::Inline(i) => Self::try_from(i),
152 SmallIntType::Heap((r, s)) => {
153 let size = usize::try_from(s).map_err(|_| SmallIntError::ConversionError)?;
154 if size > 4 {
155 let slice = unsafe { core::slice::from_raw_parts(r, size) };
156 let mut ret = vec![0; size];
157 ret.clone_from_slice(slice);
158 let mut val = ManuallyDrop::new(ret.into_boxed_slice());
159 Ok(Self(SmallUintType::Heap((val.as_mut_ptr(), size))))
160 } else {
161 Ok(Self(SmallUintType::Inline(u128::try_from(value)?)))
162 }
163 }
164 }
165 }
166}
167
168impl SmallUint {
169 pub fn from_smallint_unsigned(value: SmallInt) -> Self {
171 match value.0 {
172 SmallIntType::Inline(i) => Self::try_from(i.abs()).unwrap(),
173 SmallIntType::Heap((r, s)) => {
174 let size = usize::try_from(s.abs()).unwrap();
175 if size > 4 {
176 let slice = unsafe { core::slice::from_raw_parts(r, size) };
177 let mut ret = vec![0; size];
178 ret.clone_from_slice(slice);
179 let mut val = ManuallyDrop::new(ret.into_boxed_slice());
180 Self(SmallUintType::Heap((val.as_mut_ptr(), size)))
181 } else if s >= 0 {
182 Self(SmallUintType::Inline(u128::try_from(value).unwrap()))
183 } else {
184 Self(SmallUintType::Inline(u128::try_from(-value).unwrap()))
185 }
186 }
187 }
188 }
189}