Skip to main content

reifydb_value/value/number/
parse.rs

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