use crate::deserialize::Item;
use nom::character::streaming::{char, digit1};
use nom::error::{ErrorKind, ParseError};
use nom::sequence::preceded;
use nom::Parser;
use nom::{AsChar, IResult, Input};
use core::cell::Cell;
use alloc::str::FromStr;
use alloc::string::ToString;
pub fn int<'a, I: Input + ToString, E: ParseError<I>>(input: I) -> IResult<I, Item, E>
where <I as Input>::Item: AsChar {
let string_int = preceded(char('-'), digit1).parse(input)?;
Ok((string_int.0, Item::Int(0 - i64::from_str(string_int.1.to_string().as_str()).map_err(|_| {
nom::Err::Error(E::from_error_kind(string_int.1, ErrorKind::Digit))
})?)))
}
#[test]
pub fn test_int() {
use nom::Finish;
use crate::DeserializeError;
match int::<&str, DeserializeError<&str>>("-727nya").finish() {
Ok(item) => assert_eq!(item, ("nya", Item::Int(-727))),
Err(err) => panic!("{}", err),
}
}
pub fn uint<'a, I: Input + ToString, E: ParseError<I>>(input: I) -> IResult<I, Item, E>
where <I as Input>::Item: AsChar {
let string_int = digit1.parse(input)?;
Ok((string_int.0, Item::UInt(u64::from_str(string_int.1.to_string().as_str()).map_err(|_| {
nom::Err::Error(E::from_error_kind(string_int.1, ErrorKind::Digit))
})?)))
}
#[test]
pub fn test_uint() {
use nom::Finish;
use crate::DeserializeError;
match uint::<&str, DeserializeError<&str>>("727nya").finish() {
Ok(item) => assert_eq!(item, ("nya", Item::UInt(727))),
Err(err) => panic!("{}", err),
}
}
fn digit_or_dot_1<I: Input, E: ParseError<I>>(input: I) -> IResult<I, I, E>
where <I as Input>::Item: AsChar {
let dot_found = Cell::new(false);
let result = input.split_at_position1(|c| {
let dot = c.as_char() == '.';
if dot {
dot_found.replace(true);
}
!(dot | matches!(c.as_char(), '0'..='9'))
}, ErrorKind::Digit);
if !dot_found.get() {
Err(nom::Err::Error(E::from_error_kind(input, ErrorKind::IsNot)))
} else {
result
}
}
pub fn float<I: Input + ToString, E: ParseError<I>>(input: I) -> IResult<I, Item, E>
where <I as Input>::Item: AsChar {
let string_float = digit_or_dot_1.parse(input)?;
Ok((string_float.0, Item::Float(f64::from_str(string_float.1.to_string().as_str()).map_err(|_| {
nom::Err::Error(E::from_error_kind(string_float.1, ErrorKind::Digit))
})?)))
}
#[test]
pub fn test_float() {
use nom::Finish;
use crate::DeserializeError;
match float::<&str, DeserializeError<&str>>("7.27nya").finish() {
Ok(item) => assert_eq!(item, ("nya", Item::Float(7.27))),
Err(err) => panic!("{}", err),
}
match float::<&str, DeserializeError<&str>>("727nya").finish() {
Err(err) => match err {
DeserializeError::ParseError(_, kind) => {
assert_eq ! (kind, ErrorKind::IsNot);
}
_ => assert!(false),
},
Ok(_) => assert!(false),
}
}