ProgrammingFullstack Developer

Explain how reading and parsing strings to numbers (e.g., from String to i32) is implemented in Rust? What pitfalls exist when using the parse method, and how to properly handle conversion errors?

Pass interviews with Hintsage AI assistant

Answer

Rust provides convenient standard means for converting strings to numbers via the FromStr trait. The most commonly used method is .parse::<T>(), which can be called on strings and slices.

Background

In many languages, converting a string to a number is a common task, but in Rust, it is done as safely and transparently as possible; error handling is part of the standard library contract rather than runtime exceptions.

Problem

.parse::<T>() returns a result type Result<T, ParseIntError> (or similar for other types), which forces explicit handling of failures. A common mistake is to ignore the possibility of error, using unwrap() without analysis, which threatens a program crash on incorrect input rather than a proper error message.

Solution

To convert strings, use the parse method. Its signature:

let num: i32 = "42".parse().unwrap();

But it is better to handle the error:

let s = "abc"; match s.parse::<i32>() { Ok(n) => println!("Received number: {}", n), Err(e) => println!("Parsing error: {e}"), }

Key features:

  • For each numeric type, FromStr is implemented, but exact limitations are implicit: spaces, signs, overflow are handled differently
  • Errors are returned as Result, not through panic or exceptions
  • Any type with an implementation of FromStr (including user-defined ones) can be the target of .parse()

Tricky questions.

Can parse be used without specifying the result type?

No, without specifying the type (or implicit type inference), Rust will give an error because it doesn't understand which type to convert to.

What happens if you try to parse a string with non-numeric content into a number?

The method will return an error (Err(...)), not panic. The error implements the Debug trait, which is convenient for output.

let num: Result<u32, _> = "not_a_number".parse(); assert!(num.is_err());

Is it possible to use unwrap after parse if you are confident in the content?

Technically yes, but it's an anti-pattern. If the string is unexpectedly invalid, the program will crash.

Common mistakes and anti-patterns

  • Using unwrap() without error handling
  • Not using trim before conversion if the input is from the user
  • Type error when parsing (parse::<String>()) instead of the target numeric type

Real-life example

Negative case

A console utility reads a number from the user and uses .parse().unwrap(). In case of a random incorrect input, the program suddenly crashes, and the user does not understand the reason.

Pros:

  • Simpler code

Cons:

  • Potential program exit; poor user experience

Positive case

The input is first trimmed of spaces, and parse is used in a match scenario or if needed — map_err to return a custom error. Errors are handled correctly, providing a clear error message.

Pros:

  • The program does not crash on invalid input; errors are informative
  • The code is safer and clearer to maintain

Cons:

  • Slightly more code when handling input