If you are new to Rust then From (From
) and Into (into
) traits might sound confusing to you, but they are interesting trait systems of Rust. In this tutorial, we will learn From and Into traits with examples.
The From and Into traits are inherently linked, and this is actually part of its implementation. If you are able to convert type A from type B, then it should be easy to believe that we should be able to convert type B to type A.
From Trait
The From
trait provides the ability to create a conversion trait, which allows you to convert values of one type into values of another type. For example, the standard library implements impl From<&'_ str> for String
which allows you to generate a String
from a &str
.
For example, we can easily convert a &str
into a String
let my_str = "Hello Intmain"; let my_string = String::from(my_str);
Another example of from trait:
Suppose we want to implement our own From trait From<String> for SplitName
. This would allow us to split any given name separated by whitespace into Struct containing first and last names. This can be done easily using From trait. Below is an example of the same.
use std::convert::From; #[derive(Debug)] struct SplitName{ first_name: String, last_name: String, } impl From<String> for SplitName { fn from(item: String) -> Self { let name_vector:Vec<&str> = item.split_whitespace().collect(); SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string(), } } } fn main() { let from_example = SplitName::from("Int Main".to_string()); println!("The name is {:?}", from_example); }
Output
The name is: SplitName { first_name: "Int", last_name: "Main" }
The From
is also very useful when performing error handling. When constructing a function that is capable of failing, the return type will generally be of the form Result<T, E>
.
Note: This trait must not fail. The From trait is intended for perfect conversions. If the conversion can fail or is not perfect, use TryFrom
Into Trait
The Into
trait is the opposite of the From
trait. The Implementation of From automatically provides the implementation of Into trait and one should avoid implementing Into
trait and instead implement From
trait.
Using the Into
trait will typically require specification of the type to convert into as the compiler is unable to determine this most of the time.
For example, we can easily convert a &str
into a String
let my_str = "Hello Intmain"; let my_string :String = my_str.into();
Taking the above example again to split any given name separated by whitespace into Struct containing first and last names, we can split the name directly by calling the .into()
to the given name after converting it into the string. Here we are required to provide the specification as: let into_example :SplitName = "Int Main".to_string().into();
Here’s the complete code to convert a name into SplitName using the From and Into traits:
use std::convert::From; #[derive(Debug)] struct SplitName{ first_name: String, last_name: String, } impl From<String> for SplitName { fn from(item: String) -> Self { let name_vector:Vec<&str> = item.split_whitespace().collect(); SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string(), } } } fn main() { let from_example = SplitName::from("Int Main".to_string()); println!("The name is using from: {:?}", from_example); let into_example :SplitName = "Int Main".to_string().into(); println!("TThe name is using into: {:?}", into_example); }
Output
The name is using from: SplitName { first_name: "Int", last_name: "Main" } The name is using into: SplitName { first_name: "Int", last_name: "Main" }
You’re free to use into()
and from()
both and it’s up to you to decide which one feels the most expressive to your code but prefers using Into
over From
when specifying trait bounds on a generic function to ensure that types that only implement Into
can be used as well.
Note: This trait must not fail. If the conversion can fail, use TryInto
.
Conclusion
The “From” and “Into” traits in Rust are used to perform type conversions. The “From” trait allows you to convert values of one type into values of another type by implementing the from
method. The “Into” trait is a simplified version of the “From” trait and allows for a more straightforward conversion by implementing the into
method.
The main difference between the two is that the “Into” trait assumes that the conversion will always be successful, while the “From” trait allows for the possibility of a failed conversion, which is achieved by returning a Result
type from the from
method implementation, which can be either Ok
with the converted value, or Err
with an error description.