Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the standard way to create custom conversion between types in Rust?

If I defined some enum and wanted to create a parser from string to that type, is there something better than just:

impl TheType {
    fn from_str(s: &str) -> TheType { 
        // ...
    }
}
like image 861
viraptor Avatar asked Sep 06 '25 03:09

viraptor


2 Answers

The right way for converting from a string / parsing text is to implement the FromStr trait. For the example from the question it would look like this:

use std::str::FromStr;

enum Failure {
    ReasonOne,
    ReasonTwo,
}

impl FromStr for TheType {
    type Err = Failure;

    fn from_str(s: &str) -> Result<TheType, Self::Err> { 
        unimplemented!()
    }
}
like image 75
viraptor Avatar answered Sep 07 '25 21:09

viraptor


For generic conversion that cannot fail, you should implement the std::convert::From trait:

use std::convert::From;

#[derive(PartialEq, Eq, Debug)]
enum MyEnum {
    One,
    Two,
    Many(i64),
}

impl From<i64> for MyEnum {
    fn from(val: i64) -> Self {
        match val {
            1 => MyEnum::One,
            2 => MyEnum::Two,
            _ => MyEnum::Many(val),
        }
    }
}

fn main() {
    assert_eq!(MyEnum::from(1), MyEnum::One);
    assert_eq!(MyEnum::from(2), MyEnum::Two);
    assert_eq!(MyEnum::from(3), MyEnum::Many(3));
}

Conveniently, implementing From also automatically implements Into:

let one: MyEnum = 1.into(); assert_eq!(one, MyEnum::One);
let two: MyEnum = 2.into(); assert_eq!(two, MyEnum::Two);
let many: MyEnum = 3.into(); assert_eq!(many, MyEnum::Many(3));

For potentially failing conversion, you should implement std::convert::TryFrom instead. It's only available in Rust 1.34 and up though, before these versions you can use the implementation in the conv crate.

like image 45
Danilo Bargen Avatar answered Sep 07 '25 20:09

Danilo Bargen