Parse
Strings can be converted to integers in Rust with the parse()
function. We can parse just parts of strings with get()
. With the TurboFish operator, we can parse to specific types.
With the to_string
function, we can convert an integer into a string
. And then parse()
can convert the string
back into a u32
integer.
Here we want to parse to a specific type like a usize
. We can use the special Rust TurboFish operator in an if-let
statement to parse to a usize
.
parse()
, we can unwrap()
the result. But using if let Ok()
is a more elegant and clean syntax for parse.fn main() { let data = "1200"; // Parse to a specific type with TurboFish. if let Ok(result) = data.parse::<usize>() { println!("USIZE RESULT: {}", result); } }USIZE RESULT: 1200
Suppose we have some digits inside of another string
. We can extract a slice from the string
with a function like get()
. Then we can parse the number.
len()
to extract the range of characters up to 2 places before the end. We unwrap()
the result.fn main() { let value = "x 1234 y"; // Get inner part of string we want to parse. let inner_part = value.get(2..value.len() - 2).unwrap(); println!("INNER PART: {}", inner_part); // Parse the inner part. let result: u32 = inner_part.parse().unwrap(); println!("PARSED: {0}", result); }INNER PART: 1234 PARSED: 1234
str
Sometimes we want to convert a string
to an integer, and other times we want the opposite conversion. Here we convert an integer into a str
with to_string
.
fn main() { // Convert an int into a string, and then back into an int. // ... Use u32 to mean 32-bit int. let value = 5678; let result = value.to_string(); let parsed: u32 = result.parse().unwrap(); // Results. println!("RESULT: {} {} {}", value, result, parsed); }RESULT: 5678 5678 5678
String
arrayOften we are dealing with arrays of str
in Rust programs. We can parse these with a for
-loop over the array—the concepts remain the same.
fn main() { let values: [&str; 2] = ["123", "456"]; // Loop over string array, parsing each value. for value in &values { let parsed: u32 = value.parse().unwrap(); println!("PARSED+1: {}", parsed + 1); } }PARSED+1: 124 PARSED+1: 457
If we do not need many features, we can write a simple loop-based parsing function in Rust. This just iterates over bytes and multiplies the result by 10.
fn parse_fast(value: &str) -> i32 { // Parse with bytes loop. let mut result = 0; for b in value.bytes() { result = 10 * result + ((b as i32) - 48); } result } fn main() { println!("RESULT: {}", parse_fast("123") == 123); }RESULT: true
If we have a Rust program that parses i32
values excessively, should we use the custom optimized function? This benchmark tests the function.
i32
result.parse_fast
function, which returns a value directly and does not support error handling.use std::time::*; fn parse_fast(value: &str) -> i32 { // Parse with bytes loop. let mut result = 0; for b in value.bytes() { result = 10 * result + ((b as i32) - 48); } result } fn main() { if let Ok(max) = "100000000".parse::<usize>() { let number = String::from("123"); // Version 1: use parse function. let t0 = Instant::now(); for _ in 0..max { if let Ok(result) = number.parse::<i32>() { if result != 123 { return; } } } println!("{}", t0.elapsed().as_millis()); // Version 2: use simple parse fast function. let t1 = Instant::now(); for _ in 0..max { if parse_fast(&number) != 123 { return; } } println!("{}", t1.elapsed().as_millis()); } }355 ms parse 31 ms parse_fast
With parse()
we can convert a string
into numeric types like u32
. We must unwrap
the result of parse. To parse ranges of strings, we can first call get()
.