reifydb_type/value/number/
parse.rs

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