Skip to main content

midenc_hir/ir/parse/
from_str_radix.rs

1use crate::{Felt, Immediate};
2
3pub trait FromStrRadix: Sized {
4    type Error: core::error::Error;
5
6    fn try_from_str_radix(source: &str, radix: u32) -> Result<Self, Self::Error>;
7}
8
9macro_rules! from_str_radix_impl {
10    ($($t:ty),*) => {
11        $(
12            impl FromStrRadix for $t {
13                type Error = core::num::ParseIntError;
14
15                #[inline]
16                fn try_from_str_radix(source: &str, radix: u32) -> Result<Self, Self::Error> {
17                    <$t>::from_str_radix(source, radix)
18                }
19            }
20        )*
21    }
22}
23
24from_str_radix_impl!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
25
26#[doc(hidden)]
27#[derive(Debug, thiserror::Error)]
28pub enum FeltOutOfRangeError {
29    #[error(transparent)]
30    Parse(#[from] core::num::ParseIntError),
31    #[error("invalid felt: {0} is larger than the field modulus")]
32    OutOfRange(u64),
33}
34
35impl FromStrRadix for Felt {
36    type Error = FeltOutOfRangeError;
37
38    fn try_from_str_radix(source: &str, radix: u32) -> Result<Self, Self::Error> {
39        let value = u64::try_from_str_radix(source, radix).map_err(FeltOutOfRangeError::Parse)?;
40        Felt::new(value).map_err(|err| FeltOutOfRangeError::OutOfRange(err.as_u64()))
41    }
42}
43
44impl FromStrRadix for Immediate {
45    type Error = core::num::ParseIntError;
46
47    fn try_from_str_radix(source: &str, radix: u32) -> Result<Self, Self::Error> {
48        if source.starts_with('-') {
49            let n = i128::try_from_str_radix(source, radix)?;
50            match n {
51                n if n > (i64::MAX as i128) || n < (i64::MIN as i128) => Ok(Immediate::I128(n)),
52                n if n > (i32::MAX as i128) || n < (i32::MIN as i128) => {
53                    Ok(Immediate::I64(n as i64))
54                }
55                n if n > (i16::MAX as i128) || n < (i16::MIN as i128) => {
56                    Ok(Immediate::I32(n as i32))
57                }
58                n if n > (i8::MAX as i128) || n < (i8::MIN as i128) => Ok(Immediate::I16(n as i16)),
59                n @ (0i128..=1i128) => Ok(Immediate::I8(n as i8)),
60                n => Ok(Immediate::I1(n == 1i128)),
61            }
62        } else {
63            let n = u128::try_from_str_radix(source, radix)?;
64            match n {
65                n if n > (u64::MAX as u128) => Ok(Immediate::U128(n)),
66                n if n > (u32::MAX as u128) => Ok(Immediate::U64(n as u64)),
67                n if n > (u16::MAX as u128) => Ok(Immediate::U32(n as u32)),
68                n if n > (u8::MAX as u128) => Ok(Immediate::U16(n as u16)),
69                n if n > 1u128 => Ok(Immediate::U8(n as u8)),
70                n => Ok(Immediate::I1(n == 1u128)),
71            }
72        }
73    }
74}