Skip to main content

reifydb_value/value/number/
parse.rs

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