checked_rs_macro_impl/params/
number_value.rs

1use num_format::{Buffer, CustomFormat, Grouping};
2use proc_macro2::TokenStream;
3use quote::ToTokens;
4use syn::{parse_quote, spanned::Spanned};
5
6use super::{NumberArg, NumberKind};
7
8#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub enum NumberValue {
10    U8(u8),
11    U16(u16),
12    U32(u32),
13    U64(u64),
14    U128(u128),
15    USize(usize),
16    I8(i8),
17    I16(i16),
18    I32(i32),
19    I64(i64),
20    I128(i128),
21    ISize(isize),
22}
23
24impl From<u8> for NumberValue {
25    fn from(n: u8) -> Self {
26        Self::U8(n)
27    }
28}
29
30impl From<u16> for NumberValue {
31    fn from(n: u16) -> Self {
32        Self::U16(n)
33    }
34}
35
36impl From<u32> for NumberValue {
37    fn from(n: u32) -> Self {
38        Self::U32(n)
39    }
40}
41
42impl From<u64> for NumberValue {
43    fn from(n: u64) -> Self {
44        Self::U64(n)
45    }
46}
47
48impl From<u128> for NumberValue {
49    fn from(n: u128) -> Self {
50        Self::U128(n)
51    }
52}
53
54impl From<usize> for NumberValue {
55    fn from(n: usize) -> Self {
56        Self::USize(n)
57    }
58}
59
60impl From<i8> for NumberValue {
61    fn from(n: i8) -> Self {
62        Self::I8(n)
63    }
64}
65
66impl From<i16> for NumberValue {
67    fn from(n: i16) -> Self {
68        Self::I16(n)
69    }
70}
71
72impl From<i32> for NumberValue {
73    fn from(n: i32) -> Self {
74        Self::I32(n)
75    }
76}
77
78impl From<i64> for NumberValue {
79    fn from(n: i64) -> Self {
80        Self::I64(n)
81    }
82}
83
84impl From<i128> for NumberValue {
85    fn from(n: i128) -> Self {
86        Self::I128(n)
87    }
88}
89
90impl From<isize> for NumberValue {
91    fn from(n: isize) -> Self {
92        Self::ISize(n)
93    }
94}
95
96impl std::ops::RangeBounds<NumberValue> for NumberValue {
97    fn start_bound(&self) -> std::ops::Bound<&NumberValue> {
98        std::ops::Bound::Included(self)
99    }
100
101    fn end_bound(&self) -> std::ops::Bound<&NumberValue> {
102        std::ops::Bound::Excluded(self)
103    }
104}
105
106impl std::fmt::Debug for NumberValue {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        match self {
109            Self::U8(n) => write!(f, "{}", n),
110            Self::U16(n) => write!(f, "{}", n),
111            Self::U32(n) => write!(f, "{}", n),
112            Self::U64(n) => write!(f, "{}", n),
113            Self::U128(n) => write!(f, "{}", n),
114            Self::USize(n) => write!(f, "{}", n),
115            Self::I8(n) => write!(f, "{}", n),
116            Self::I16(n) => write!(f, "{}", n),
117            Self::I32(n) => write!(f, "{}", n),
118            Self::I64(n) => write!(f, "{}", n),
119            Self::I128(n) => write!(f, "{}", n),
120            Self::ISize(n) => write!(f, "{}", n),
121        }
122    }
123}
124
125impl From<NumberValue> for NumberKind {
126    fn from(value: NumberValue) -> Self {
127        value.kind()
128    }
129}
130
131impl From<&NumberValue> for NumberKind {
132    fn from(value: &NumberValue) -> Self {
133        value.kind()
134    }
135}
136
137impl std::fmt::Display for NumberValue {
138    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139        match self {
140            Self::U8(n) => write!(f, "{}", n),
141            Self::U16(n) => write!(f, "{}", n),
142            Self::U32(n) => write!(f, "{}", n),
143            Self::U64(n) => write!(f, "{}", n),
144            Self::U128(n) => write!(f, "{}", n),
145            Self::USize(n) => write!(f, "{}", n),
146            Self::I8(n) => write!(f, "{}", n),
147            Self::I16(n) => write!(f, "{}", n),
148            Self::I32(n) => write!(f, "{}", n),
149            Self::I64(n) => write!(f, "{}", n),
150            Self::I128(n) => write!(f, "{}", n),
151            Self::ISize(n) => write!(f, "{}", n),
152        }
153    }
154}
155
156impl ToTokens for NumberValue {
157    fn to_tokens(&self, tokens: &mut TokenStream) {
158        match self {
159            Self::U8(n) => n.to_tokens(tokens),
160            Self::U16(n) => n.to_tokens(tokens),
161            Self::U32(n) => n.to_tokens(tokens),
162            Self::U64(n) => n.to_tokens(tokens),
163            Self::U128(n) => n.to_tokens(tokens),
164            Self::USize(n) => n.to_tokens(tokens),
165            Self::I8(n) => n.to_tokens(tokens),
166            Self::I16(n) => n.to_tokens(tokens),
167            Self::I32(n) => n.to_tokens(tokens),
168            Self::I64(n) => n.to_tokens(tokens),
169            Self::I128(n) => n.to_tokens(tokens),
170            Self::ISize(n) => n.to_tokens(tokens),
171        }
172    }
173}
174
175impl NumberValue {
176    pub fn kind(&self) -> NumberKind {
177        match self {
178            Self::U8(..) => NumberKind::U8,
179            Self::U16(..) => NumberKind::U16,
180            Self::U32(..) => NumberKind::U32,
181            Self::U64(..) => NumberKind::U64,
182            Self::U128(..) => NumberKind::U128,
183            Self::USize(..) => NumberKind::USize,
184            Self::I8(..) => NumberKind::I8,
185            Self::I16(..) => NumberKind::I16,
186            Self::I32(..) => NumberKind::I32,
187            Self::I64(..) => NumberKind::I64,
188            Self::I128(..) => NumberKind::I128,
189            Self::ISize(..) => NumberKind::ISize,
190        }
191    }
192
193    pub fn new(kind: NumberKind, n: i128) -> Self {
194        match kind {
195            NumberKind::U8 => Self::U8(n as u8),
196            NumberKind::U16 => Self::U16(n as u16),
197            NumberKind::U32 => Self::U32(n as u32),
198            NumberKind::U64 => Self::U64(n as u64),
199            NumberKind::U128 => Self::U128(n as u128),
200            NumberKind::USize => Self::USize(n as usize),
201            NumberKind::I8 => Self::I8(n as i8),
202            NumberKind::I16 => Self::I16(n as i16),
203            NumberKind::I32 => Self::I32(n as i32),
204            NumberKind::I64 => Self::I64(n as i64),
205            NumberKind::I128 => Self::I128(n as i128),
206            NumberKind::ISize => Self::ISize(n as isize),
207        }
208    }
209
210    pub fn into_usize(self) -> usize {
211        match self {
212            Self::U8(n) => n as usize,
213            Self::U16(n) => n as usize,
214            Self::U32(n) => n as usize,
215            Self::U64(n) => n as usize,
216            Self::U128(n) => n as usize,
217            Self::USize(n) => n,
218            Self::I8(n) => n as usize,
219            Self::I16(n) => n as usize,
220            Self::I32(n) => n as usize,
221            Self::I64(n) => n as usize,
222            Self::I128(n) => n as usize,
223            Self::ISize(n) => n as usize,
224        }
225    }
226
227    pub fn into_i128(self) -> i128 {
228        match self {
229            Self::U8(n) => n as i128,
230            Self::U16(n) => n as i128,
231            Self::U32(n) => n as i128,
232            Self::U64(n) => n as i128,
233            Self::U128(n) => n as i128,
234            Self::USize(n) => n as i128,
235            Self::I8(n) => n as i128,
236            Self::I16(n) => n as i128,
237            Self::I32(n) => n as i128,
238            Self::I64(n) => n as i128,
239            Self::I128(n) => n,
240            Self::ISize(n) => n as i128,
241        }
242    }
243
244    pub fn iter_to(self, end: Self) -> impl Iterator<Item = Self> {
245        let kind = self.kind();
246        let start = self.into_i128();
247        let end = end.into_i128();
248
249        (start..end).map(move |n| Self::new(kind, n))
250    }
251
252    pub fn is_zero(&self) -> bool {
253        match self {
254            Self::U8(n) => *n == 0,
255            Self::U16(n) => *n == 0,
256            Self::U32(n) => *n == 0,
257            Self::U64(n) => *n == 0,
258            Self::U128(n) => *n == 0,
259            Self::USize(n) => *n == 0,
260            Self::I8(n) => *n == 0,
261            Self::I16(n) => *n == 0,
262            Self::I32(n) => *n == 0,
263            Self::I64(n) => *n == 0,
264            Self::I128(n) => *n == 0,
265            Self::ISize(n) => *n == 0,
266        }
267    }
268
269    pub fn is_positive(&self) -> bool {
270        match self {
271            Self::U8(n) => *n > 0,
272            Self::U16(n) => *n > 0,
273            Self::U32(n) => *n > 0,
274            Self::U64(n) => *n > 0,
275            Self::U128(n) => *n > 0,
276            Self::USize(n) => *n > 0,
277            Self::I8(n) => *n > 0,
278            Self::I16(n) => *n > 0,
279            Self::I32(n) => *n > 0,
280            Self::I64(n) => *n > 0,
281            Self::I128(n) => *n > 0,
282            Self::ISize(n) => *n > 0,
283        }
284    }
285
286    pub fn abs(&self) -> Self {
287        match self {
288            Self::U8(n) => Self::U8(*n),
289            Self::U16(n) => Self::U16(*n),
290            Self::U32(n) => Self::U32(*n),
291            Self::U64(n) => Self::U64(*n),
292            Self::U128(n) => Self::U128(*n),
293            Self::USize(n) => Self::USize(*n),
294            Self::I8(n) => Self::I8(n.abs()),
295            Self::I16(n) => Self::I16(n.abs()),
296            Self::I32(n) => Self::I32(n.abs()),
297            Self::I64(n) => Self::I64(n.abs()),
298            Self::I128(n) => Self::I128(n.abs()),
299            Self::ISize(n) => Self::ISize(n.abs()),
300        }
301    }
302
303    pub fn into_separated_string(&self) -> String {
304        let format = CustomFormat::builder()
305            .grouping(Grouping::Standard)
306            .separator("_")
307            .build()
308            .expect("valid format");
309
310        let mut buf = Buffer::new();
311
312        match self {
313            Self::U8(n) => buf.write_formatted(n, &format),
314            Self::U16(n) => buf.write_formatted(n, &format),
315            Self::U32(n) => buf.write_formatted(n, &format),
316            Self::U64(n) => buf.write_formatted(n, &format),
317            Self::U128(n) => buf.write_formatted(n, &format),
318            Self::USize(n) => buf.write_formatted(n, &format),
319            Self::I8(n) => buf.write_formatted(n, &format),
320            Self::I16(n) => buf.write_formatted(n, &format),
321            Self::I32(n) => buf.write_formatted(n, &format),
322            Self::I64(n) => buf.write_formatted(n, &format),
323            Self::I128(n) => buf.write_formatted(n, &format),
324            Self::ISize(n) => buf.write_formatted(n, &format),
325        };
326
327        buf.to_string()
328    }
329
330    pub fn into_number_arg(&self) -> NumberArg {
331        parse_quote!(#self)
332    }
333
334    pub fn add(self, rhs: Self) -> syn::Result<Self> {
335        Ok(match (self, rhs) {
336            (Self::U8(a), Self::U8(b)) => Self::U8(a + b),
337            (Self::U16(a), Self::U16(b)) => Self::U16(a + b),
338            (Self::U32(a), Self::U32(b)) => Self::U32(a + b),
339            (Self::U64(a), Self::U64(b)) => Self::U64(a + b),
340            (Self::U128(a), Self::U128(b)) => Self::U128(a + b),
341            (Self::USize(a), Self::USize(b)) => Self::USize(a + b),
342            (Self::I8(a), Self::I8(b)) => Self::I8(a + b),
343            (Self::I16(a), Self::I16(b)) => Self::I16(a + b),
344            (Self::I32(a), Self::I32(b)) => Self::I32(a + b),
345            (Self::I64(a), Self::I64(b)) => Self::I64(a + b),
346            (Self::I128(a), Self::I128(b)) => Self::I128(a + b),
347            (Self::ISize(a), Self::ISize(b)) => Self::ISize(a + b),
348            _ => {
349                return Err(syn::Error::new(
350                    self.span(),
351                    format!("Invalid addition: {:?} + {:?}", self, rhs),
352                ))
353            }
354        })
355    }
356
357    pub fn add_usize(self, rhs: usize) -> Self {
358        match self {
359            Self::U8(n) => Self::U8(n + rhs as u8),
360            Self::U16(n) => Self::U16(n + rhs as u16),
361            Self::U32(n) => Self::U32(n + rhs as u32),
362            Self::U64(n) => Self::U64(n + rhs as u64),
363            Self::U128(n) => Self::U128(n + rhs as u128),
364            Self::USize(n) => Self::USize(n + rhs),
365            Self::I8(n) => Self::I8(n + rhs as i8),
366            Self::I16(n) => Self::I16(n + rhs as i16),
367            Self::I32(n) => Self::I32(n + rhs as i32),
368            Self::I64(n) => Self::I64(n + rhs as i64),
369            Self::I128(n) => Self::I128(n + rhs as i128),
370            Self::ISize(n) => Self::ISize(n + rhs as isize),
371        }
372    }
373
374    pub fn sub(self, rhs: Self) -> syn::Result<Self> {
375        Ok(match (self, rhs) {
376            (Self::U8(a), Self::U8(b)) => Self::U8(a - b),
377            (Self::U16(a), Self::U16(b)) => Self::U16(a - b),
378            (Self::U32(a), Self::U32(b)) => Self::U32(a - b),
379            (Self::U64(a), Self::U64(b)) => Self::U64(a - b),
380            (Self::U128(a), Self::U128(b)) => Self::U128(a - b),
381            (Self::USize(a), Self::USize(b)) => Self::USize(a - b),
382            (Self::I8(a), Self::I8(b)) => Self::I8(a - b),
383            (Self::I16(a), Self::I16(b)) => Self::I16(a - b),
384            (Self::I32(a), Self::I32(b)) => Self::I32(a - b),
385            (Self::I64(a), Self::I64(b)) => Self::I64(a - b),
386            (Self::I128(a), Self::I128(b)) => Self::I128(a - b),
387            (Self::ISize(a), Self::ISize(b)) => Self::ISize(a - b),
388            _ => {
389                return Err(syn::Error::new(
390                    self.span(),
391                    format!("Invalid subtraction: {:?} - {:?}", self, rhs),
392                ))
393            }
394        })
395    }
396
397    pub fn sub_usize(self, rhs: usize) -> Self {
398        match self {
399            Self::U8(n) => Self::U8(n - rhs as u8),
400            Self::U16(n) => Self::U16(n - rhs as u16),
401            Self::U32(n) => Self::U32(n - rhs as u32),
402            Self::U64(n) => Self::U64(n - rhs as u64),
403            Self::U128(n) => Self::U128(n - rhs as u128),
404            Self::USize(n) => Self::USize(n - rhs),
405            Self::I8(n) => Self::I8(n - rhs as i8),
406            Self::I16(n) => Self::I16(n - rhs as i16),
407            Self::I32(n) => Self::I32(n - rhs as i32),
408            Self::I64(n) => Self::I64(n - rhs as i64),
409            Self::I128(n) => Self::I128(n - rhs as i128),
410            Self::ISize(n) => Self::ISize(n - rhs as isize),
411        }
412    }
413}