Skip to main content

reifydb_type/value/number/
parse.rs

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