use crate::parser::{code, prelude::*, Input, ParseError, ParseResult};
use super::{LiteralError, Radix};
#[allow(clippy::module_name_repetitions)]
pub fn recognize_natural(radix: Radix) -> impl for<'a> Fn(Input<'a>) -> ParseResult<'a, &'a str> {
move |input| {
recognize(tuple((opt(char('+')), radix.digit1())))(input).map_err(|mut err| {
err.push(input, code::ERR_NATURAL_FORMAT, LiteralError::NaturalFormat);
err
})
}
}
pub fn natural(radix: Radix) -> impl for<'a> Fn(Input<'a>) -> ParseResult<'a, u64> {
move |input| {
let (output, input) = recognize_natural(radix)(input)?;
let value = u64::from_str_radix(output, radix.base()).map_err(|_| {
ParseError::new(input, code::ERR_NATURAL, LiteralError::Natural).and_semantic()
})?;
Ok((value, input))
}
}
#[cfg(test)]
mod tests {
use super::*;
const NATURALS: [(&str, Radix); 28] = [
("0", Radix::Binary),
("0", Radix::Octal),
("0", Radix::Decimal),
("0", Radix::Hexadecimal),
("1", Radix::Binary),
("1", Radix::Octal),
("1", Radix::Decimal),
("1", Radix::Hexadecimal),
("0101010", Radix::Binary),
("01234567", Radix::Octal),
("0123456789", Radix::Decimal),
("0123456789", Radix::Hexadecimal),
("abcdef", Radix::Hexadecimal),
("ABCDEF", Radix::Hexadecimal),
("+0", Radix::Binary),
("+0", Radix::Octal),
("+0", Radix::Decimal),
("+0", Radix::Hexadecimal),
("+1", Radix::Binary),
("+1", Radix::Octal),
("+1", Radix::Decimal),
("+1", Radix::Hexadecimal),
("+0101010", Radix::Binary),
("+01234567", Radix::Octal),
("+0123456789", Radix::Decimal),
("+0123456789", Radix::Hexadecimal),
("+abcdef", Radix::Hexadecimal),
("+ABCDEF", Radix::Hexadecimal),
];
#[test]
fn recognize_natural_success() {
for (value, radix) in &NATURALS {
let input = Input::new(value);
let result = recognize_natural(*radix)(input);
assert_eq!(result, Ok((*value, Input::new(""))));
}
}
#[test]
fn natural_success() {
for (value, radix) in &NATURALS {
let input = Input::new(value);
let result = natural(*radix)(input);
assert_eq!(
result,
Ok((
u64::from_str_radix(value, radix.base()).unwrap(),
Input::new("")
))
);
}
}
}