🎓 A1Learner
🔍

Rust Parsing Strings

Parsing turns text into a value of another type. "42".parse() builds a value from text through the FromStr trait.

parse returns a Result

Use text.parse() to turn text into another type. It returns a Result, because the text might not fit the type:

let good: Result<i32, _> = "42".parse();
let bad: Result<i32, _> = "abc".parse();
println!("{:?} {:?}", good, bad);

Name the target type two ways

Rust must know the target type. Write it as an annotation, or inside the call with the turbofish — the ::<...> part:

let a: i32 = "5".parse().unwrap();
let b = "10".parse::<i32>().unwrap();
println!("sum = {}", a + b);

Numbers, bool and char all parse

parse works for any type that implements the FromStr trait. The standard library implements it for numbers, bool and char:

let flag: bool = "true".parse().unwrap();
let letter: char = "x".parse().unwrap();
println!("{} {}", flag, letter);

Teach parse your own type

Implement FromStr for your type: name type Err, and write from_str. Inside, parse the pieces and return Ok, or pass an error out with ?:

impl FromStr for Age {
    type Err = ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Age(s.trim().parse()?))
    }
}

Other bases use a different tool

Numbers written in other bases are not the job of parse. from_str_radix reads the base you name — the Parsing Numbers lesson goes deeper:

println!("{:?}", u32::from_str_radix("ff", 16));

parse does not trim

Spaces are not skipped for you. This text fails, even though the number inside is fine:

println!("{:?}", " 42 ".parse::<i32>());

Example

use std::num::ParseIntError;
use std::str::FromStr;
#[derive(Debug)]
struct Age(u8);
impl FromStr for Age {
    type Err = ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let n: u8 = s.trim().parse()?;
        Ok(Age(n))
    }
}
fn main() {
    let parsed: i32 = "5".parse().unwrap();
    let turbo = "10".parse::<i32>().unwrap();
    println!("sum = {}", parsed + turbo);
    let flag: bool = "true".parse().unwrap();
    println!("flag = {}", flag);
    let age: Age = " 36 ".parse().unwrap();
    println!("age = {}", age.0);
    println!("bad = {:?}", "abc".parse::<i32>());
}

Key points

  • Going the other way is .to_string(): every Display type gets it for free — implement Display, never ToString by hand
  • Some text has a specialist parser instead.
  • A date string goes to one parser.
  • It goes to chrono's NaiveDate::parse_from_str("22/10/2026", "%d/%m/%Y").
  • A web address goes to the url crate.
  • Url::parse hands back three things.
  • It hands back the scheme.
  • It hands back the host and query pairs.
  • They are already split.
  • Call .trim() first when spaces are allowed, as the User Input lesson did.
  • Parsing reads text and builds a typed value from it.

In this example, Age teaches parse a skill. It teaches it how to build an Age from text. from_str trims the text. It parses it as a u8. It wraps it. In main, the first two lines show both ways. They show how to name the target type. One way is the annotation on parsed. The other is the turbofish on turbo. 5 + 10 prints sum = 15. A bool parses too, because the standard library implements FromStr for it. Then " 36 " becomes an Age. Our own impl does that. The last line shows failure staying calm. "abc" cannot be a number. So parse returns an Err. Nothing crashes.

Note

parse trims nothing by itself: " 42 ".parse::<i32>() fails with an invalid-digit error.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

What must a type implement before "text".parse() can build a value of that type?