#![deny(warnings)]
use num_traits::Num;
#[inline]
pub fn parse<T: Num>(input: &str) -> Result<T, T::FromStrRadixErr> {
let input = input
.trim()
.chars()
.filter(|&c| c != '_')
.collect::<String>();
if input.starts_with("0x") {
return T::from_str_radix(input.trim_start_matches("0x"), 16);
}
if input.starts_with("0b") {
return T::from_str_radix(input.trim_start_matches("0b"), 2);
}
if input.starts_with("0o") {
return T::from_str_radix(input.trim_start_matches("0o"), 8);
}
#[cfg(feature = "implicit-octal")]
{
if input.starts_with("0") {
return if input == "0" {
Ok(T::zero())
} else {
T::from_str_radix(input.trim_start_matches("0"), 8)
};
}
}
T::from_str_radix(&input, 10)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn turbofish_usize_dec() {
let s = "42";
let u = parse::<usize>(s).unwrap();
assert_eq!(42, u);
}
#[test]
fn deduct_usize_dec() {
let s = "42";
let u = parse(s).unwrap();
assert_eq!(42usize, u);
}
macro_rules! int_parse {
($type:ident, $s:literal, $e:literal) => {
#[test]
fn $type() {
let u: Result<$type, _> = crate::parse($s);
assert_eq!(Ok($e), u);
}
};
}
macro_rules! int_parse_err {
($type:ident, $s:literal) => {
mod err {
#[test]
fn $type() {
let u: Result<$type, _> = crate::parse($s);
assert!(u.is_err(), "expected Err(_), got = {:?}", u);
}
}
};
}
mod decimal {
int_parse!(usize, "42", 42);
int_parse!(isize, "42", 42);
int_parse!(u8, "42", 42);
int_parse!(i8, "42", 42);
int_parse!(u16, "42", 42);
int_parse!(i16, "42", 42);
int_parse!(u32, "42", 42);
int_parse!(i32, "42", 42);
int_parse!(u64, "42", 42);
int_parse!(i64, "42", 42);
int_parse!(u128, "42", 42);
int_parse!(i128, "42", 42);
}
mod decimal_negative {
int_parse!(isize, "-42", -42);
int_parse!(i8, "-42", -42);
}
mod hexadecimal {
int_parse!(usize, "0x42", 66);
int_parse!(isize, "0x42", 66);
int_parse!(u8, "0x42", 66);
int_parse!(i8, "0x42", 66);
int_parse!(u16, "0x42", 66);
int_parse!(i16, "0x42", 66);
int_parse!(u32, "0x42", 66);
int_parse!(i32, "0x42", 66);
int_parse!(u64, "0x42", 66);
int_parse!(i64, "0x42", 66);
int_parse!(u128, "0x42", 66);
int_parse!(i128, "0x42", 66);
}
mod octal_explicit {
int_parse!(usize, "0o42", 34);
int_parse!(isize, "0o42", 34);
int_parse!(u8, "0o42", 34);
int_parse!(i8, "0o42", 34);
int_parse!(u16, "0o42", 34);
int_parse!(i16, "0o42", 34);
int_parse!(u32, "0o42", 34);
int_parse!(i32, "0o42", 34);
int_parse!(u64, "0o42", 34);
int_parse!(i64, "0o42", 34);
int_parse!(u128, "0o42", 34);
int_parse!(i128, "0o42", 34);
}
#[cfg(feature = "implicit-octal")]
mod octal_implicit {
use super::*;
int_parse!(usize, "042", 34);
int_parse!(isize, "042", 34);
int_parse!(u8, "042", 34);
int_parse!(i8, "042", 34);
int_parse!(u16, "042", 34);
int_parse!(i16, "042", 34);
int_parse!(u32, "042", 34);
int_parse!(i32, "042", 34);
int_parse!(u64, "042", 34);
int_parse!(i64, "042", 34);
int_parse!(u128, "042", 34);
int_parse!(i128, "042", 34);
#[test]
fn issue_nr_0() {
let s = "0";
assert_eq!(0, parse::<usize>(s).unwrap());
assert_eq!(0, parse::<isize>(s).unwrap());
assert_eq!(0, parse::<i8>(s).unwrap());
assert_eq!(0, parse::<u8>(s).unwrap());
assert_eq!(0, parse::<i16>(s).unwrap());
assert_eq!(0, parse::<u16>(s).unwrap());
assert_eq!(0, parse::<i32>(s).unwrap());
assert_eq!(0, parse::<u32>(s).unwrap());
assert_eq!(0, parse::<i64>(s).unwrap());
assert_eq!(0, parse::<u64>(s).unwrap());
assert_eq!(0, parse::<i128>(s).unwrap());
assert_eq!(0, parse::<u128>(s).unwrap());
}
}
#[cfg(not(feature = "implicit-octal"))]
mod octal_implicit_disabled {
use super::*;
#[test]
fn no_implicit_is_int() {
let s = "042";
let u = parse::<usize>(s);
assert_eq!(Ok(42), u, "{:?}", u);
}
}
mod binary {
int_parse!(usize, "0b0110", 6);
int_parse!(isize, "0b0110", 6);
int_parse!(u8, "0b0110", 6);
int_parse!(i8, "0b0110", 6);
int_parse!(u16, "0b0110", 6);
int_parse!(i16, "0b0110", 6);
int_parse!(u32, "0b0110", 6);
int_parse!(i32, "0b0110", 6);
int_parse!(u64, "0b0110", 6);
int_parse!(i64, "0b0110", 6);
int_parse!(u128, "0b0110", 6);
int_parse!(i128, "0b0110", 6);
}
mod binary_negative {
int_parse_err!(i8, "0b1000_0000");
int_parse!(i8, "0b-0111_1111", -127);
}
mod underscore {
int_parse!(usize, "0b0110_0110", 102);
int_parse!(isize, "0x0110_0110", 17_826_064);
int_parse!(u64, "0o0110_0110", 294_984);
int_parse!(u128, "1_100_110", 1_100_110);
#[cfg(feature = "implicit-octal")]
mod implicit_octal {
int_parse!(i128, "0110_0110", 294_984);
}
#[cfg(not(feature = "implicit-octal"))]
mod implicit_octal {
int_parse!(i128, "0110_0110", 1_100_110);
}
}
}