Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reading integers from text

Use a sized type’s parse method for external text. It borrows the string and returns an allocation-free Result. Decimal ASCII digits and an optional sign are accepted, with surrounding Unicode whitespace ignored. Numeric prefixes, underscores, and non-ASCII digits are not accepted.

def main() -> Result[(), AllocError | IoError]:
    print(str.repr(u8.parse(" 255 "))?)?
    print(str.repr(u8.parse("256"))?)?
    print(str.repr(i64.parse("hello"))?)?
    Ok(())
Result[u8, ParseError].Ok(255)
Result[u8, ParseError].Err(ParseError.OutOfRange)
Result[i64, ParseError].Err(ParseError.Invalid)

Functions returning the same error type can propagate parsing failures with ?. try_from reports a value that does not fit with RangeError.OutOfRange. Match it explicitly to combine parsing, calculation, and narrowing in a function returning ParseError:

def shade(percent: &str) -> Result[u8, ParseError]:
    number = i64.parse(percent)?
    scaled_result = checked:
        number * 255
    product = match scaled_result:
        case Ok(value):
            value
        case Err(_):
            return Err(ParseError.OutOfRange)
    hundred: Positive[i64] = 100
    scaled = product // hundred
    match u8.try_from(scaled):
        case Ok(value):
            Ok(value)
        case Err(error):
            match error:
                case RangeError.OutOfRange:
                    Err(ParseError.OutOfRange)

def main() -> Result[(), AllocError | IoError]:
    print(str.repr(shade("50"))?)?
    print(str.repr(shade("150"))?)?
    print(str.repr(shade("half"))?)?
    Ok(())
Result[u8, ParseError].Ok(127)
Result[u8, ParseError].Err(ParseError.OutOfRange)
Result[u8, ParseError].Err(ParseError.Invalid)

The local checked multiplication maps overflow to ParseError.OutOfRange, keeping this conversion helper’s public error contract. The positive divisor proves division cannot fail. No unchecked arithmetic or lossy cast is needed.