Repository: typst/typst
File: crates/typst-library/src/foundations/int.rs (Rust)

Code before:
    /// ```example
    /// #int(false) \
    /// #int(true) \
    /// #int(2.7) \
    /// #int(decimal("3.8")) \
    /// #(int("27") + int("4")) \
    /// #(int("beef", base: 16))
    /// ```
    #[func(constructor)]
    pub fn construct(
        /// The value that should be converted to an integer.
        value: Spanned<ToInt>,
        /// The base (radix) for parsing strings, between 2 and 36.
        #[named]
        #[default(Spanned::new(Base::Default, Span::detached()))]
        base: Spanned<Base>,
    ) -> SourceResult<i64> {
        Ok(match value.v {
            ToInt::Int(n) => match base.v {
                Base::User(_) => bail!(base.span, "base is only supported for strings"),
                _ => n,
            },
            ToInt::Str(s) => {
                let base_value = base.v.value();
                let radix: u32 = match base_value {
                    2..=36 => base_value.try_into().unwrap(),
                    _ => bail!(base.span, "base must be between 2 and 36"),
                };

                match s.strip_prefix('-').or_else(|| s.strip_prefix(repr::MINUS_SIGN)) {
                    // Negative (without minus)
                    Some(s) => {
                        // Parse the digits part into u64
                        //  => abs(i64::MIN) fits into u64
                        let bigger = u64::from_str_radix(s, radix)
                            .map_err(|e| parse_str_error(e.kind(), value.span))?;

                        // Number wouldn't fit into i64
                        if bigger > i64::MIN.unsigned_abs() {
                            return Err(parse_str_error(
                                &IntErrorKind::NegOverflow,
                                value.span,
                            ));
                        }

                        bigger.wrapping_neg() as i64
                    }
                    // Positive
                    None => i64::from_str_radix(&s, radix)
                        .map_err(|e| parse_str_error(e.kind(), value.span))?,
                }

Review comment (suggestion):
```suggestion
                    2..=36 => base_value as u32
```

Code after:
    /// ```example
    /// #int(false) \
    /// #int(true) \
    /// #int(2.7) \
    /// #int(decimal("3.8")) \
    /// #(int("27") + int("4")) \
    /// #(int("beef", base: 16))
    /// ```
    #[func(constructor)]
    pub fn construct(
        /// The value that should be converted to an integer.
        value: Spanned<ToInt>,
        /// The base (radix) for parsing strings, between 2 and 36.
        #[named]
        #[default(Spanned::new(Base::Default, Span::detached()))]
        base: Spanned<Base>,
    ) -> SourceResult<i64> {
        Ok(match value.v {
            ToInt::Int(n) => match base.v {
                Base::User(_) => bail!(base.span, "base is only supported for strings"),
                _ => n,
            },
            ToInt::Str(s) => {
                let base_value = base.v.value();
                let radix: u32 = match base_value {
                    2..=36 => base_value as u32,
                    _ => bail!(base.span, "base must be between 2 and 36"),
                };

                match s.strip_prefix('-').or_else(|| s.strip_prefix(repr::MINUS_SIGN)) {
                    // Negative (without minus)
                    Some(s) => {
                        // Parse the digits part into u64
                        //  => abs(i64::MIN) fits into u64
                        let bigger = u64::from_str_radix(s, radix)
                            .map_err(|e| parse_str_error(e.kind(), base))
                            .at(value.span)?;

                        // Number wouldn't fit into i64
                        if bigger > i64::MIN.unsigned_abs() {
                            return Err(parse_str_error(
                                &IntErrorKind::NegOverflow,
                                base,
                            ))
                            .at(value.span);
                        }

                        bigger.wrapping_neg() as i64
                    }
                    // Positive
                    None => i64::from_str_radix(&s, radix)