Primitives are converting through casting (see Types)
Custom Types are converted through the use of Traits. Common ones being From and Into
From and Into Traits
Lets us define custom type conversions
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let num = Number::from(30);
println!("My number is {:?}", num);
}use std::convert::Into;
#[derive(Debug)]
struct Number {
value: i32,
}
impl Into<Number> for i32 {
fn into(self) -> Number {
Number { value: self }
}
}
fn main() {
let int = 5;
// Try removing the type annotation
let num: Number = int.into();
println!("My number is {:?}", num);
}If you have implemented From then you do not need to implement Into. They are designed to be closely connected like that.
There exist TryFrom and Tryinto for conversion traits that are fallible.
To and From String
There exist of standard libraries to help do this in an idiocratic way
use std::fmt;
struct Circle {
radius: i32
}
impl fmt::Display for Circle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Circle of radius {}", self.radius)
}
}
fn main() {
let circle = Circle { radius: 6 };
println!("{}", circle.to_string());
}use std::num::ParseIntError;
use std::str::FromStr;
#[derive(Debug)]
struct Circle {
radius: i32,
}
impl FromStr for Circle {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().parse() {
Ok(num) => Ok(Circle{ radius: num }),
Err(e) => Err(e),
}
}
}
fn main() {
let radius = " 3 ";
let circle: Circle = radius.parse().unwrap();
println!("{:?}", circle);
}