Rust Parsing Numbers
Number parsing turns text into a number in a chosen base or size. A failed parse names its reason.
parse is from_str in disguise
Both spellings run the same code. from_str needs the FromStr trait in scope:
use std::str::FromStr;
let n = i32::from_str("42").unwrap();
let m: i32 = "42".parse().unwrap();
println!("{} {}", n, m);Read hex and binary text: from_str_radix
The second input is the base. Hex digits run past 9 into the letters a to f:
println!("{:?}", u32::from_str_radix("ff", 16));
println!("{:?}", u32::from_str_radix("1010", 2));Prefixes are not digits
Text like 0xff carries a label the parser does not want. Strip it first, or the parse fails:
let hex = "0xff";
let digits = hex.strip_prefix("0x").unwrap();
println!("{:?}", u32::from_str_radix(digits, 16));
println!("{:?}", u32::from_str_radix("0xff", 16));A minus sign is welcome, underscores are not
A sign belongs to the number. Underscores only decorate literals in your source code — in text read from outside, they are invalid digits:
println!("{:?}", i32::from_str_radix("-1010", 2));
println!("{:?}", i32::from_str_radix("1_000", 10));Ask why it failed
Print the error with {:?}. It names the reason: too big for the type, or no text at all:
let too_big = "999999999999".parse::<i32>();
println!("{:?}", too_big);
let empty = "".parse::<i32>();
println!("{:?}", empty);Floats read exponents and special words
A float parse accepts scientific notation, and even the special values by name:
println!("{}", "2.5e3".parse::<f64>().unwrap());
println!("{}", "inf".parse::<f64>().unwrap());Example
fn main() {
let colour = "0xFF8000";
let hex_part = colour.strip_prefix("0x").unwrap();
let value = u32::from_str_radix(hex_part, 16).unwrap();
println!("colour value = {}", value);
let binary = u32::from_str_radix("1111", 2).unwrap();
println!("binary 1111 = {}", binary);
let age: Result<u8, _> = "300".parse();
println!("age 300 as u8 = {:?}", age);
let temp: Result<i32, _> = "-12".parse();
println!("temp = {:?}", temp);
}Key points
- parse is a thin front door: underneath, it calls from_str from the FromStr trait — and you can call Type::from_str(text) directly
- Use Type::from_str_radix(text, radix) to read a number written in another base.
- The radix may be from 2 to 36.
- Strip prefixes yourself.
- from_str_radix("0xff", 16) fails, because the 0x is not a digit.
- Clean the text first, for example with strip_prefix.
- A leading + or - sign is welcome in parsed text.
- Underscores and spaces are not.
- Underscores belong in literals you write in code, not in text read while running.
- A failed parse names its reason.
- Empty means empty text.
- InvalidDigit means bad characters.
- PosOverflow or NegOverflow means the number does not fit the type.
- Floats parse more than digits.
- "2.5e3" becomes 2500.0.
- And "inf" and "NaN" become the special float values.
- Real text arrives as hex inside a colour code or as binary from a sensor.
- Number parsing reads text as a number in the base and size code asks for.
In this example, a web colour arrives as text. strip_prefix removes the 0x label, and from_str_radix with radix 16 reads the hex digits FF8000 as the number 16744448. The same function with radix 2 reads binary 1111 as 15. The last two lines keep the Result instead of unwrapping it. 300 cannot fit in a u8, so the parse reports PosOverflow. Meanwhile -12 fits an i32 easily and arrives as Ok(-12). Nothing crashed — every failure arrived as a value the program could inspect.
Note
The radix may go up to 36 because digits run 0–9 and then a–z: u32::from_str_radix("z", 36) is Ok(35).
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
What does u32::from_str_radix("ff", 16) return?