1use crate::Decimal;
27use crate::error::ConvertError;
28
29pub(crate) const fn is_sound_const(
40 int_max: i128,
41 int_min: i128,
42 backing_max: i128,
43 backing_min: i128,
44 d: u32,
45) -> bool {
46 let Some(pow) = 10_i128.checked_pow(d) else {
47 return false;
48 };
49 let Some(max_scaled) = int_max.checked_mul(pow) else {
50 return false;
51 };
52 let Some(min_scaled) = int_min.checked_mul(pow) else {
53 return false;
54 };
55 max_scaled <= backing_max && min_scaled >= backing_min
56}
57
58macro_rules! impl_from_sound {
59 ($backing:ty, $d:literal, [$($int:ty),* $(,)?]) => {
60 $(
61 const _: () = assert!(
69 $crate::from_int::is_sound_const(
70 <$int>::MAX as i128,
71 <$int>::MIN as i128,
72 <$backing>::MAX as i128,
73 <$backing>::MIN as i128,
74 $d,
75 ),
76 concat!(
77 "nexus-decimal: impl_from_sound! invoked with unsound combination ",
78 stringify!($int),
79 " -> Decimal<",
80 stringify!($backing),
81 ", ",
82 stringify!($d),
83 ">"
84 ),
85 );
86
87 impl From<$int> for Decimal<$backing, $d> {
88 #[inline(always)]
92 fn from(value: $int) -> Self {
93 Self {
94 value: (value as $backing) * Self::SCALE,
95 }
96 }
97 }
98 )*
99 };
100}
101
102macro_rules! impl_try_from_int {
103 ($backing:ty, $d:literal, signed: [$($int:ty),* $(,)?]) => {
104 $(
105 impl TryFrom<$int> for Decimal<$backing, $d> {
106 type Error = ConvertError;
107 #[inline]
108 fn try_from(value: $int) -> Result<Self, Self::Error> {
109 Self::from_i64(value as i64).ok_or(ConvertError::Overflow)
110 }
111 }
112 )*
113 };
114 ($backing:ty, $d:literal, unsigned: [$($int:ty),* $(,)?]) => {
115 $(
116 impl TryFrom<$int> for Decimal<$backing, $d> {
117 type Error = ConvertError;
118 #[inline]
119 fn try_from(value: $int) -> Result<Self, Self::Error> {
120 Self::from_u64(value as u64).ok_or(ConvertError::Overflow)
121 }
122 }
123 )*
124 };
125}
126
127impl From<i32> for Decimal<i32, 0> {
136 #[inline(always)]
138 fn from(value: i32) -> Self {
139 Self { value }
140 }
141}
142
143impl From<i64> for Decimal<i64, 0> {
144 #[inline(always)]
146 fn from(value: i64) -> Self {
147 Self { value }
148 }
149}
150
151impl From<i128> for Decimal<i128, 0> {
152 #[inline(always)]
154 fn from(value: i128) -> Self {
155 Self { value }
156 }
157}
158
159impl_from_sound!(i32, 0, [i8, i16, u8, u16]);
161impl_try_from_int!(i32, 0, signed: [i64]);
162impl_try_from_int!(i32, 0, unsigned: [u64]);
163impl_from_sound!(i32, 1, [i8, i16, u8, u16]);
164impl_try_from_int!(i32, 1, signed: [i64]);
165impl_try_from_int!(i32, 1, unsigned: [u64]);
166impl_from_sound!(i32, 2, [i8, i16, u8, u16]);
167impl_try_from_int!(i32, 2, signed: [i64]);
168impl_try_from_int!(i32, 2, unsigned: [u64]);
169impl_from_sound!(i32, 3, [i8, i16, u8, u16]);
170impl_try_from_int!(i32, 3, signed: [i64]);
171impl_try_from_int!(i32, 3, unsigned: [u64]);
172impl_from_sound!(i32, 4, [i8, i16, u8, u16]);
173impl_try_from_int!(i32, 4, signed: [i64]);
174impl_try_from_int!(i32, 4, unsigned: [u64]);
175impl_from_sound!(i32, 5, [i8, u8]);
176impl_try_from_int!(i32, 5, signed: [i64]);
177impl_try_from_int!(i32, 5, unsigned: [u64]);
178impl_from_sound!(i32, 6, [i8, u8]);
179impl_try_from_int!(i32, 6, signed: [i64]);
180impl_try_from_int!(i32, 6, unsigned: [u64]);
181impl_from_sound!(i32, 7, [i8]);
182impl_try_from_int!(i32, 7, signed: [i64]);
183impl_try_from_int!(i32, 7, unsigned: [u64]);
184impl_try_from_int!(i32, 8, signed: [i64]);
185impl_try_from_int!(i32, 8, unsigned: [u64]);
186impl_try_from_int!(i32, 9, signed: [i64]);
187impl_try_from_int!(i32, 9, unsigned: [u64]);
188
189impl_from_sound!(i64, 0, [i8, i16, i32, u8, u16, u32]);
191impl_try_from_int!(i64, 0, unsigned: [u64]);
195impl_from_sound!(i64, 1, [i8, i16, i32, u8, u16, u32]);
196impl_try_from_int!(i64, 1, signed: [i64]);
197impl_try_from_int!(i64, 1, unsigned: [u64]);
198impl_from_sound!(i64, 2, [i8, i16, i32, u8, u16, u32]);
199impl_try_from_int!(i64, 2, signed: [i64]);
200impl_try_from_int!(i64, 2, unsigned: [u64]);
201impl_from_sound!(i64, 3, [i8, i16, i32, u8, u16, u32]);
202impl_try_from_int!(i64, 3, signed: [i64]);
203impl_try_from_int!(i64, 3, unsigned: [u64]);
204impl_from_sound!(i64, 4, [i8, i16, i32, u8, u16, u32]);
205impl_try_from_int!(i64, 4, signed: [i64]);
206impl_try_from_int!(i64, 4, unsigned: [u64]);
207impl_from_sound!(i64, 5, [i8, i16, i32, u8, u16, u32]);
208impl_try_from_int!(i64, 5, signed: [i64]);
209impl_try_from_int!(i64, 5, unsigned: [u64]);
210impl_from_sound!(i64, 6, [i8, i16, i32, u8, u16, u32]);
211impl_try_from_int!(i64, 6, signed: [i64]);
212impl_try_from_int!(i64, 6, unsigned: [u64]);
213impl_from_sound!(i64, 7, [i8, i16, i32, u8, u16, u32]);
214impl_try_from_int!(i64, 7, signed: [i64]);
215impl_try_from_int!(i64, 7, unsigned: [u64]);
216impl_from_sound!(i64, 8, [i8, i16, i32, u8, u16, u32]);
217impl_try_from_int!(i64, 8, signed: [i64]);
218impl_try_from_int!(i64, 8, unsigned: [u64]);
219impl_from_sound!(i64, 9, [i8, i16, i32, u8, u16, u32]);
220impl_try_from_int!(i64, 9, signed: [i64]);
221impl_try_from_int!(i64, 9, unsigned: [u64]);
222impl_from_sound!(i64, 10, [i8, i16, u8, u16]);
223impl_try_from_int!(i64, 10, signed: [i64]);
224impl_try_from_int!(i64, 10, unsigned: [u64]);
225impl_from_sound!(i64, 11, [i8, i16, u8, u16]);
226impl_try_from_int!(i64, 11, signed: [i64]);
227impl_try_from_int!(i64, 11, unsigned: [u64]);
228impl_from_sound!(i64, 12, [i8, i16, u8, u16]);
229impl_try_from_int!(i64, 12, signed: [i64]);
230impl_try_from_int!(i64, 12, unsigned: [u64]);
231impl_from_sound!(i64, 13, [i8, i16, u8, u16]);
232impl_try_from_int!(i64, 13, signed: [i64]);
233impl_try_from_int!(i64, 13, unsigned: [u64]);
234impl_from_sound!(i64, 14, [i8, i16, u8, u16]);
235impl_try_from_int!(i64, 14, signed: [i64]);
236impl_try_from_int!(i64, 14, unsigned: [u64]);
237impl_from_sound!(i64, 15, [i8, u8]);
238impl_try_from_int!(i64, 15, signed: [i64]);
239impl_try_from_int!(i64, 15, unsigned: [u64]);
240impl_from_sound!(i64, 16, [i8, u8]);
241impl_try_from_int!(i64, 16, signed: [i64]);
242impl_try_from_int!(i64, 16, unsigned: [u64]);
243impl_try_from_int!(i64, 17, signed: [i64]);
244impl_try_from_int!(i64, 17, unsigned: [u64]);
245impl_try_from_int!(i64, 18, signed: [i64]);
246impl_try_from_int!(i64, 18, unsigned: [u64]);
247
248impl_from_sound!(i128, 0, [i8, i16, i32, i64, u8, u16, u32, u64]);
250impl_from_sound!(i128, 1, [i8, i16, i32, i64, u8, u16, u32, u64]);
251impl_from_sound!(i128, 2, [i8, i16, i32, i64, u8, u16, u32, u64]);
252impl_from_sound!(i128, 3, [i8, i16, i32, i64, u8, u16, u32, u64]);
253impl_from_sound!(i128, 4, [i8, i16, i32, i64, u8, u16, u32, u64]);
254impl_from_sound!(i128, 5, [i8, i16, i32, i64, u8, u16, u32, u64]);
255impl_from_sound!(i128, 6, [i8, i16, i32, i64, u8, u16, u32, u64]);
256impl_from_sound!(i128, 7, [i8, i16, i32, i64, u8, u16, u32, u64]);
257impl_from_sound!(i128, 8, [i8, i16, i32, i64, u8, u16, u32, u64]);
258impl_from_sound!(i128, 9, [i8, i16, i32, i64, u8, u16, u32, u64]);
259impl_from_sound!(i128, 10, [i8, i16, i32, i64, u8, u16, u32, u64]);
260impl_from_sound!(i128, 11, [i8, i16, i32, i64, u8, u16, u32, u64]);
261impl_from_sound!(i128, 12, [i8, i16, i32, i64, u8, u16, u32, u64]);
262impl_from_sound!(i128, 13, [i8, i16, i32, i64, u8, u16, u32, u64]);
263impl_from_sound!(i128, 14, [i8, i16, i32, i64, u8, u16, u32, u64]);
264impl_from_sound!(i128, 15, [i8, i16, i32, i64, u8, u16, u32, u64]);
265impl_from_sound!(i128, 16, [i8, i16, i32, i64, u8, u16, u32, u64]);
266impl_from_sound!(i128, 17, [i8, i16, i32, i64, u8, u16, u32, u64]);
267impl_from_sound!(i128, 18, [i8, i16, i32, i64, u8, u16, u32, u64]);
268impl_from_sound!(i128, 19, [i8, i16, i32, i64, u8, u16, u32]);
269impl_try_from_int!(i128, 19, unsigned: [u64]);
270impl_from_sound!(i128, 20, [i8, i16, i32, u8, u16, u32]);
271impl_try_from_int!(i128, 20, signed: [i64]);
272impl_try_from_int!(i128, 20, unsigned: [u64]);
273impl_from_sound!(i128, 21, [i8, i16, i32, u8, u16, u32]);
274impl_try_from_int!(i128, 21, signed: [i64]);
275impl_try_from_int!(i128, 21, unsigned: [u64]);
276impl_from_sound!(i128, 22, [i8, i16, i32, u8, u16, u32]);
277impl_try_from_int!(i128, 22, signed: [i64]);
278impl_try_from_int!(i128, 22, unsigned: [u64]);
279impl_from_sound!(i128, 23, [i8, i16, i32, u8, u16, u32]);
280impl_try_from_int!(i128, 23, signed: [i64]);
281impl_try_from_int!(i128, 23, unsigned: [u64]);
282impl_from_sound!(i128, 24, [i8, i16, i32, u8, u16, u32]);
283impl_try_from_int!(i128, 24, signed: [i64]);
284impl_try_from_int!(i128, 24, unsigned: [u64]);
285impl_from_sound!(i128, 25, [i8, i16, i32, u8, u16, u32]);
286impl_try_from_int!(i128, 25, signed: [i64]);
287impl_try_from_int!(i128, 25, unsigned: [u64]);
288impl_from_sound!(i128, 26, [i8, i16, i32, u8, u16, u32]);
289impl_try_from_int!(i128, 26, signed: [i64]);
290impl_try_from_int!(i128, 26, unsigned: [u64]);
291impl_from_sound!(i128, 27, [i8, i16, i32, u8, u16, u32]);
292impl_try_from_int!(i128, 27, signed: [i64]);
293impl_try_from_int!(i128, 27, unsigned: [u64]);
294impl_from_sound!(i128, 28, [i8, i16, i32, u8, u16, u32]);
295impl_try_from_int!(i128, 28, signed: [i64]);
296impl_try_from_int!(i128, 28, unsigned: [u64]);
297impl_from_sound!(i128, 29, [i8, i16, u8, u16]);
298impl_try_from_int!(i128, 29, signed: [i64]);
299impl_try_from_int!(i128, 29, unsigned: [u64]);
300impl_from_sound!(i128, 30, [i8, i16, u8, u16]);
301impl_try_from_int!(i128, 30, signed: [i64]);
302impl_try_from_int!(i128, 30, unsigned: [u64]);
303impl_from_sound!(i128, 31, [i8, i16, u8, u16]);
304impl_try_from_int!(i128, 31, signed: [i64]);
305impl_try_from_int!(i128, 31, unsigned: [u64]);
306impl_from_sound!(i128, 32, [i8, i16, u8, u16]);
307impl_try_from_int!(i128, 32, signed: [i64]);
308impl_try_from_int!(i128, 32, unsigned: [u64]);
309impl_from_sound!(i128, 33, [i8, i16, u8, u16]);
310impl_try_from_int!(i128, 33, signed: [i64]);
311impl_try_from_int!(i128, 33, unsigned: [u64]);
312impl_from_sound!(i128, 34, [i8, u8]);
313impl_try_from_int!(i128, 34, signed: [i64]);
314impl_try_from_int!(i128, 34, unsigned: [u64]);
315impl_from_sound!(i128, 35, [i8, u8]);
316impl_try_from_int!(i128, 35, signed: [i64]);
317impl_try_from_int!(i128, 35, unsigned: [u64]);
318impl_from_sound!(i128, 36, [i8]);
319impl_try_from_int!(i128, 36, signed: [i64]);
320impl_try_from_int!(i128, 36, unsigned: [u64]);
321impl_try_from_int!(i128, 37, signed: [i64]);
322impl_try_from_int!(i128, 37, unsigned: [u64]);
323impl_try_from_int!(i128, 38, signed: [i64]);
324impl_try_from_int!(i128, 38, unsigned: [u64]);