Skip to content
Select theme

How to convert a String to a number

Short answer: Call parse on the string and name the number type — "42".parse::<i32>(), or let n: i32 = "42".parse(). It returns a Result; the error is a ParseIntError for integers and a ParseFloatError for floats.

parse is a method on str, so it works on a &str and on a String alike — a String derefs to a &str at the call site:

Run it with cargo run (cargo’s Compiling and Finished lines are not shown here):

i32: 42
u8: 42
f64: 3.14

Every integer type — i8 through i128, u8 through u128, isize, usize — and both floats implement FromStr, which is what parse calls. The target type has to come from somewhere, and there are two spellings: a let annotation or the turbofish ::<T>(), the same choice as How to tell the compiler the type of an empty Vec. Leave it out and the compiler cannot pick one — error[E0284]: type annotations needed.

When the string is not a number, the Err is a ParseIntError and its message says why:

"42" parsed as 42
"4 2" failed: invalid digit found in string
"forty-two" failed: invalid digit found in string
"" failed: cannot parse integer from empty string
"-7" parsed as -7

A signed type takes a leading -. "4 2" fails because parse reads the whole string and does not trim: a space is just another invalid character, so text from a file or a terminal wants trim() first — How to trim whitespace and strip characters. Parsing an integer from user input, where trimming and error reporting are the whole job, is a later article in this chapter.

The error also carries a kind you can match on instead of parsing the message: InvalidDigit, Empty, PosOverflow, NegOverflow. {:?} prints it as ParseIntError { kind: InvalidDigit }.

Overflow at parse time is about the type, not the digits:

"255" parsed as 255
"256" failed: number too large to fit in target type
"-1" failed: invalid digit found in string
"127" parsed as 127
"128" failed: number too large to fit in target type
"-128" parsed as -128
"-129" failed: number too small to fit in target type

256 is a well-formed integer that does not fit in a u8, so it is PosOverflow; -1 in an unsigned type is not an overflow at all but InvalidDigit, because a - is not part of an unsigned literal. Arithmetic that overflows while the program runs is a different problem, with a different answer.

f32 and f64 go through the same method and fail with ParseFloatError:

"3.14" parsed as 3.14
"1e3" parsed as 1000.0
"inf" parsed as inf
"NaN" parsed as NaN
".5" parsed as 0.5
"abc" failed: invalid float literal

The float parser takes exponent notation, inf and infinity in any letter case, NaN, and a leading or trailing dot. An empty string is its own kind — ParseFloatError { kind: Empty }, “cannot parse float from empty string” — and there is no overflow error: a literal too large for f64, like 1e400, parses as inf instead of failing.

listening on 8080
error: "99999" is not a port: number too large to fit in target type
error: "http" is not a port: invalid digit found in string

map_err converts the typed error into whatever the surrounding code reports while keeping the original message. Where a missing number has an obvious default, unwrap_or(0) beats a match. In a function that already returns a compatible Result, ? propagates the same error untouched. unwrap belongs to strings the source can see — a literal or a constant — where the parse cannot fail.

The next article in this chapter goes the other way: converting a number back into a String.