16.4 Fallible Conversions with TryFrom and TryInto

When conversions might fail, Rust provides the TryFrom and TryInto traits.

16.4.1 Handling Conversion Failures

These traits return a Result, allowing the caller to handle potential errors.

Example:

use std::convert::TryFrom;

fn main() {
    let x: i8 = 127;
    let y = u8::try_from(x); // Succeeds
    let z = u8::try_from(-1); // Fails
    println!("{:?}, {:?}", y, z);
}

Output:

Ok(127), Err(TryFromIntError(()))

16.4.2 Implementing TryFrom and TryInto for Custom Types

Custom types can define their own fallible conversions by implementing these traits.

Example:

use std::convert::TryFrom;
use std::convert::TryInto;

#[derive(Debug, PartialEq)]
struct EvenNumber(i32);
impl TryFrom<i32> for EvenNumber {
    type Error = String;

    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value % 2 == 0 {
            Ok(EvenNumber(value))
        } else {
            Err(format!("{} is not an even number", value))
        }
    }
}

fn main() {
    assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));
    assert_eq!(EvenNumber::try_from(5), Err(String::from("5 is not an even number")));

    let result: Result<EvenNumber, _> = 8i32.try_into();
    assert_eq!(result, Ok(EvenNumber(8)));
    let result: Result<EvenNumber, _> = 5i32.try_into();
    assert_eq!(result, Err(String::from("5 is not an even number")));
}