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