Casts. In Rust we have several syntaxes for casting values—we can use the "as" keyword, or use the from and into functions. Usually these compile to the same thing.
With no casts, less code is generated, so programs will be faster—it is worth trying to avoid casting. But this is not always possible.
First example. This program shows 2 example methods, add1 and add2. These both receive two byte values (u8) and then return an unsigned 32-bit integer.
Tip When inspecting the output of this program when optimized by LLVM, the methods have the same instructions.
And The compiler can merge the two functions and just treat them as a single function.
fn add1(a: u8, b: u8) -> u32 {
// Cast both arguments to u32, then add them and return a u32.
(a as u32) + (b as u32)
}
fn add2(a: u8, b: u8) -> u32 {
// Same as first version.
(u32::from(a) + u32::from(b)).into()
}
fn main() {
println!("{}", add1(1, 2));
println!("{}", add2(1, 2));
}3
3
Into, String. With into() we have access to some more powerful conversion routines. For example, we can use into to get a Vector of bytes from a String.
fn print_bytes(values: Vec<u8>) {
for v in values {
println!("{v}");
}
}
fn main() {
let initial = "abc".to_string();
// String implements From::string into Vec of u8.
print_bytes(initial.into());
}97
98
99
Compile-time error. If we try to use into() to convert a type in a way that is not supported, we will get a trait bound error. This means our code needs to be changed.
fn test(values: Vec<char>) {
// Does not work.
}
fn main() {
let initial = "abc".to_string();
// String does not implement From::string into Vec of char.
test(initial.into());
}error[E0277]: the trait bound Vec<char>: From<String> is not satisfied
Cast slice, array. It is possible to use try_into() to cast a slice to an array of the same number of elements. The counts of elements must match or an error will be encountered.
Here We have a 4-element array, and then take a slice of 2 elements at its start. Then we use try_into to cast to a 2-element array.
Important After calling try_into() we must call unwrap() to get the inner value of the result.
fn print_array(values: [u8; 2]) {
println!("{:?}", values);
}
fn main() {
let data = [10, 20, 30, 40];
// Get slice from the array, and then convert to an array of the specified length.
print_array(data[..2].try_into().unwrap());
}[10, 20]
Performance notes. In the compiler, casts seem to cause the "movzw" instruction to be generated in assembly. If the casts are removed (due to a refactoring) these instructions are not needed.
So If we can refactor a method to not need any casting, it will have fewer instructions and may execute faster.
Tip Try changing the types of data structures to match those used in functions—avoiding casting in functions can speed them up.
Summary. Casting and conversions in Rust can be done with several syntaxes. These casts are not free in terms of performance, and avoiding them can speed up important functions.
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.
This page was last updated on May 22, 2023 (edit).