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.
This program shows 2 example methods, add1
and add2
. These both receive two byte
values (u8
) and then return an unsigned 32-bit integer.
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
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
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
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.
try_into
to cast to a 2-element array.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]
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.
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.