mod digits;
mod type_descriptor;
mod panic;
pub use digits::*;
pub use type_descriptor::*;
pub use panic::*;
#[macro_export]
macro_rules! t {
($ty: ident) => {
$crate::Integer::<{
$crate::literal_parse::get_signedness(stringify!($ty))
}, {
const PARAMS_RESULT: Result<(bool, usize, u8), ($crate::literal_parse::TypeDescriptorError, &'static str)> = $crate::literal_parse::get_integer_params(stringify!($ty));
match PARAMS_RESULT {
Ok((_, bw, _)) => $crate::literal_parse::get_size_params_from_bits(bw).0,
Err(_) => $crate::panic_type_descriptor_error!(PARAMS_RESULT),
}
}, {
match $crate::literal_parse::get_integer_params(stringify!($ty)) {
Ok((_, bw, _)) => $crate::literal_parse::get_size_params_from_bits(bw).1,
_ => 0,
}
}, {
$crate::literal_parse::get_overflow_mode(stringify!($ty))
}>
};
($($_: tt)*) => {
compile_error!("expected integer type descriptor, e.g. `I256` or `U512w`");
};
}
#[macro_export]
macro_rules! n {
($literal_str: literal) => {
const {
const PARTS: (bool, u32, &[u8], &str) = $crate::literal_parse::get_negative_radix_digits_type_descriptor(stringify!($literal_str));
let (negative, radix, digit_bytes, _) = PARTS;
const TYPE_DESCRIPTOR_BYTES: &str = PARTS.3;
const PARAMS: (bool, Result<bool, ($crate::literal_parse::TypeDescriptorError, &str)>, usize, usize, u8) = $crate::literal_parse::get_integer_params_fallback(TYPE_DESCRIPTOR_BYTES);
const IMPLICIT: bool = PARAMS.0;
const N: usize = PARAMS.2;
const B: usize = PARAMS.3;
const OM: u8 = PARAMS.4;
const S: Result<bool, ($crate::literal_parse::TypeDescriptorError, &str)> = PARAMS.1;
type Parser = $crate::literal_parse::IntLiteralParser<{ IMPLICIT }, { match S {
Ok(s) => s,
Err(_) => $crate::panic_type_descriptor_error!(S),
} }, { N }, { B }, { OM }>;
Parser::parse(negative, radix, digit_bytes)
}
};
($ty: ident) => {
$crate::Integer::<{
$crate::literal_parse::get_signedness(stringify!($ty))
}, {
const PARAMS_RESULT: Result<(bool, usize, u8), ($crate::literal_parse::TypeDescriptorError, &'static str)> = $crate::literal_parse::get_integer_params(stringify!($ty));
match PARAMS_RESULT {
Ok((_, bw, _)) => $crate::literal_parse::get_size_params_from_bits(bw).0,
Err(_) => $crate::panic_type_descriptor_error!(PARAMS_RESULT),
}
}, {
match $crate::literal_parse::get_integer_params(stringify!($ty)) {
Ok((_, bw, _)) => $crate::literal_parse::get_size_params_from_bits(bw).1,
_ => 0,
}
}, {
$crate::literal_parse::get_overflow_mode(stringify!($ty))
}>
};
($($_: tt)*) => {
compile_error!("expected integer literal or integer type descriptor, e.g. `0xFFFF`, `123456U1024s`, `I256` or `U512w`");
};
}
#[doc(hidden)]
#[inline]
pub const fn get_negative_radix_digits_type_descriptor(literal_str: &str) -> (bool, u32, &[u8], &str) {
let bytes = literal_str.as_bytes();
let negative = !bytes.is_empty() && bytes[0] == b'-';
let bytes = if negative { bytes.split_at(1).1 } else { bytes };
let radix = if bytes.len() >= 2 {
match (bytes[0], bytes[1]) {
(b'0', b'b') => 2,
(b'0', b'o') => 8,
(b'0', b'x') => 16,
_ => 10,
}
} else {
10
};
let bytes = if radix == 10 {
bytes
} else {
bytes.split_at(2).1
};
let mut last_digit_index = bytes.len(); let mut i = 0; while i < bytes.len() {
let c = bytes[i] as char;
let is_digit = match radix {
16 => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == '_',
_ => (c >= '0' && c <= '9') || c == '_' ,
};
if !is_digit {
last_digit_index = i;
break;
}
i += 1;
}
let (digit_bytes, type_descriptor_bytes) = bytes.split_at(last_digit_index);
let type_descriptor = unsafe { core::str::from_utf8_unchecked(type_descriptor_bytes) }; (negative, radix, digit_bytes, type_descriptor)
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
#[test]
fn test_n_macro() {
type I256 = t!(I256);
let a: I256 = n!(0x_ABCDEF_);
assert_eq!(a.to_str_radix(16), "abcdef");
let b = n!(1_23_456U511s);
assert_eq!(b.to_str_radix(10), "123456");
let c = n!(0o123_45_670U257w);
assert_eq!(c.to_str_radix(8), "12345670");
type I24p = t!(I24p);
let d: I24p = n!(0b101010111100110111_I24p);
assert_eq!(d.to_str_radix(2), "101010111100110111");
}
}