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