shrub_core/int_utils.rs
1//! Generic utilities.
2
3use crate::error;
4
5/// Trait for integer types that support parsing from strings with a radix.
6pub trait ParseIntRadix: Sized {
7 /// Parse a string as this integer type using the specified radix.
8 ///
9 /// # Errors
10 ///
11 /// Returns the underlying [`std::num::ParseIntError`] if `s` is empty,
12 /// contains invalid digits for `radix`, or overflows this type.
13 fn from_str_radix(s: &str, radix: u32) -> Result<Self, std::num::ParseIntError>;
14
15 /// Returns the name of the integer type as a static string.
16 fn type_name() -> &'static str;
17}
18
19macro_rules! impl_parse_int_radix {
20 ($t:ty) => {
21 impl ParseIntRadix for $t {
22 fn from_str_radix(s: &str, radix: u32) -> Result<Self, std::num::ParseIntError> {
23 Self::from_str_radix(s, radix)
24 }
25
26 fn type_name() -> &'static str {
27 stringify!($t)
28 }
29 }
30 };
31}
32
33impl_parse_int_radix!(u8);
34impl_parse_int_radix!(u16);
35impl_parse_int_radix!(i32);
36impl_parse_int_radix!(u32);
37impl_parse_int_radix!(usize);
38
39/// Parse the given string as an integer in the specified radix.
40///
41/// # Arguments
42///
43/// * `s` - The string to parse.
44/// * `radix` - The base to use for parsing.
45///
46/// # Type Parameters
47///
48/// * `T` - The integer type to parse. Must implement `ParseIntRadix`.
49///
50/// # Errors
51///
52/// Returns [`crate::error::ErrorKind::IntParseError`] if `s` is not a valid
53/// number in `radix` for the target type, including when it overflows.
54///
55/// # Examples
56///
57/// ```
58/// use shrub_core::int_utils::parse;
59///
60/// let result: u32 = parse("42", 10)?;
61/// assert_eq!(result, 42);
62///
63/// let result: u8 = parse("FF", 16)?;
64/// assert_eq!(result, 255);
65/// # Ok::<(), shrub_core::error::Error>(())
66/// ```
67pub fn parse<T: ParseIntRadix>(s: &str, radix: u32) -> Result<T, error::Error> {
68 T::from_str_radix(s, radix).map_err(|inner| {
69 error::ErrorKind::IntParseError {
70 s: s.to_owned(),
71 int_type_name: T::type_name(),
72 radix,
73 inner,
74 }
75 .into()
76 })
77}