1use std::{any::TypeId, borrow::Cow, mem, num, num::IntErrorKind, ptr, str::FromStr};
5
6use crate::{
7 error::{Error, TypeError},
8 fragment::Fragment,
9 value::{
10 int::{Int, parse::parse_int},
11 is::{IsFloat, IsInt, IsUint},
12 uint::{Uint, parse::parse_uint},
13 value_type::ValueType,
14 },
15};
16
17pub fn parse_primitive_int<T>(fragment: Fragment) -> Result<T, Error>
18where
19 T: IsInt + 'static,
20{
21 if TypeId::of::<T>() == TypeId::of::<i8>() {
22 Ok(cast::<T, i8>(parse_i8(fragment)?))
23 } else if TypeId::of::<T>() == TypeId::of::<i16>() {
24 Ok(cast::<T, i16>(parse_i16(fragment)?))
25 } else if TypeId::of::<T>() == TypeId::of::<i32>() {
26 Ok(cast::<T, i32>(parse_i32(fragment)?))
27 } else if TypeId::of::<T>() == TypeId::of::<i64>() {
28 Ok(cast::<T, i64>(parse_i64(fragment)?))
29 } else if TypeId::of::<T>() == TypeId::of::<i128>() {
30 Ok(cast::<T, i128>(parse_i128(fragment)?))
31 } else if TypeId::of::<T>() == TypeId::of::<Int>() {
32 Ok(cast::<T, Int>(parse_int(fragment)?))
33 } else {
34 unreachable!();
35 }
36}
37
38pub fn parse_primitive_uint<T>(fragment: Fragment) -> Result<T, Error>
39where
40 T: IsUint + 'static,
41{
42 if TypeId::of::<T>() == TypeId::of::<u8>() {
43 Ok(cast::<T, u8>(parse_u8(fragment)?))
44 } else if TypeId::of::<T>() == TypeId::of::<u16>() {
45 Ok(cast::<T, u16>(parse_u16(fragment)?))
46 } else if TypeId::of::<T>() == TypeId::of::<u32>() {
47 Ok(cast::<T, u32>(parse_u32(fragment)?))
48 } else if TypeId::of::<T>() == TypeId::of::<u64>() {
49 Ok(cast::<T, u64>(parse_u64(fragment)?))
50 } else if TypeId::of::<T>() == TypeId::of::<u128>() {
51 Ok(cast::<T, u128>(parse_u128(fragment)?))
52 } else if TypeId::of::<T>() == TypeId::of::<Uint>() {
53 Ok(cast::<T, Uint>(parse_uint(fragment)?))
54 } else {
55 unreachable!();
56 }
57}
58
59pub fn parse_float<T>(fragment: Fragment) -> Result<T, Error>
60where
61 T: IsFloat + 'static,
62{
63 if fragment.text().to_lowercase().contains("nan") {
64 return Err(TypeError::NanNotAllowed.into());
65 }
66
67 if TypeId::of::<T>() == TypeId::of::<f32>() {
68 Ok(cast::<T, f32>(parse_f32(fragment.clone())?))
69 } else if TypeId::of::<T>() == TypeId::of::<f64>() {
70 Ok(cast::<T, f64>(parse_f64(fragment)?))
71 } else {
72 unreachable!();
73 }
74}
75
76fn cast_float_to_int<T: 'static>(f: f64) -> T {
77 if TypeId::of::<T>() == TypeId::of::<i8>() {
78 cast::<T, i8>(f as i8)
79 } else if TypeId::of::<T>() == TypeId::of::<i16>() {
80 cast::<T, i16>(f as i16)
81 } else if TypeId::of::<T>() == TypeId::of::<i32>() {
82 cast::<T, i32>(f as i32)
83 } else if TypeId::of::<T>() == TypeId::of::<i64>() {
84 cast::<T, i64>(f as i64)
85 } else if TypeId::of::<T>() == TypeId::of::<i128>() {
86 cast::<T, i128>(f as i128)
87 } else if TypeId::of::<T>() == TypeId::of::<u8>() {
88 cast::<T, u8>(f as u8)
89 } else if TypeId::of::<T>() == TypeId::of::<u16>() {
90 cast::<T, u16>(f as u16)
91 } else if TypeId::of::<T>() == TypeId::of::<u32>() {
92 cast::<T, u32>(f as u32)
93 } else if TypeId::of::<T>() == TypeId::of::<u64>() {
94 cast::<T, u64>(f as u64)
95 } else if TypeId::of::<T>() == TypeId::of::<u128>() {
96 cast::<T, u128>(f as u128)
97 } else {
98 unreachable!()
99 }
100}
101
102fn cast<T: 'static, U: 'static>(v: U) -> T {
103 assert_eq!(TypeId::of::<T>(), TypeId::of::<U>());
104
105 let v = mem::ManuallyDrop::new(v);
106 unsafe { ptr::read(&*v as *const U as *const T) }
109}
110
111trait TypeInfo {
112 fn type_enum() -> ValueType;
113}
114
115impl TypeInfo for i8 {
116 fn type_enum() -> ValueType {
117 ValueType::Int1
118 }
119}
120impl TypeInfo for i16 {
121 fn type_enum() -> ValueType {
122 ValueType::Int2
123 }
124}
125impl TypeInfo for i32 {
126 fn type_enum() -> ValueType {
127 ValueType::Int4
128 }
129}
130impl TypeInfo for i64 {
131 fn type_enum() -> ValueType {
132 ValueType::Int8
133 }
134}
135impl TypeInfo for i128 {
136 fn type_enum() -> ValueType {
137 ValueType::Int16
138 }
139}
140impl TypeInfo for u8 {
141 fn type_enum() -> ValueType {
142 ValueType::Uint1
143 }
144}
145impl TypeInfo for u16 {
146 fn type_enum() -> ValueType {
147 ValueType::Uint2
148 }
149}
150impl TypeInfo for u32 {
151 fn type_enum() -> ValueType {
152 ValueType::Uint4
153 }
154}
155impl TypeInfo for u64 {
156 fn type_enum() -> ValueType {
157 ValueType::Uint8
158 }
159}
160impl TypeInfo for u128 {
161 fn type_enum() -> ValueType {
162 ValueType::Uint16
163 }
164}
165impl TypeInfo for f32 {
166 fn type_enum() -> ValueType {
167 ValueType::Float4
168 }
169}
170impl TypeInfo for f64 {
171 fn type_enum() -> ValueType {
172 ValueType::Float8
173 }
174}
175
176#[inline]
177fn parse_signed_generic<T>(fragment: Fragment) -> Result<T, Error>
178where
179 T: FromStr<Err = num::ParseIntError> + TypeInfo + 'static,
180{
181 let raw_value = fragment.text();
182
183 let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
184 || raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
185 let has_underscores = raw_value.as_bytes().contains(&b'_');
186
187 let value = match (needs_trimming, has_underscores) {
188 (false, false) => Cow::Borrowed(raw_value),
189
190 (true, false) => Cow::Borrowed(raw_value.trim()),
191 (false, true) => Cow::Owned(raw_value.replace('_', "")),
192 (true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
193 };
194
195 if value.is_empty() {
196 return Err(TypeError::InvalidNumberFormat {
197 target: T::type_enum(),
198 fragment,
199 }
200 .into());
201 }
202
203 match value.parse::<T>() {
204 Ok(v) => Ok(v),
205 Err(err) => match err.kind() {
206 IntErrorKind::Empty => Err(TypeError::InvalidNumberFormat {
207 target: T::type_enum(),
208 fragment,
209 }
210 .into()),
211 IntErrorKind::InvalidDigit => {
212 if let Ok(f) = value.parse::<f64>() {
213 let truncated = f.trunc();
214 let type_enum = T::type_enum();
215 let in_range = match type_enum {
216 ValueType::Int1 => {
217 truncated >= i8::MIN as f64 && truncated <= i8::MAX as f64
218 }
219 ValueType::Int2 => {
220 truncated >= i16::MIN as f64 && truncated <= i16::MAX as f64
221 }
222 ValueType::Int4 => {
223 truncated >= i32::MIN as f64 && truncated <= i32::MAX as f64
224 }
225 ValueType::Int8 => {
226 truncated >= i64::MIN as f64 && truncated <= i64::MAX as f64
227 }
228 ValueType::Int16 => {
229 truncated >= i128::MIN as f64 && truncated <= i128::MAX as f64
230 }
231 _ => false,
232 };
233 if in_range {
234 Ok(cast_float_to_int::<T>(truncated))
235 } else {
236 Err(TypeError::NumberOutOfRange {
237 target: type_enum,
238 fragment,
239 descriptor: None,
240 }
241 .into())
242 }
243 } else {
244 Err(TypeError::InvalidNumberFormat {
245 target: T::type_enum(),
246 fragment,
247 }
248 .into())
249 }
250 }
251 IntErrorKind::PosOverflow => Err(TypeError::NumberOutOfRange {
252 target: T::type_enum(),
253 fragment,
254 descriptor: None,
255 }
256 .into()),
257 IntErrorKind::NegOverflow => Err(TypeError::NumberOutOfRange {
258 target: T::type_enum(),
259 fragment,
260 descriptor: None,
261 }
262 .into()),
263 IntErrorKind::Zero => Err(TypeError::InvalidNumberFormat {
264 target: T::type_enum(),
265 fragment,
266 }
267 .into()),
268 &_ => unreachable!("{}", err),
269 },
270 }
271}
272
273#[inline]
274fn parse_unsigned_generic<T>(fragment: Fragment) -> Result<T, Error>
275where
276 T: FromStr<Err = num::ParseIntError> + TypeInfo + 'static,
277{
278 let raw_value = fragment.text();
279
280 let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
281 || raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
282 let has_underscores = raw_value.as_bytes().contains(&b'_');
283
284 let value = match (needs_trimming, has_underscores) {
285 (false, false) => Cow::Borrowed(raw_value),
286
287 (true, false) => Cow::Borrowed(raw_value.trim()),
288 (false, true) => Cow::Owned(raw_value.replace('_', "")),
289 (true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
290 };
291
292 if value.is_empty() {
293 return Err(TypeError::InvalidNumberFormat {
294 target: T::type_enum(),
295 fragment,
296 }
297 .into());
298 }
299
300 match value.parse::<T>() {
301 Ok(v) => Ok(v),
302 Err(err) => match err.kind() {
303 IntErrorKind::Empty => Err(TypeError::InvalidNumberFormat {
304 target: T::type_enum(),
305 fragment,
306 }
307 .into()),
308 IntErrorKind::InvalidDigit => {
309 if let Ok(f) = value.parse::<f64>() {
310 if f < 0.0 {
311 return Err(TypeError::NumberOutOfRange {
312 target: T::type_enum(),
313 fragment,
314 descriptor: None,
315 }
316 .into());
317 }
318 let truncated = f.trunc();
319 let type_enum = T::type_enum();
320 let in_range = match type_enum {
321 ValueType::Uint1 => truncated >= 0.0 && truncated <= u8::MAX as f64,
322 ValueType::Uint2 => truncated >= 0.0 && truncated <= u16::MAX as f64,
323 ValueType::Uint4 => truncated >= 0.0 && truncated <= u32::MAX as f64,
324 ValueType::Uint8 => truncated >= 0.0 && truncated <= u64::MAX as f64,
325 ValueType::Uint16 => truncated >= 0.0 && truncated <= u128::MAX as f64,
326 _ => false,
327 };
328 if in_range {
329 Ok(cast_float_to_int::<T>(truncated))
330 } else {
331 Err(TypeError::NumberOutOfRange {
332 target: type_enum,
333 fragment,
334 descriptor: None,
335 }
336 .into())
337 }
338 } else if value.contains("-") {
339 Err(TypeError::NumberOutOfRange {
340 target: T::type_enum(),
341 fragment,
342 descriptor: None,
343 }
344 .into())
345 } else {
346 Err(TypeError::InvalidNumberFormat {
347 target: T::type_enum(),
348 fragment,
349 }
350 .into())
351 }
352 }
353 IntErrorKind::PosOverflow => Err(TypeError::NumberOutOfRange {
354 target: T::type_enum(),
355 fragment,
356 descriptor: None,
357 }
358 .into()),
359 IntErrorKind::NegOverflow => Err(TypeError::NumberOutOfRange {
360 target: T::type_enum(),
361 fragment,
362 descriptor: None,
363 }
364 .into()),
365 IntErrorKind::Zero => Err(TypeError::InvalidNumberFormat {
366 target: T::type_enum(),
367 fragment,
368 }
369 .into()),
370 &_ => unreachable!("{}", err),
371 },
372 }
373}
374
375#[inline]
376fn parse_float_generic<T>(fragment: Fragment) -> Result<T, Error>
377where
378 T: FromStr<Err = num::ParseFloatError> + Copy + TypeInfo + PartialEq + 'static,
379{
380 let raw_value = fragment.text();
381
382 let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
383 || raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
384 let has_underscores = raw_value.as_bytes().contains(&b'_');
385
386 let value = match (needs_trimming, has_underscores) {
387 (false, false) => Cow::Borrowed(raw_value),
388
389 (true, false) => Cow::Borrowed(raw_value.trim()),
390 (false, true) => Cow::Owned(raw_value.replace('_', "")),
391 (true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
392 };
393
394 if value.is_empty() {
395 return Err(TypeError::InvalidNumberFormat {
396 target: T::type_enum(),
397 fragment,
398 }
399 .into());
400 }
401
402 match value.parse::<T>() {
403 Ok(v) => {
404 if TypeId::of::<T>() == TypeId::of::<f32>() {
405 let v_f32 = cast::<f32, T>(v);
406 if v_f32.is_infinite() {
407 return Err(TypeError::NumberOutOfRange {
408 target: T::type_enum(),
409 fragment,
410 descriptor: None,
411 }
412 .into());
413 }
414 } else if TypeId::of::<T>() == TypeId::of::<f64>() {
415 let v_f64 = cast::<f64, T>(v);
416 if v_f64.is_infinite() {
417 return Err(TypeError::NumberOutOfRange {
418 target: T::type_enum(),
419 fragment,
420 descriptor: None,
421 }
422 .into());
423 }
424 }
425 Ok(v)
426 }
427 Err(_) => Err(TypeError::InvalidNumberFormat {
428 target: T::type_enum(),
429 fragment,
430 }
431 .into()),
432 }
433}
434
435#[inline]
436fn parse_f32(fragment: Fragment) -> Result<f32, Error> {
437 parse_float_generic::<f32>(fragment)
438}
439
440#[inline]
441fn parse_f64(fragment: Fragment) -> Result<f64, Error> {
442 parse_float_generic::<f64>(fragment)
443}
444
445#[inline]
446fn parse_i8(fragment: Fragment) -> Result<i8, Error> {
447 parse_signed_generic::<i8>(fragment)
448}
449
450#[inline]
451fn parse_i16(fragment: Fragment) -> Result<i16, Error> {
452 parse_signed_generic::<i16>(fragment)
453}
454
455#[inline]
456fn parse_i32(fragment: Fragment) -> Result<i32, Error> {
457 parse_signed_generic::<i32>(fragment)
458}
459
460#[inline]
461fn parse_i64(fragment: Fragment) -> Result<i64, Error> {
462 parse_signed_generic::<i64>(fragment)
463}
464
465#[inline]
466fn parse_i128(fragment: Fragment) -> Result<i128, Error> {
467 parse_signed_generic::<i128>(fragment)
468}
469
470#[inline]
471fn parse_u8(fragment: Fragment) -> Result<u8, Error> {
472 parse_unsigned_generic::<u8>(fragment)
473}
474
475#[inline]
476fn parse_u16(fragment: Fragment) -> Result<u16, Error> {
477 parse_unsigned_generic::<u16>(fragment)
478}
479
480#[inline]
481fn parse_u32(fragment: Fragment) -> Result<u32, Error> {
482 parse_unsigned_generic::<u32>(fragment)
483}
484
485#[inline]
486fn parse_u64(fragment: Fragment) -> Result<u64, Error> {
487 parse_unsigned_generic::<u64>(fragment)
488}
489
490#[inline]
491fn parse_u128(fragment: Fragment) -> Result<u128, Error> {
492 parse_unsigned_generic::<u128>(fragment)
493}
494
495#[cfg(test)]
496#[allow(clippy::approx_constant)]
497pub mod tests {
498
499 mod i8 {
500 use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
501
502 #[test]
503 fn test_valid_zero() {
504 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("0")), Ok(0));
505 }
506
507 #[test]
508 fn test_valid_positive() {
509 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42")), Ok(42));
510 }
511
512 #[test]
513 fn test_valid_negative() {
514 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42")), Ok(-42));
515 }
516
517 #[test]
518 fn test_valid_max() {
519 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("127")), Ok(127));
520 }
521
522 #[test]
523 fn test_valid_min() {
524 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-128")), Ok(-128));
525 }
526
527 #[test]
528 fn test_overflow_positive() {
529 assert!(parse_primitive_int::<i8>(Fragment::testing("128")).is_err());
530 }
531
532 #[test]
533 fn test_overflow_negative() {
534 assert!(parse_primitive_int::<i8>(Fragment::testing("-129")).is_err());
535 }
536
537 #[test]
538 fn test_invalid_text() {
539 assert!(parse_primitive_int::<i8>(Fragment::testing("abc")).is_err());
540 }
541
542 #[test]
543 fn test_invalid_empty() {
544 assert!(parse_primitive_int::<i8>(Fragment::testing("")).is_err());
545 }
546
547 #[test]
548 fn test_invalid_whitespace() {
549 assert!(parse_primitive_int::<i8>(Fragment::testing(" ")).is_err());
550 }
551
552 #[test]
553 fn test_float_truncation_positive() {
554 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42.9")), Ok(42));
555 }
556
557 #[test]
558 fn test_float_truncation_negative() {
559 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42.9")), Ok(-42));
560 }
561
562 #[test]
563 fn test_float_truncation_zero() {
564 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("0.0")), Ok(0));
565 }
566
567 #[test]
568 fn test_float_truncation_negative_zero() {
569 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-0.0")), Ok(0));
570 }
571
572 #[test]
573 fn test_float_truncation_max() {
574 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("127.9")), Ok(127));
575 }
576
577 #[test]
578 fn test_float_truncation_min() {
579 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-128.9")), Ok(-128));
580 }
581
582 #[test]
583 fn test_float_scientific_notation() {
584 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("1e+2")), Ok(100));
585 }
586
587 #[test]
588 fn test_float_scientific_small() {
589 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("1.23e-1")), Ok(0));
590 }
591
592 #[test]
593 fn test_float_overflow_positive() {
594 assert!(parse_primitive_int::<i8>(Fragment::testing("128.0")).is_err());
595 }
596
597 #[test]
598 fn test_float_overflow_negative() {
599 assert!(parse_primitive_int::<i8>(Fragment::testing("-129.0")).is_err());
600 }
601
602 #[test]
603 fn test_float_overflow_scientific() {
604 assert!(parse_primitive_int::<i8>(Fragment::testing("1e3")).is_err());
605 }
606
607 #[test]
608 fn test_invalid_float_format() {
609 assert!(parse_primitive_int::<i8>(Fragment::testing("1.2.3")).is_err());
610 }
611
612 #[test]
613 fn trimming_leading_space() {
614 assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" 42")), Ok(42));
615 }
616
617 #[test]
618 fn trimming_trailing_space() {
619 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42 ")), Ok(42));
620 }
621
622 #[test]
623 fn trimming_both_spaces() {
624 assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" 42 ")), Ok(42));
625 }
626
627 #[test]
628 fn trimming_negative_leading_space() {
629 assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" -42")), Ok(-42));
630 }
631
632 #[test]
633 fn trimming_negative_trailing_space() {
634 assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42 ")), Ok(-42));
635 }
636
637 #[test]
638 fn trimming_negative_both_spaces() {
639 assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" -42 ")), Ok(-42));
640 }
641 }
642
643 mod i16 {
644 use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
645
646 #[test]
647 fn test_valid_zero() {
648 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("0")), Ok(0));
649 }
650
651 #[test]
652 fn test_valid_positive() {
653 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000")), Ok(1000));
654 }
655
656 #[test]
657 fn test_valid_negative() {
658 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000")), Ok(-1000));
659 }
660
661 #[test]
662 fn test_valid_max() {
663 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("32767")), Ok(32767));
664 }
665
666 #[test]
667 fn test_valid_min() {
668 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-32768")), Ok(-32768));
669 }
670
671 #[test]
672 fn test_overflow_positive() {
673 assert!(parse_primitive_int::<i16>(Fragment::testing("32768")).is_err());
674 }
675
676 #[test]
677 fn test_overflow_negative() {
678 assert!(parse_primitive_int::<i16>(Fragment::testing("-32769")).is_err());
679 }
680
681 #[test]
682 fn test_invalid_text() {
683 assert!(parse_primitive_int::<i16>(Fragment::testing("hello")).is_err());
684 }
685
686 #[test]
687 fn test_invalid_empty() {
688 assert!(parse_primitive_int::<i16>(Fragment::testing("")).is_err());
689 }
690
691 #[test]
692 fn test_float_truncation_positive() {
693 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000.7")), Ok(1000));
694 }
695
696 #[test]
697 fn test_float_truncation_negative() {
698 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000.7")), Ok(-1000));
699 }
700
701 #[test]
702 fn test_float_truncation_max() {
703 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("32767.9")), Ok(32767));
704 }
705
706 #[test]
707 fn test_float_truncation_min() {
708 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-32768.9")), Ok(-32768));
709 }
710
711 #[test]
712 fn test_float_scientific_notation() {
713 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1.5e3")), Ok(1500));
714 }
715
716 #[test]
717 fn test_float_overflow_positive() {
718 assert!(parse_primitive_int::<i16>(Fragment::testing("32768.0")).is_err());
719 }
720
721 #[test]
722 fn test_float_overflow_negative() {
723 assert!(parse_primitive_int::<i16>(Fragment::testing("-32769.0")).is_err());
724 }
725
726 #[test]
727 fn test_float_overflow_scientific() {
728 assert!(parse_primitive_int::<i16>(Fragment::testing("1e5")).is_err());
729 }
730
731 #[test]
732 fn trimming_leading_space() {
733 assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" 1000")), Ok(1000));
734 }
735
736 #[test]
737 fn trimming_trailing_space() {
738 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000 ")), Ok(1000));
739 }
740
741 #[test]
742 fn trimming_both_spaces() {
743 assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" 1000 ")), Ok(1000));
744 }
745
746 #[test]
747 fn trimming_negative_leading_space() {
748 assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" -1000")), Ok(-1000));
749 }
750
751 #[test]
752 fn trimming_negative_trailing_space() {
753 assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000 ")), Ok(-1000));
754 }
755
756 #[test]
757 fn trimming_negative_both_spaces() {
758 assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" -1000 ")), Ok(-1000));
759 }
760 }
761
762 mod i32 {
763 use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
764
765 #[test]
766 fn test_valid_zero() {
767 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("0")), Ok(0));
768 }
769
770 #[test]
771 fn test_valid_positive() {
772 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1000000")), Ok(1000000));
773 }
774
775 #[test]
776 fn test_valid_negative() {
777 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-1000000")), Ok(-1000000));
778 }
779
780 #[test]
781 fn test_valid_max() {
782 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("2147483647")), Ok(2147483647));
783 }
784
785 #[test]
786 fn test_valid_min() {
787 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-2147483648")), Ok(-2147483648));
788 }
789
790 #[test]
791 fn test_overflow_positive() {
792 assert!(parse_primitive_int::<i32>(Fragment::testing("2147483648")).is_err());
793 }
794
795 #[test]
796 fn test_overflow_negative() {
797 assert!(parse_primitive_int::<i32>(Fragment::testing("-2147483649")).is_err());
798 }
799
800 #[test]
801 fn test_invalid_text() {
802 assert!(parse_primitive_int::<i32>(Fragment::testing("not_a_number")).is_err());
803 }
804
805 #[test]
806 fn test_invalid_empty() {
807 assert!(parse_primitive_int::<i32>(Fragment::testing("")).is_err());
808 }
809
810 #[test]
811 fn test_float_truncation_positive() {
812 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("3.14")), Ok(3));
813 }
814
815 #[test]
816 fn test_float_truncation_negative() {
817 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-3.14")), Ok(-3));
818 }
819
820 #[test]
821 fn test_float_truncation_zero() {
822 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("0.0")), Ok(0));
823 }
824
825 #[test]
826 fn test_float_truncation_negative_zero() {
827 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-0.0")), Ok(0));
828 }
829
830 #[test]
831 fn test_float_truncation_large() {
832 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("42.999")), Ok(42));
833 }
834
835 #[test]
836 fn test_float_scientific_notation() {
837 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1e+2")), Ok(100));
838 }
839
840 #[test]
841 fn test_float_scientific_decimal() {
842 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("2.5e3")), Ok(2500));
843 }
844
845 #[test]
846 fn test_float_scientific_negative() {
847 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-1.5e2")), Ok(-150));
848 }
849
850 #[test]
851 fn test_float_scientific_small() {
852 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1.23e-1")), Ok(0));
853 }
854
855 #[test]
856 fn test_float_scientific_very_small() {
857 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("9.9e-1")), Ok(0));
858 }
859
860 #[test]
861 fn test_float_overflow_positive() {
862 assert!(parse_primitive_int::<i32>(Fragment::testing("2147483648.0")).is_err());
863 }
864
865 #[test]
866 fn test_float_overflow_negative() {
867 assert!(parse_primitive_int::<i32>(Fragment::testing("-2147483649.0")).is_err());
868 }
869
870 #[test]
871 fn test_float_overflow_scientific() {
872 assert!(parse_primitive_int::<i32>(Fragment::testing("1e10")).is_err());
873 }
874
875 #[test]
876 fn test_invalid_float_format() {
877 assert!(parse_primitive_int::<i32>(Fragment::testing("1.2.3")).is_err());
878 }
879
880 #[test]
881 fn trimming_leading_space() {
882 assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" 123")), Ok(123));
883 }
884
885 #[test]
886 fn trimming_trailing_space() {
887 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("123 ")), Ok(123));
888 }
889
890 #[test]
891 fn trimming_both_spaces() {
892 assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" 123 ")), Ok(123));
893 }
894
895 #[test]
896 fn trimming_negative_leading_space() {
897 assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" -456")), Ok(-456));
898 }
899
900 #[test]
901 fn trimming_negative_trailing_space() {
902 assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-456 ")), Ok(-456));
903 }
904
905 #[test]
906 fn trimming_negative_both_spaces() {
907 assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" -456 ")), Ok(-456));
908 }
909 }
910
911 mod i64 {
912 use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
913
914 #[test]
915 fn test_valid_zero() {
916 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("0")), Ok(0));
917 }
918
919 #[test]
920 fn test_valid_positive() {
921 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1000000000")), Ok(1000000000));
922 }
923
924 #[test]
925 fn test_valid_negative() {
926 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-1000000000")), Ok(-1000000000));
927 }
928
929 #[test]
930 fn test_valid_max() {
931 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("9223372036854775807")), Ok(i64::MAX));
932 }
933
934 #[test]
935 fn test_valid_min() {
936 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-9223372036854775808")), Ok(i64::MIN));
937 }
938
939 #[test]
940 fn test_overflow_positive() {
941 assert!(parse_primitive_int::<i64>(Fragment::testing("9223372036854775808")).is_err());
942 }
943
944 #[test]
945 fn test_overflow_negative() {
946 assert!(parse_primitive_int::<i64>(Fragment::testing("-9223372036854775809")).is_err());
947 }
948
949 #[test]
950 fn test_invalid_text() {
951 assert!(parse_primitive_int::<i64>(Fragment::testing("invalid")).is_err());
952 }
953
954 #[test]
955 fn test_invalid_empty() {
956 assert!(parse_primitive_int::<i64>(Fragment::testing("")).is_err());
957 }
958
959 #[test]
960 fn test_float_truncation_positive() {
961 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("12345.67")), Ok(12345));
962 }
963
964 #[test]
965 fn test_float_truncation_negative() {
966 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-12345.67")), Ok(-12345));
967 }
968
969 #[test]
970 fn test_float_scientific_notation() {
971 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1e10")), Ok(10000000000));
972 }
973
974 #[test]
975 fn test_float_scientific_large() {
976 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("9.223e18")), Ok(9223000000000000000));
977 }
978
979 #[test]
980 fn test_float_overflow_positive() {
981 assert!(parse_primitive_int::<i64>(Fragment::testing("1e19")).is_err());
982 }
983
984 #[test]
985 fn test_float_overflow_negative() {
986 assert!(parse_primitive_int::<i64>(Fragment::testing("-1e19")).is_err());
987 }
988
989 #[test]
990 fn trimming_leading_space() {
991 assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" 1000000000")), Ok(1000000000));
992 }
993
994 #[test]
995 fn trimming_trailing_space() {
996 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1000000000 ")), Ok(1000000000));
997 }
998
999 #[test]
1000 fn trimming_both_spaces() {
1001 assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" 1000000000 ")), Ok(1000000000));
1002 }
1003
1004 #[test]
1005 fn trimming_negative_leading_space() {
1006 assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" -1000000000")), Ok(-1000000000));
1007 }
1008
1009 #[test]
1010 fn trimming_negative_trailing_space() {
1011 assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-1000000000 ")), Ok(-1000000000));
1012 }
1013
1014 #[test]
1015 fn trimming_negative_both_spaces() {
1016 assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" -1000000000 ")), Ok(-1000000000));
1017 }
1018 }
1019
1020 mod i128 {
1021 use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
1022
1023 #[test]
1024 fn test_valid_zero() {
1025 assert_eq!(parse_primitive_int::<i128>(Fragment::testing("0")), Ok(0));
1026 }
1027
1028 #[test]
1029 fn test_valid_positive() {
1030 assert_eq!(
1031 parse_primitive_int::<i128>(Fragment::testing("12345678901234567890")),
1032 Ok(12345678901234567890)
1033 );
1034 }
1035
1036 #[test]
1037 fn test_valid_negative() {
1038 assert_eq!(
1039 parse_primitive_int::<i128>(Fragment::testing("-12345678901234567890")),
1040 Ok(-12345678901234567890)
1041 );
1042 }
1043
1044 #[test]
1045 fn test_valid_max() {
1046 assert_eq!(
1047 parse_primitive_int::<i128>(Fragment::testing(&i128::MAX.to_string())),
1048 Ok(i128::MAX)
1049 );
1050 }
1051
1052 #[test]
1053 fn test_valid_min() {
1054 assert_eq!(
1055 parse_primitive_int::<i128>(Fragment::testing(&i128::MIN.to_string())),
1056 Ok(i128::MIN)
1057 );
1058 }
1059
1060 #[test]
1061 fn test_overflow_positive() {
1062 assert!(parse_primitive_int::<i128>(Fragment::testing(
1063 "170141183460469231731687303715884105728"
1064 ))
1065 .is_err());
1066 }
1067
1068 #[test]
1069 fn test_overflow_negative() {
1070 assert!(parse_primitive_int::<i128>(Fragment::testing(
1071 "-170141183460469231731687303715884105729"
1072 ))
1073 .is_err());
1074 }
1075
1076 #[test]
1077 fn test_invalid_text() {
1078 assert!(parse_primitive_int::<i128>(Fragment::testing("abc")).is_err());
1079 }
1080
1081 #[test]
1082 fn test_invalid_empty() {
1083 assert!(parse_primitive_int::<i128>(Fragment::testing("")).is_err());
1084 }
1085
1086 #[test]
1087 fn test_float_truncation_positive() {
1088 assert_eq!(parse_primitive_int::<i128>(Fragment::testing("123456789.123")), Ok(123456789));
1089 }
1090
1091 #[test]
1092 fn test_float_truncation_negative() {
1093 assert_eq!(parse_primitive_int::<i128>(Fragment::testing("-123456789.123")), Ok(-123456789));
1094 }
1095
1096 #[test]
1097 fn test_float_scientific_notation() {
1098 assert_eq!(parse_primitive_int::<i128>(Fragment::testing("1e20")), Ok(100000000000000000000));
1099 }
1100
1101 #[test]
1102 fn test_float_overflow_positive() {
1103 assert!(parse_primitive_int::<i128>(Fragment::testing("1e40")).is_err());
1104 }
1105
1106 #[test]
1107 fn test_float_overflow_negative() {
1108 assert!(parse_primitive_int::<i128>(Fragment::testing("-1e40")).is_err());
1109 }
1110
1111 #[test]
1112 fn trimming_leading_space() {
1113 assert_eq!(
1114 parse_primitive_int::<i128>(Fragment::testing(" 12345678901234567890")),
1115 Ok(12345678901234567890)
1116 );
1117 }
1118
1119 #[test]
1120 fn trimming_trailing_space() {
1121 assert_eq!(
1122 parse_primitive_int::<i128>(Fragment::testing("12345678901234567890 ")),
1123 Ok(12345678901234567890)
1124 );
1125 }
1126
1127 #[test]
1128 fn trimming_both_spaces() {
1129 assert_eq!(
1130 parse_primitive_int::<i128>(Fragment::testing(" 12345678901234567890 ")),
1131 Ok(12345678901234567890)
1132 );
1133 }
1134
1135 #[test]
1136 fn trimming_negative_leading_space() {
1137 assert_eq!(
1138 parse_primitive_int::<i128>(Fragment::testing(" -12345678901234567890")),
1139 Ok(-12345678901234567890)
1140 );
1141 }
1142
1143 #[test]
1144 fn trimming_negative_trailing_space() {
1145 assert_eq!(
1146 parse_primitive_int::<i128>(Fragment::testing("-12345678901234567890 ")),
1147 Ok(-12345678901234567890)
1148 );
1149 }
1150
1151 #[test]
1152 fn trimming_negative_both_spaces() {
1153 assert_eq!(
1154 parse_primitive_int::<i128>(Fragment::testing(" -12345678901234567890 ")),
1155 Ok(-12345678901234567890)
1156 );
1157 }
1158 }
1159
1160 mod u8 {
1161 use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
1162
1163 #[test]
1164 fn test_valid_zero() {
1165 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("0")), Ok(0));
1166 }
1167
1168 #[test]
1169 fn test_valid_positive() {
1170 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128")), Ok(128));
1171 }
1172
1173 #[test]
1174 fn test_valid_max() {
1175 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("255")), Ok(255));
1176 }
1177
1178 #[test]
1179 fn test_overflow_positive() {
1180 assert!(parse_primitive_uint::<u8>(Fragment::testing("256")).is_err());
1181 }
1182
1183 #[test]
1184 fn test_overflow_negative() {
1185 assert!(parse_primitive_uint::<u8>(Fragment::testing("-1")).is_err());
1186 }
1187
1188 #[test]
1189 fn test_invalid_text() {
1190 assert!(parse_primitive_uint::<u8>(Fragment::testing("abc")).is_err());
1191 }
1192
1193 #[test]
1194 fn test_invalid_empty() {
1195 assert!(parse_primitive_uint::<u8>(Fragment::testing("")).is_err());
1196 }
1197
1198 #[test]
1199 fn test_float_truncation_positive() {
1200 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128.9")), Ok(128));
1201 }
1202
1203 #[test]
1204 fn test_float_truncation_zero() {
1205 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("0.0")), Ok(0));
1206 }
1207
1208 #[test]
1209 fn test_float_truncation_max() {
1210 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("255.9")), Ok(255));
1211 }
1212
1213 #[test]
1214 fn test_float_scientific_notation() {
1215 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("2e2")), Ok(200));
1216 }
1217
1218 #[test]
1219 fn test_float_scientific_small() {
1220 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("1.23e-1")), Ok(0));
1221 }
1222
1223 #[test]
1224 fn test_float_negative() {
1225 assert!(parse_primitive_uint::<u8>(Fragment::testing("-1.5")).is_err());
1226 }
1227
1228 #[test]
1229 fn test_float_negative_zero() {
1230 assert!(parse_primitive_uint::<u8>(Fragment::testing("-0.1")).is_err());
1231 }
1232
1233 #[test]
1234 fn test_float_overflow_positive() {
1235 assert!(parse_primitive_uint::<u8>(Fragment::testing("256.0")).is_err());
1236 }
1237
1238 #[test]
1239 fn test_float_overflow_scientific() {
1240 assert!(parse_primitive_uint::<u8>(Fragment::testing("1e3")).is_err());
1241 }
1242
1243 #[test]
1244 fn test_invalid_float_format() {
1245 assert!(parse_primitive_uint::<u8>(Fragment::testing("1.2.3")).is_err());
1246 }
1247
1248 #[test]
1249 fn trimming_leading_space() {
1250 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing(" 128")), Ok(128));
1251 }
1252
1253 #[test]
1254 fn trimming_trailing_space() {
1255 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128 ")), Ok(128));
1256 }
1257
1258 #[test]
1259 fn trimming_both_spaces() {
1260 assert_eq!(parse_primitive_uint::<u8>(Fragment::testing(" 128 ")), Ok(128));
1261 }
1262 }
1263
1264 mod u16 {
1265 use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
1266
1267 #[test]
1268 fn test_valid_zero() {
1269 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("0")), Ok(0));
1270 }
1271
1272 #[test]
1273 fn test_valid_positive() {
1274 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768")), Ok(32768));
1275 }
1276
1277 #[test]
1278 fn test_valid_max() {
1279 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("65535")), Ok(65535));
1280 }
1281
1282 #[test]
1283 fn test_overflow_positive() {
1284 assert!(parse_primitive_uint::<u16>(Fragment::testing("65536")).is_err());
1285 }
1286
1287 #[test]
1288 fn test_overflow_negative() {
1289 assert!(parse_primitive_uint::<u16>(Fragment::testing("-1")).is_err());
1290 }
1291
1292 #[test]
1293 fn test_invalid_text() {
1294 assert!(parse_primitive_uint::<u16>(Fragment::testing("invalid")).is_err());
1295 }
1296
1297 #[test]
1298 fn test_invalid_empty() {
1299 assert!(parse_primitive_uint::<u16>(Fragment::testing("")).is_err());
1300 }
1301
1302 #[test]
1303 fn test_float_truncation_positive() {
1304 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768.7")), Ok(32768));
1305 }
1306
1307 #[test]
1308 fn test_float_truncation_max() {
1309 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("65535.9")), Ok(65535));
1310 }
1311
1312 #[test]
1313 fn test_float_scientific_notation() {
1314 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("6.5e4")), Ok(65000));
1315 }
1316
1317 #[test]
1318 fn test_float_negative() {
1319 assert!(parse_primitive_uint::<u16>(Fragment::testing("-100.0")).is_err());
1320 }
1321
1322 #[test]
1323 fn test_float_overflow_positive() {
1324 assert!(parse_primitive_uint::<u16>(Fragment::testing("65536.0")).is_err());
1325 }
1326
1327 #[test]
1328 fn test_float_overflow_scientific() {
1329 assert!(parse_primitive_uint::<u16>(Fragment::testing("1e5")).is_err());
1330 }
1331
1332 #[test]
1333 fn trimming_leading_space() {
1334 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing(" 32768")), Ok(32768));
1335 }
1336
1337 #[test]
1338 fn trimming_trailing_space() {
1339 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768 ")), Ok(32768));
1340 }
1341
1342 #[test]
1343 fn trimming_both_spaces() {
1344 assert_eq!(parse_primitive_uint::<u16>(Fragment::testing(" 32768 ")), Ok(32768));
1345 }
1346 }
1347
1348 mod u32 {
1349 use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
1350
1351 #[test]
1352 fn test_valid_zero() {
1353 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("0")), Ok(0));
1354 }
1355
1356 #[test]
1357 fn test_valid_positive() {
1358 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1000000")), Ok(1000000));
1359 }
1360
1361 #[test]
1362 fn test_valid_max() {
1363 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("4294967295")), Ok(4294967295));
1364 }
1365
1366 #[test]
1367 fn test_overflow_positive() {
1368 assert!(parse_primitive_uint::<u32>(Fragment::testing("4294967296")).is_err());
1369 }
1370
1371 #[test]
1372 fn test_overflow_negative() {
1373 assert!(parse_primitive_uint::<u32>(Fragment::testing("-1")).is_err());
1374 }
1375
1376 #[test]
1377 fn test_invalid_text() {
1378 assert!(parse_primitive_uint::<u32>(Fragment::testing("text")).is_err());
1379 }
1380
1381 #[test]
1382 fn test_invalid_empty() {
1383 assert!(parse_primitive_uint::<u32>(Fragment::testing("")).is_err());
1384 }
1385
1386 #[test]
1387 fn test_float_truncation_positive() {
1388 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("3.14")), Ok(3));
1389 }
1390
1391 #[test]
1392 fn test_float_truncation_zero() {
1393 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("0.0")), Ok(0));
1394 }
1395
1396 #[test]
1397 fn test_float_truncation_large() {
1398 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("42.999")), Ok(42));
1399 }
1400
1401 #[test]
1402 fn test_float_scientific_notation() {
1403 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1e+2")), Ok(100));
1404 }
1405
1406 #[test]
1407 fn test_float_scientific_decimal() {
1408 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("2.5e3")), Ok(2500));
1409 }
1410
1411 #[test]
1412 fn test_float_scientific_small() {
1413 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1.23e-1")), Ok(0));
1414 }
1415
1416 #[test]
1417 fn test_float_negative() {
1418 assert!(parse_primitive_uint::<u32>(Fragment::testing("-3.14")).is_err());
1419 }
1420
1421 #[test]
1422 fn test_float_negative_small() {
1423 assert!(parse_primitive_uint::<u32>(Fragment::testing("-0.1")).is_err());
1424 }
1425
1426 #[test]
1427 fn test_float_negative_scientific() {
1428 assert!(parse_primitive_uint::<u32>(Fragment::testing("-1e2")).is_err());
1429 }
1430
1431 #[test]
1432 fn test_float_overflow_positive() {
1433 assert!(parse_primitive_uint::<u32>(Fragment::testing("4294967296.0")).is_err());
1434 }
1435
1436 #[test]
1437 fn test_float_overflow_scientific() {
1438 assert!(parse_primitive_uint::<u32>(Fragment::testing("1e10")).is_err());
1439 }
1440
1441 #[test]
1442 fn test_invalid_float_format() {
1443 assert!(parse_primitive_uint::<u32>(Fragment::testing("1.2.3")).is_err());
1444 }
1445
1446 #[test]
1447 fn trimming_leading_space() {
1448 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing(" 1000000")), Ok(1000000));
1449 }
1450
1451 #[test]
1452 fn trimming_trailing_space() {
1453 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1000000 ")), Ok(1000000));
1454 }
1455
1456 #[test]
1457 fn trimming_both_spaces() {
1458 assert_eq!(parse_primitive_uint::<u32>(Fragment::testing(" 1000000 ")), Ok(1000000));
1459 }
1460 }
1461
1462 mod u64 {
1463 use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
1464
1465 #[test]
1466 fn test_valid_zero() {
1467 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("0")), Ok(0));
1468 }
1469
1470 #[test]
1471 fn test_valid_positive() {
1472 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1000000000000")), Ok(1000000000000));
1473 }
1474
1475 #[test]
1476 fn test_valid_max() {
1477 assert_eq!(
1478 parse_primitive_uint::<u64>(Fragment::testing("18446744073709551615")),
1479 Ok(u64::MAX)
1480 );
1481 }
1482
1483 #[test]
1484 fn test_overflow_positive() {
1485 assert!(parse_primitive_uint::<u64>(Fragment::testing("18446744073709551616")).is_err());
1486 }
1487
1488 #[test]
1489 fn test_overflow_negative() {
1490 assert!(parse_primitive_uint::<u64>(Fragment::testing("-1")).is_err());
1491 }
1492
1493 #[test]
1494 fn test_invalid_text() {
1495 assert!(parse_primitive_uint::<u64>(Fragment::testing("not_valid")).is_err());
1496 }
1497
1498 #[test]
1499 fn test_invalid_empty() {
1500 assert!(parse_primitive_uint::<u64>(Fragment::testing("")).is_err());
1501 }
1502
1503 #[test]
1504 fn test_float_truncation_positive() {
1505 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("123456789.123")), Ok(123456789));
1506 }
1507
1508 #[test]
1509 fn test_float_scientific_notation() {
1510 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1e12")), Ok(1000000000000));
1511 }
1512
1513 #[test]
1514 fn test_float_negative() {
1515 assert!(parse_primitive_uint::<u64>(Fragment::testing("-1.0")).is_err());
1516 }
1517
1518 #[test]
1519 fn test_float_overflow_positive() {
1520 assert!(parse_primitive_uint::<u64>(Fragment::testing("2e19")).is_err());
1521 }
1522
1523 #[test]
1524 fn test_float_overflow_scientific() {
1525 assert!(parse_primitive_uint::<u64>(Fragment::testing("1e20")).is_err());
1526 }
1527
1528 #[test]
1529 fn trimming_leading_space() {
1530 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing(" 1000000000000")), Ok(1000000000000));
1531 }
1532
1533 #[test]
1534 fn trimming_trailing_space() {
1535 assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1000000000000 ")), Ok(1000000000000));
1536 }
1537
1538 #[test]
1539 fn trimming_both_spaces() {
1540 assert_eq!(
1541 parse_primitive_uint::<u64>(Fragment::testing(" 1000000000000 ")),
1542 Ok(1000000000000)
1543 );
1544 }
1545 }
1546
1547 mod u128 {
1548 use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
1549
1550 #[test]
1551 fn test_valid_zero() {
1552 assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("0")), Ok(0));
1553 }
1554
1555 #[test]
1556 fn test_valid_positive() {
1557 assert_eq!(
1558 parse_primitive_uint::<u128>(Fragment::testing("12345678901234567890")),
1559 Ok(12345678901234567890)
1560 );
1561 }
1562
1563 #[test]
1564 fn test_valid_max() {
1565 assert_eq!(
1566 parse_primitive_uint::<u128>(Fragment::testing(&u128::MAX.to_string())),
1567 Ok(u128::MAX)
1568 );
1569 }
1570
1571 #[test]
1572 fn test_overflow_positive() {
1573 assert!(parse_primitive_uint::<u128>(Fragment::testing(
1574 "340282366920938463463374607431768211456"
1575 ))
1576 .is_err());
1577 }
1578
1579 #[test]
1580 fn test_overflow_negative() {
1581 assert!(parse_primitive_uint::<u128>(Fragment::testing("-1")).is_err());
1582 }
1583
1584 #[test]
1585 fn test_invalid_text() {
1586 assert!(parse_primitive_uint::<u128>(Fragment::testing("abc")).is_err());
1587 }
1588
1589 #[test]
1590 fn test_invalid_empty() {
1591 assert!(parse_primitive_uint::<u128>(Fragment::testing("")).is_err());
1592 }
1593
1594 #[test]
1595 fn test_float_truncation_positive() {
1596 assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("123456789.999")), Ok(123456789));
1597 }
1598
1599 #[test]
1600 fn test_float_scientific_notation() {
1601 assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("1e20")), Ok(100000000000000000000));
1602 }
1603
1604 #[test]
1605 fn test_float_negative() {
1606 assert!(parse_primitive_uint::<u128>(Fragment::testing("-1.0")).is_err());
1607 }
1608
1609 #[test]
1610 fn test_float_overflow_positive() {
1611 assert!(parse_primitive_uint::<u128>(Fragment::testing("1e40")).is_err());
1612 }
1613
1614 #[test]
1615 fn test_float_overflow_scientific() {
1616 assert!(parse_primitive_uint::<u128>(Fragment::testing("1e50")).is_err());
1617 }
1618
1619 #[test]
1620 fn trimming_leading_space() {
1621 assert_eq!(
1622 parse_primitive_uint::<u128>(Fragment::testing(" 12345678901234567890")),
1623 Ok(12345678901234567890)
1624 );
1625 }
1626
1627 #[test]
1628 fn trimming_trailing_space() {
1629 assert_eq!(
1630 parse_primitive_uint::<u128>(Fragment::testing("12345678901234567890 ")),
1631 Ok(12345678901234567890)
1632 );
1633 }
1634
1635 #[test]
1636 fn trimming_both_spaces() {
1637 assert_eq!(
1638 parse_primitive_uint::<u128>(Fragment::testing(" 12345678901234567890 ")),
1639 Ok(12345678901234567890)
1640 );
1641 }
1642 }
1643
1644 mod f32 {
1645 use crate::{fragment::Fragment, value::number::parse::parse_float};
1646
1647 #[test]
1648 fn test_valid_zero() {
1649 assert_eq!(parse_float::<f32>(Fragment::testing("0.0")), Ok(0.0));
1650 }
1651
1652 #[test]
1653 fn test_valid_positive() {
1654 assert_eq!(parse_float::<f32>(Fragment::testing("1.5")), Ok(1.5));
1655 }
1656
1657 #[test]
1658 fn test_valid_negative() {
1659 assert_eq!(parse_float::<f32>(Fragment::testing("-3.14")), Ok(-3.14));
1660 }
1661
1662 #[test]
1663 fn test_valid_integer() {
1664 assert_eq!(parse_float::<f32>(Fragment::testing("42")), Ok(42.0));
1665 }
1666
1667 #[test]
1668 fn test_valid_scientific() {
1669 assert_eq!(parse_float::<f32>(Fragment::testing("1e2")), Ok(100.0));
1670 }
1671
1672 #[test]
1673 fn test_valid_scientific_negative() {
1674 assert_eq!(parse_float::<f32>(Fragment::testing("1e-2")), Ok(0.01));
1675 }
1676
1677 #[test]
1678 fn test_overflow_positive() {
1679 assert!(parse_float::<f32>(Fragment::testing("3.5e38")).is_err());
1680 }
1681
1682 #[test]
1683 fn test_overflow_negative() {
1684 assert!(parse_float::<f32>(Fragment::testing("-3.5e38")).is_err());
1685 }
1686
1687 #[test]
1688 fn test_invalid_text() {
1689 assert!(parse_float::<f32>(Fragment::testing("abc")).is_err());
1690 }
1691
1692 #[test]
1693 fn test_invalid_empty() {
1694 assert!(parse_float::<f32>(Fragment::testing("")).is_err());
1695 }
1696
1697 #[test]
1698 fn test_invalid_whitespace() {
1699 assert!(parse_float::<f32>(Fragment::testing(" ")).is_err());
1700 }
1701
1702 #[test]
1703 fn test_invalid_nan() {
1704 assert!(parse_float::<f32>(Fragment::testing("NaN")).is_err());
1705 }
1706
1707 #[test]
1708 fn test_invalid_nan_lowercase() {
1709 assert!(parse_float::<f32>(Fragment::testing("nan")).is_err());
1710 }
1711
1712 #[test]
1713 fn test_invalid_multiple_dots() {
1714 assert!(parse_float::<f32>(Fragment::testing("1.2.3")).is_err());
1715 }
1716
1717 #[test]
1718 fn trimming_leading_space() {
1719 assert_eq!(parse_float::<f32>(Fragment::testing(" 1.5")), Ok(1.5));
1720 }
1721
1722 #[test]
1723 fn trimming_trailing_space() {
1724 assert_eq!(parse_float::<f32>(Fragment::testing("1.5 ")), Ok(1.5));
1725 }
1726
1727 #[test]
1728 fn trimming_both_spaces() {
1729 assert_eq!(parse_float::<f32>(Fragment::testing(" 1.5 ")), Ok(1.5));
1730 }
1731
1732 #[test]
1733 fn trimming_negative_leading_space() {
1734 assert_eq!(parse_float::<f32>(Fragment::testing(" -3.14")), Ok(-3.14));
1735 }
1736
1737 #[test]
1738 fn trimming_negative_trailing_space() {
1739 assert_eq!(parse_float::<f32>(Fragment::testing("-3.14 ")), Ok(-3.14));
1740 }
1741
1742 #[test]
1743 fn trimming_negative_both_spaces() {
1744 assert_eq!(parse_float::<f32>(Fragment::testing(" -3.14 ")), Ok(-3.14));
1745 }
1746 }
1747
1748 mod f64 {
1749 use crate::{fragment::Fragment, value::number::parse::parse_float};
1750
1751 #[test]
1752 fn test_valid_zero() {
1753 assert_eq!(parse_float::<f64>(Fragment::testing("0.0")), Ok(0.0));
1754 }
1755
1756 #[test]
1757 fn test_valid_positive() {
1758 assert_eq!(parse_float::<f64>(Fragment::testing("1.23")), Ok(1.23));
1759 }
1760
1761 #[test]
1762 fn test_valid_negative() {
1763 assert_eq!(parse_float::<f64>(Fragment::testing("-0.001")), Ok(-0.001));
1764 }
1765
1766 #[test]
1767 fn test_valid_integer() {
1768 assert_eq!(parse_float::<f64>(Fragment::testing("42")), Ok(42.0));
1769 }
1770
1771 #[test]
1772 fn test_valid_scientific() {
1773 assert_eq!(parse_float::<f64>(Fragment::testing("1e10")), Ok(1e10));
1774 }
1775
1776 #[test]
1777 fn test_valid_scientific_negative() {
1778 assert_eq!(parse_float::<f64>(Fragment::testing("1e-10")), Ok(1e-10));
1779 }
1780
1781 #[test]
1782 fn test_overflow_positive() {
1783 assert!(parse_float::<f64>(Fragment::testing("1e400")).is_err());
1784 }
1785
1786 #[test]
1787 fn test_overflow_negative() {
1788 assert!(parse_float::<f64>(Fragment::testing("-1e400")).is_err());
1789 }
1790
1791 #[test]
1792 fn test_invalid_text() {
1793 assert!(parse_float::<f64>(Fragment::testing("abc")).is_err());
1794 }
1795
1796 #[test]
1797 fn test_invalid_empty() {
1798 assert!(parse_float::<f64>(Fragment::testing("")).is_err());
1799 }
1800
1801 #[test]
1802 fn test_invalid_whitespace() {
1803 assert!(parse_float::<f64>(Fragment::testing(" ")).is_err());
1804 }
1805
1806 #[test]
1807 fn test_invalid_nan() {
1808 assert!(parse_float::<f64>(Fragment::testing("NaN")).is_err());
1809 }
1810
1811 #[test]
1812 fn test_invalid_nan_mixed_case() {
1813 assert!(parse_float::<f64>(Fragment::testing("NaN")).is_err());
1814 }
1815
1816 #[test]
1817 fn test_invalid_multiple_dots() {
1818 assert!(parse_float::<f64>(Fragment::testing("1.2.3")).is_err());
1819 }
1820
1821 #[test]
1822 fn trimming_leading_space() {
1823 assert_eq!(parse_float::<f64>(Fragment::testing(" 1.23")), Ok(1.23));
1824 }
1825
1826 #[test]
1827 fn trimming_trailing_space() {
1828 assert_eq!(parse_float::<f64>(Fragment::testing("1.23 ")), Ok(1.23));
1829 }
1830
1831 #[test]
1832 fn trimming_both_spaces() {
1833 assert_eq!(parse_float::<f64>(Fragment::testing(" 1.23 ")), Ok(1.23));
1834 }
1835
1836 #[test]
1837 fn trimming_negative_leading_space() {
1838 assert_eq!(parse_float::<f64>(Fragment::testing(" -0.001")), Ok(-0.001));
1839 }
1840
1841 #[test]
1842 fn trimming_negative_trailing_space() {
1843 assert_eq!(parse_float::<f64>(Fragment::testing("-0.001 ")), Ok(-0.001));
1844 }
1845
1846 #[test]
1847 fn trimming_negative_both_spaces() {
1848 assert_eq!(parse_float::<f64>(Fragment::testing(" -0.001 ")), Ok(-0.001));
1849 }
1850 }
1851
1852 mod big_int {
1853 use crate::{
1854 fragment::Fragment,
1855 value::{int::Int, number::parse::parse_primitive_int},
1856 };
1857
1858 #[test]
1859 fn test_parse_int_basic() {
1860 let result = parse_primitive_int::<Int>(Fragment::testing("12345"));
1861 assert!(result.is_ok());
1862 assert_eq!(format!("{}", result.unwrap()), "12345");
1863 }
1864
1865 #[test]
1866 fn test_parse_int_negative() {
1867 let result = parse_primitive_int::<Int>(Fragment::testing("-12345"));
1868 assert!(result.is_ok());
1869 assert_eq!(format!("{}", result.unwrap()), "-12345");
1870 }
1871
1872 #[test]
1873 fn test_parse_int_large() {
1874 let result = parse_primitive_int::<Int>(Fragment::testing("123456789012345678901234567890"));
1875 assert!(result.is_ok());
1876 assert_eq!(format!("{}", result.unwrap()), "123456789012345678901234567890");
1877 }
1878 }
1879
1880 mod big_uint {
1881 use crate::{
1882 fragment::Fragment,
1883 value::{number::parse::parse_primitive_uint, uint::Uint},
1884 };
1885
1886 #[test]
1887 fn test_parse_uint_basic() {
1888 let result = parse_primitive_uint::<Uint>(Fragment::testing("12345"));
1889 assert!(result.is_ok());
1890 assert_eq!(format!("{}", result.unwrap()), "12345");
1891 }
1892
1893 #[test]
1894 fn test_parse_uint_large() {
1895 let result = parse_primitive_uint::<Uint>(Fragment::testing("123456789012345678901234567890"));
1896 assert!(result.is_ok());
1897 assert_eq!(format!("{}", result.unwrap()), "123456789012345678901234567890");
1898 }
1899 }
1900}