use std::{any::TypeId, borrow::Cow, mem, num, num::IntErrorKind, ptr, str::FromStr};
use crate::{
error::{Error, TypeError},
fragment::Fragment,
value::{
int::{Int, parse::parse_int},
is::{IsFloat, IsInt, IsUint},
r#type::Type,
uint::{Uint, parse::parse_uint},
},
};
pub fn parse_primitive_int<T>(fragment: Fragment) -> Result<T, Error>
where
T: IsInt + 'static,
{
if TypeId::of::<T>() == TypeId::of::<i8>() {
Ok(cast::<T, i8>(parse_i8(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<i16>() {
Ok(cast::<T, i16>(parse_i16(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<i32>() {
Ok(cast::<T, i32>(parse_i32(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<i64>() {
Ok(cast::<T, i64>(parse_i64(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<i128>() {
Ok(cast::<T, i128>(parse_i128(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<Int>() {
Ok(cast::<T, Int>(parse_int(fragment)?))
} else {
unreachable!();
}
}
pub fn parse_primitive_uint<T>(fragment: Fragment) -> Result<T, Error>
where
T: IsUint + 'static,
{
if TypeId::of::<T>() == TypeId::of::<u8>() {
Ok(cast::<T, u8>(parse_u8(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<u16>() {
Ok(cast::<T, u16>(parse_u16(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<u32>() {
Ok(cast::<T, u32>(parse_u32(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<u64>() {
Ok(cast::<T, u64>(parse_u64(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<u128>() {
Ok(cast::<T, u128>(parse_u128(fragment)?))
} else if TypeId::of::<T>() == TypeId::of::<Uint>() {
Ok(cast::<T, Uint>(parse_uint(fragment)?))
} else {
unreachable!();
}
}
pub fn parse_float<T>(fragment: Fragment) -> Result<T, Error>
where
T: IsFloat + 'static,
{
if fragment.text().to_lowercase().contains("nan") {
return Err(TypeError::NanNotAllowed.into());
}
if TypeId::of::<T>() == TypeId::of::<f32>() {
Ok(cast::<T, f32>(parse_f32(fragment.clone())?))
} else if TypeId::of::<T>() == TypeId::of::<f64>() {
Ok(cast::<T, f64>(parse_f64(fragment)?))
} else {
unreachable!();
}
}
fn cast_float_to_int<T: 'static>(f: f64) -> T {
if TypeId::of::<T>() == TypeId::of::<i8>() {
cast::<T, i8>(f as i8)
} else if TypeId::of::<T>() == TypeId::of::<i16>() {
cast::<T, i16>(f as i16)
} else if TypeId::of::<T>() == TypeId::of::<i32>() {
cast::<T, i32>(f as i32)
} else if TypeId::of::<T>() == TypeId::of::<i64>() {
cast::<T, i64>(f as i64)
} else if TypeId::of::<T>() == TypeId::of::<i128>() {
cast::<T, i128>(f as i128)
} else if TypeId::of::<T>() == TypeId::of::<u8>() {
cast::<T, u8>(f as u8)
} else if TypeId::of::<T>() == TypeId::of::<u16>() {
cast::<T, u16>(f as u16)
} else if TypeId::of::<T>() == TypeId::of::<u32>() {
cast::<T, u32>(f as u32)
} else if TypeId::of::<T>() == TypeId::of::<u64>() {
cast::<T, u64>(f as u64)
} else if TypeId::of::<T>() == TypeId::of::<u128>() {
cast::<T, u128>(f as u128)
} else {
unreachable!()
}
}
fn cast<T: 'static, U: 'static>(v: U) -> T {
assert_eq!(TypeId::of::<T>(), TypeId::of::<U>());
let v = mem::ManuallyDrop::new(v);
unsafe { ptr::read(&*v as *const U as *const T) }
}
trait TypeInfo {
fn type_enum() -> Type;
}
impl TypeInfo for i8 {
fn type_enum() -> Type {
Type::Int1
}
}
impl TypeInfo for i16 {
fn type_enum() -> Type {
Type::Int2
}
}
impl TypeInfo for i32 {
fn type_enum() -> Type {
Type::Int4
}
}
impl TypeInfo for i64 {
fn type_enum() -> Type {
Type::Int8
}
}
impl TypeInfo for i128 {
fn type_enum() -> Type {
Type::Int16
}
}
impl TypeInfo for u8 {
fn type_enum() -> Type {
Type::Uint1
}
}
impl TypeInfo for u16 {
fn type_enum() -> Type {
Type::Uint2
}
}
impl TypeInfo for u32 {
fn type_enum() -> Type {
Type::Uint4
}
}
impl TypeInfo for u64 {
fn type_enum() -> Type {
Type::Uint8
}
}
impl TypeInfo for u128 {
fn type_enum() -> Type {
Type::Uint16
}
}
impl TypeInfo for f32 {
fn type_enum() -> Type {
Type::Float4
}
}
impl TypeInfo for f64 {
fn type_enum() -> Type {
Type::Float8
}
}
#[inline]
fn parse_signed_generic<T>(fragment: Fragment) -> Result<T, Error>
where
T: FromStr<Err = num::ParseIntError> + TypeInfo + 'static,
{
let raw_value = fragment.text();
let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
|| raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
let has_underscores = raw_value.as_bytes().contains(&b'_');
let value = match (needs_trimming, has_underscores) {
(false, false) => Cow::Borrowed(raw_value), (true, false) => Cow::Borrowed(raw_value.trim()),
(false, true) => Cow::Owned(raw_value.replace('_', "")),
(true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
};
if value.is_empty() {
return Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into());
}
match value.parse::<T>() {
Ok(v) => Ok(v),
Err(err) => match err.kind() {
IntErrorKind::Empty => Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into()),
IntErrorKind::InvalidDigit => {
if let Ok(f) = value.parse::<f64>() {
let truncated = f.trunc();
let type_enum = T::type_enum();
let in_range = match type_enum {
Type::Int1 => {
truncated >= i8::MIN as f64 && truncated <= i8::MAX as f64
}
Type::Int2 => {
truncated >= i16::MIN as f64 && truncated <= i16::MAX as f64
}
Type::Int4 => {
truncated >= i32::MIN as f64 && truncated <= i32::MAX as f64
}
Type::Int8 => {
truncated >= i64::MIN as f64 && truncated <= i64::MAX as f64
}
Type::Int16 => {
truncated >= i128::MIN as f64 && truncated <= i128::MAX as f64
}
_ => false,
};
if in_range {
Ok(cast_float_to_int::<T>(truncated))
} else {
Err(TypeError::NumberOutOfRange {
target: type_enum,
fragment,
descriptor: None,
}
.into())
}
} else {
Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into())
}
}
IntErrorKind::PosOverflow => Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into()),
IntErrorKind::NegOverflow => Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into()),
IntErrorKind::Zero => Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into()),
&_ => unreachable!("{}", err),
},
}
}
#[inline]
fn parse_unsigned_generic<T>(fragment: Fragment) -> Result<T, Error>
where
T: FromStr<Err = num::ParseIntError> + TypeInfo + 'static,
{
let raw_value = fragment.text();
let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
|| raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
let has_underscores = raw_value.as_bytes().contains(&b'_');
let value = match (needs_trimming, has_underscores) {
(false, false) => Cow::Borrowed(raw_value), (true, false) => Cow::Borrowed(raw_value.trim()),
(false, true) => Cow::Owned(raw_value.replace('_', "")),
(true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
};
if value.is_empty() {
return Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into());
}
match value.parse::<T>() {
Ok(v) => Ok(v),
Err(err) => {
match err.kind() {
IntErrorKind::Empty => Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into()),
IntErrorKind::InvalidDigit => {
if let Ok(f) = value.parse::<f64>() {
if f < 0.0 {
return Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into());
}
let truncated = f.trunc();
let type_enum = T::type_enum();
let in_range = match type_enum {
Type::Uint1 => truncated >= 0.0 && truncated <= u8::MAX as f64,
Type::Uint2 => truncated >= 0.0 && truncated <= u16::MAX as f64,
Type::Uint4 => truncated >= 0.0 && truncated <= u32::MAX as f64,
Type::Uint8 => truncated >= 0.0 && truncated <= u64::MAX as f64,
Type::Uint16 => {
truncated >= 0.0 && truncated <= u128::MAX as f64
}
_ => false,
};
if in_range {
Ok(cast_float_to_int::<T>(truncated))
} else {
Err(TypeError::NumberOutOfRange {
target: type_enum,
fragment,
descriptor: None,
}
.into())
}
} else if value.contains("-") {
Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into())
} else {
Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into())
}
}
IntErrorKind::PosOverflow => Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into()),
IntErrorKind::NegOverflow => Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into()),
IntErrorKind::Zero => Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into()),
&_ => unreachable!("{}", err),
}
}
}
}
#[inline]
fn parse_float_generic<T>(fragment: Fragment) -> Result<T, Error>
where
T: FromStr<Err = num::ParseFloatError> + Copy + TypeInfo + PartialEq + 'static,
{
let raw_value = fragment.text();
let needs_trimming = raw_value.as_bytes().first().is_some_and(|&b| b.is_ascii_whitespace())
|| raw_value.as_bytes().last().is_some_and(|&b| b.is_ascii_whitespace());
let has_underscores = raw_value.as_bytes().contains(&b'_');
let value = match (needs_trimming, has_underscores) {
(false, false) => Cow::Borrowed(raw_value), (true, false) => Cow::Borrowed(raw_value.trim()),
(false, true) => Cow::Owned(raw_value.replace('_', "")),
(true, true) => Cow::Owned(raw_value.trim().replace('_', "")),
};
if value.is_empty() {
return Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into());
}
match value.parse::<T>() {
Ok(v) => {
if TypeId::of::<T>() == TypeId::of::<f32>() {
let v_f32 = cast::<f32, T>(v);
if v_f32.is_infinite() {
return Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into());
}
} else if TypeId::of::<T>() == TypeId::of::<f64>() {
let v_f64 = cast::<f64, T>(v);
if v_f64.is_infinite() {
return Err(TypeError::NumberOutOfRange {
target: T::type_enum(),
fragment,
descriptor: None,
}
.into());
}
}
Ok(v)
}
Err(_) => Err(TypeError::InvalidNumberFormat {
target: T::type_enum(),
fragment,
}
.into()),
}
}
#[inline]
fn parse_f32(fragment: Fragment) -> Result<f32, Error> {
parse_float_generic::<f32>(fragment)
}
#[inline]
fn parse_f64(fragment: Fragment) -> Result<f64, Error> {
parse_float_generic::<f64>(fragment)
}
#[inline]
fn parse_i8(fragment: Fragment) -> Result<i8, Error> {
parse_signed_generic::<i8>(fragment)
}
#[inline]
fn parse_i16(fragment: Fragment) -> Result<i16, Error> {
parse_signed_generic::<i16>(fragment)
}
#[inline]
fn parse_i32(fragment: Fragment) -> Result<i32, Error> {
parse_signed_generic::<i32>(fragment)
}
#[inline]
fn parse_i64(fragment: Fragment) -> Result<i64, Error> {
parse_signed_generic::<i64>(fragment)
}
#[inline]
fn parse_i128(fragment: Fragment) -> Result<i128, Error> {
parse_signed_generic::<i128>(fragment)
}
#[inline]
fn parse_u8(fragment: Fragment) -> Result<u8, Error> {
parse_unsigned_generic::<u8>(fragment)
}
#[inline]
fn parse_u16(fragment: Fragment) -> Result<u16, Error> {
parse_unsigned_generic::<u16>(fragment)
}
#[inline]
fn parse_u32(fragment: Fragment) -> Result<u32, Error> {
parse_unsigned_generic::<u32>(fragment)
}
#[inline]
fn parse_u64(fragment: Fragment) -> Result<u64, Error> {
parse_unsigned_generic::<u64>(fragment)
}
#[inline]
fn parse_u128(fragment: Fragment) -> Result<u128, Error> {
parse_unsigned_generic::<u128>(fragment)
}
#[cfg(test)]
#[allow(clippy::approx_constant)]
pub mod tests {
mod i8 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42")), Ok(42));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42")), Ok(-42));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("127")), Ok(127));
}
#[test]
fn test_valid_min() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-128")), Ok(-128));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_int::<i8>(Fragment::testing("128")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_int::<i8>(Fragment::testing("-129")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_int::<i8>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_int::<i8>(Fragment::testing("")).is_err());
}
#[test]
fn test_invalid_whitespace() {
assert!(parse_primitive_int::<i8>(Fragment::testing(" ")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42.9")), Ok(42));
}
#[test]
fn test_float_truncation_negative() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42.9")), Ok(-42));
}
#[test]
fn test_float_truncation_zero() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("0.0")), Ok(0));
}
#[test]
fn test_float_truncation_negative_zero() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-0.0")), Ok(0));
}
#[test]
fn test_float_truncation_max() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("127.9")), Ok(127));
}
#[test]
fn test_float_truncation_min() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-128.9")), Ok(-128));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("1e+2")), Ok(100));
}
#[test]
fn test_float_scientific_small() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("1.23e-1")), Ok(0));
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_int::<i8>(Fragment::testing("128.0")).is_err());
}
#[test]
fn test_float_overflow_negative() {
assert!(parse_primitive_int::<i8>(Fragment::testing("-129.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_int::<i8>(Fragment::testing("1e3")).is_err());
}
#[test]
fn test_invalid_float_format() {
assert!(parse_primitive_int::<i8>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" 42")), Ok(42));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("42 ")), Ok(42));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" 42 ")), Ok(42));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" -42")), Ok(-42));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing("-42 ")), Ok(-42));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_primitive_int::<i8>(Fragment::testing(" -42 ")), Ok(-42));
}
}
mod i16 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000")), Ok(1000));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000")), Ok(-1000));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("32767")), Ok(32767));
}
#[test]
fn test_valid_min() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-32768")), Ok(-32768));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_int::<i16>(Fragment::testing("32768")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_int::<i16>(Fragment::testing("-32769")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_int::<i16>(Fragment::testing("hello")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_int::<i16>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000.7")), Ok(1000));
}
#[test]
fn test_float_truncation_negative() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000.7")), Ok(-1000));
}
#[test]
fn test_float_truncation_max() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("32767.9")), Ok(32767));
}
#[test]
fn test_float_truncation_min() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-32768.9")), Ok(-32768));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1.5e3")), Ok(1500));
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_int::<i16>(Fragment::testing("32768.0")).is_err());
}
#[test]
fn test_float_overflow_negative() {
assert!(parse_primitive_int::<i16>(Fragment::testing("-32769.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_int::<i16>(Fragment::testing("1e5")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" 1000")), Ok(1000));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("1000 ")), Ok(1000));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" 1000 ")), Ok(1000));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" -1000")), Ok(-1000));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing("-1000 ")), Ok(-1000));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_primitive_int::<i16>(Fragment::testing(" -1000 ")), Ok(-1000));
}
}
mod i32 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1000000")), Ok(1000000));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-1000000")), Ok(-1000000));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("2147483647")), Ok(2147483647));
}
#[test]
fn test_valid_min() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-2147483648")), Ok(-2147483648));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_int::<i32>(Fragment::testing("2147483648")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_int::<i32>(Fragment::testing("-2147483649")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_int::<i32>(Fragment::testing("not_a_number")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_int::<i32>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("3.14")), Ok(3));
}
#[test]
fn test_float_truncation_negative() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-3.14")), Ok(-3));
}
#[test]
fn test_float_truncation_zero() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("0.0")), Ok(0));
}
#[test]
fn test_float_truncation_negative_zero() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-0.0")), Ok(0));
}
#[test]
fn test_float_truncation_large() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("42.999")), Ok(42));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1e+2")), Ok(100));
}
#[test]
fn test_float_scientific_decimal() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("2.5e3")), Ok(2500));
}
#[test]
fn test_float_scientific_negative() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-1.5e2")), Ok(-150));
}
#[test]
fn test_float_scientific_small() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("1.23e-1")), Ok(0));
}
#[test]
fn test_float_scientific_very_small() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("9.9e-1")), Ok(0));
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_int::<i32>(Fragment::testing("2147483648.0")).is_err());
}
#[test]
fn test_float_overflow_negative() {
assert!(parse_primitive_int::<i32>(Fragment::testing("-2147483649.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_int::<i32>(Fragment::testing("1e10")).is_err());
}
#[test]
fn test_invalid_float_format() {
assert!(parse_primitive_int::<i32>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" 123")), Ok(123));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("123 ")), Ok(123));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" 123 ")), Ok(123));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" -456")), Ok(-456));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing("-456 ")), Ok(-456));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_primitive_int::<i32>(Fragment::testing(" -456 ")), Ok(-456));
}
}
mod i64 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1000000000")), Ok(1000000000));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-1000000000")), Ok(-1000000000));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("9223372036854775807")), Ok(i64::MAX));
}
#[test]
fn test_valid_min() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-9223372036854775808")), Ok(i64::MIN));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_int::<i64>(Fragment::testing("9223372036854775808")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_int::<i64>(Fragment::testing("-9223372036854775809")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_int::<i64>(Fragment::testing("invalid")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_int::<i64>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("12345.67")), Ok(12345));
}
#[test]
fn test_float_truncation_negative() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-12345.67")), Ok(-12345));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1e10")), Ok(10000000000));
}
#[test]
fn test_float_scientific_large() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("9.223e18")), Ok(9223000000000000000));
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_int::<i64>(Fragment::testing("1e19")).is_err());
}
#[test]
fn test_float_overflow_negative() {
assert!(parse_primitive_int::<i64>(Fragment::testing("-1e19")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" 1000000000")), Ok(1000000000));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("1000000000 ")), Ok(1000000000));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" 1000000000 ")), Ok(1000000000));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" -1000000000")), Ok(-1000000000));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing("-1000000000 ")), Ok(-1000000000));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_primitive_int::<i64>(Fragment::testing(" -1000000000 ")), Ok(-1000000000));
}
}
mod i128 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_int};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_int::<i128>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing("12345678901234567890")),
Ok(12345678901234567890)
);
}
#[test]
fn test_valid_negative() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing("-12345678901234567890")),
Ok(-12345678901234567890)
);
}
#[test]
fn test_valid_max() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(&i128::MAX.to_string())),
Ok(i128::MAX)
);
}
#[test]
fn test_valid_min() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(&i128::MIN.to_string())),
Ok(i128::MIN)
);
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_int::<i128>(Fragment::testing(
"170141183460469231731687303715884105728"
))
.is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_int::<i128>(Fragment::testing(
"-170141183460469231731687303715884105729"
))
.is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_int::<i128>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_int::<i128>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_int::<i128>(Fragment::testing("123456789.123")), Ok(123456789));
}
#[test]
fn test_float_truncation_negative() {
assert_eq!(parse_primitive_int::<i128>(Fragment::testing("-123456789.123")), Ok(-123456789));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_int::<i128>(Fragment::testing("1e20")), Ok(100000000000000000000));
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_int::<i128>(Fragment::testing("1e40")).is_err());
}
#[test]
fn test_float_overflow_negative() {
assert!(parse_primitive_int::<i128>(Fragment::testing("-1e40")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(" 12345678901234567890")),
Ok(12345678901234567890)
);
}
#[test]
fn trimming_trailing_space() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing("12345678901234567890 ")),
Ok(12345678901234567890)
);
}
#[test]
fn trimming_both_spaces() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(" 12345678901234567890 ")),
Ok(12345678901234567890)
);
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(" -12345678901234567890")),
Ok(-12345678901234567890)
);
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing("-12345678901234567890 ")),
Ok(-12345678901234567890)
);
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(
parse_primitive_int::<i128>(Fragment::testing(" -12345678901234567890 ")),
Ok(-12345678901234567890)
);
}
}
mod u8 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128")), Ok(128));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("255")), Ok(255));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("256")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("-1")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128.9")), Ok(128));
}
#[test]
fn test_float_truncation_zero() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("0.0")), Ok(0));
}
#[test]
fn test_float_truncation_max() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("255.9")), Ok(255));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("2e2")), Ok(200));
}
#[test]
fn test_float_scientific_small() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("1.23e-1")), Ok(0));
}
#[test]
fn test_float_negative() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("-1.5")).is_err());
}
#[test]
fn test_float_negative_zero() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("-0.1")).is_err());
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("256.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("1e3")).is_err());
}
#[test]
fn test_invalid_float_format() {
assert!(parse_primitive_uint::<u8>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing(" 128")), Ok(128));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing("128 ")), Ok(128));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_uint::<u8>(Fragment::testing(" 128 ")), Ok(128));
}
}
mod u16 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768")), Ok(32768));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("65535")), Ok(65535));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("65536")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("-1")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("invalid")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768.7")), Ok(32768));
}
#[test]
fn test_float_truncation_max() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("65535.9")), Ok(65535));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("6.5e4")), Ok(65000));
}
#[test]
fn test_float_negative() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("-100.0")).is_err());
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("65536.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_uint::<u16>(Fragment::testing("1e5")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing(" 32768")), Ok(32768));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing("32768 ")), Ok(32768));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_uint::<u16>(Fragment::testing(" 32768 ")), Ok(32768));
}
}
mod u32 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1000000")), Ok(1000000));
}
#[test]
fn test_valid_max() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("4294967295")), Ok(4294967295));
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("4294967296")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("-1")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("text")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("3.14")), Ok(3));
}
#[test]
fn test_float_truncation_zero() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("0.0")), Ok(0));
}
#[test]
fn test_float_truncation_large() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("42.999")), Ok(42));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1e+2")), Ok(100));
}
#[test]
fn test_float_scientific_decimal() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("2.5e3")), Ok(2500));
}
#[test]
fn test_float_scientific_small() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1.23e-1")), Ok(0));
}
#[test]
fn test_float_negative() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("-3.14")).is_err());
}
#[test]
fn test_float_negative_small() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("-0.1")).is_err());
}
#[test]
fn test_float_negative_scientific() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("-1e2")).is_err());
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("4294967296.0")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("1e10")).is_err());
}
#[test]
fn test_invalid_float_format() {
assert!(parse_primitive_uint::<u32>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing(" 1000000")), Ok(1000000));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing("1000000 ")), Ok(1000000));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_primitive_uint::<u32>(Fragment::testing(" 1000000 ")), Ok(1000000));
}
}
mod u64 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1000000000000")), Ok(1000000000000));
}
#[test]
fn test_valid_max() {
assert_eq!(
parse_primitive_uint::<u64>(Fragment::testing("18446744073709551615")),
Ok(u64::MAX)
);
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("18446744073709551616")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("-1")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("not_valid")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("123456789.123")), Ok(123456789));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1e12")), Ok(1000000000000));
}
#[test]
fn test_float_negative() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("-1.0")).is_err());
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("2e19")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_uint::<u64>(Fragment::testing("1e20")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing(" 1000000000000")), Ok(1000000000000));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_primitive_uint::<u64>(Fragment::testing("1000000000000 ")), Ok(1000000000000));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(
parse_primitive_uint::<u64>(Fragment::testing(" 1000000000000 ")),
Ok(1000000000000)
);
}
}
mod u128 {
use crate::{fragment::Fragment, value::number::parse::parse_primitive_uint};
#[test]
fn test_valid_zero() {
assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("0")), Ok(0));
}
#[test]
fn test_valid_positive() {
assert_eq!(
parse_primitive_uint::<u128>(Fragment::testing("12345678901234567890")),
Ok(12345678901234567890)
);
}
#[test]
fn test_valid_max() {
assert_eq!(
parse_primitive_uint::<u128>(Fragment::testing(&u128::MAX.to_string())),
Ok(u128::MAX)
);
}
#[test]
fn test_overflow_positive() {
assert!(parse_primitive_uint::<u128>(Fragment::testing(
"340282366920938463463374607431768211456"
))
.is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("-1")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("")).is_err());
}
#[test]
fn test_float_truncation_positive() {
assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("123456789.999")), Ok(123456789));
}
#[test]
fn test_float_scientific_notation() {
assert_eq!(parse_primitive_uint::<u128>(Fragment::testing("1e20")), Ok(100000000000000000000));
}
#[test]
fn test_float_negative() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("-1.0")).is_err());
}
#[test]
fn test_float_overflow_positive() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("1e40")).is_err());
}
#[test]
fn test_float_overflow_scientific() {
assert!(parse_primitive_uint::<u128>(Fragment::testing("1e50")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(
parse_primitive_uint::<u128>(Fragment::testing(" 12345678901234567890")),
Ok(12345678901234567890)
);
}
#[test]
fn trimming_trailing_space() {
assert_eq!(
parse_primitive_uint::<u128>(Fragment::testing("12345678901234567890 ")),
Ok(12345678901234567890)
);
}
#[test]
fn trimming_both_spaces() {
assert_eq!(
parse_primitive_uint::<u128>(Fragment::testing(" 12345678901234567890 ")),
Ok(12345678901234567890)
);
}
}
mod f32 {
use crate::{fragment::Fragment, value::number::parse::parse_float};
#[test]
fn test_valid_zero() {
assert_eq!(parse_float::<f32>(Fragment::testing("0.0")), Ok(0.0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_float::<f32>(Fragment::testing("1.5")), Ok(1.5));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_float::<f32>(Fragment::testing("-3.14")), Ok(-3.14));
}
#[test]
fn test_valid_integer() {
assert_eq!(parse_float::<f32>(Fragment::testing("42")), Ok(42.0));
}
#[test]
fn test_valid_scientific() {
assert_eq!(parse_float::<f32>(Fragment::testing("1e2")), Ok(100.0));
}
#[test]
fn test_valid_scientific_negative() {
assert_eq!(parse_float::<f32>(Fragment::testing("1e-2")), Ok(0.01));
}
#[test]
fn test_overflow_positive() {
assert!(parse_float::<f32>(Fragment::testing("3.5e38")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_float::<f32>(Fragment::testing("-3.5e38")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_float::<f32>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_float::<f32>(Fragment::testing("")).is_err());
}
#[test]
fn test_invalid_whitespace() {
assert!(parse_float::<f32>(Fragment::testing(" ")).is_err());
}
#[test]
fn test_invalid_nan() {
assert!(parse_float::<f32>(Fragment::testing("NaN")).is_err());
}
#[test]
fn test_invalid_nan_lowercase() {
assert!(parse_float::<f32>(Fragment::testing("nan")).is_err());
}
#[test]
fn test_invalid_multiple_dots() {
assert!(parse_float::<f32>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_float::<f32>(Fragment::testing(" 1.5")), Ok(1.5));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_float::<f32>(Fragment::testing("1.5 ")), Ok(1.5));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_float::<f32>(Fragment::testing(" 1.5 ")), Ok(1.5));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_float::<f32>(Fragment::testing(" -3.14")), Ok(-3.14));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_float::<f32>(Fragment::testing("-3.14 ")), Ok(-3.14));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_float::<f32>(Fragment::testing(" -3.14 ")), Ok(-3.14));
}
}
mod f64 {
use crate::{fragment::Fragment, value::number::parse::parse_float};
#[test]
fn test_valid_zero() {
assert_eq!(parse_float::<f64>(Fragment::testing("0.0")), Ok(0.0));
}
#[test]
fn test_valid_positive() {
assert_eq!(parse_float::<f64>(Fragment::testing("1.23")), Ok(1.23));
}
#[test]
fn test_valid_negative() {
assert_eq!(parse_float::<f64>(Fragment::testing("-0.001")), Ok(-0.001));
}
#[test]
fn test_valid_integer() {
assert_eq!(parse_float::<f64>(Fragment::testing("42")), Ok(42.0));
}
#[test]
fn test_valid_scientific() {
assert_eq!(parse_float::<f64>(Fragment::testing("1e10")), Ok(1e10));
}
#[test]
fn test_valid_scientific_negative() {
assert_eq!(parse_float::<f64>(Fragment::testing("1e-10")), Ok(1e-10));
}
#[test]
fn test_overflow_positive() {
assert!(parse_float::<f64>(Fragment::testing("1e400")).is_err());
}
#[test]
fn test_overflow_negative() {
assert!(parse_float::<f64>(Fragment::testing("-1e400")).is_err());
}
#[test]
fn test_invalid_text() {
assert!(parse_float::<f64>(Fragment::testing("abc")).is_err());
}
#[test]
fn test_invalid_empty() {
assert!(parse_float::<f64>(Fragment::testing("")).is_err());
}
#[test]
fn test_invalid_whitespace() {
assert!(parse_float::<f64>(Fragment::testing(" ")).is_err());
}
#[test]
fn test_invalid_nan() {
assert!(parse_float::<f64>(Fragment::testing("NaN")).is_err());
}
#[test]
fn test_invalid_nan_mixed_case() {
assert!(parse_float::<f64>(Fragment::testing("NaN")).is_err());
}
#[test]
fn test_invalid_multiple_dots() {
assert!(parse_float::<f64>(Fragment::testing("1.2.3")).is_err());
}
#[test]
fn trimming_leading_space() {
assert_eq!(parse_float::<f64>(Fragment::testing(" 1.23")), Ok(1.23));
}
#[test]
fn trimming_trailing_space() {
assert_eq!(parse_float::<f64>(Fragment::testing("1.23 ")), Ok(1.23));
}
#[test]
fn trimming_both_spaces() {
assert_eq!(parse_float::<f64>(Fragment::testing(" 1.23 ")), Ok(1.23));
}
#[test]
fn trimming_negative_leading_space() {
assert_eq!(parse_float::<f64>(Fragment::testing(" -0.001")), Ok(-0.001));
}
#[test]
fn trimming_negative_trailing_space() {
assert_eq!(parse_float::<f64>(Fragment::testing("-0.001 ")), Ok(-0.001));
}
#[test]
fn trimming_negative_both_spaces() {
assert_eq!(parse_float::<f64>(Fragment::testing(" -0.001 ")), Ok(-0.001));
}
}
mod big_int {
use crate::{
fragment::Fragment,
value::{int::Int, number::parse::parse_primitive_int},
};
#[test]
fn test_parse_int_basic() {
let result = parse_primitive_int::<Int>(Fragment::testing("12345"));
assert!(result.is_ok());
assert_eq!(format!("{}", result.unwrap()), "12345");
}
#[test]
fn test_parse_int_negative() {
let result = parse_primitive_int::<Int>(Fragment::testing("-12345"));
assert!(result.is_ok());
assert_eq!(format!("{}", result.unwrap()), "-12345");
}
#[test]
fn test_parse_int_large() {
let result = parse_primitive_int::<Int>(Fragment::testing("123456789012345678901234567890"));
assert!(result.is_ok());
assert_eq!(format!("{}", result.unwrap()), "123456789012345678901234567890");
}
}
mod big_uint {
use crate::{
fragment::Fragment,
value::{number::parse::parse_primitive_uint, uint::Uint},
};
#[test]
fn test_parse_uint_basic() {
let result = parse_primitive_uint::<Uint>(Fragment::testing("12345"));
assert!(result.is_ok());
assert_eq!(format!("{}", result.unwrap()), "12345");
}
#[test]
fn test_parse_uint_large() {
let result = parse_primitive_uint::<Uint>(Fragment::testing("123456789012345678901234567890"));
assert!(result.is_ok());
assert_eq!(format!("{}", result.unwrap()), "123456789012345678901234567890");
}
}
}