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}