viraptor
viraptor

Reputation: 34145

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 { 
        // ...
    }
}

Upvotes: 4

Views: 2668

Answers (2)

Danilo Bargen
Danilo Bargen

Reputation: 19432

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.

Upvotes: 3

viraptor
viraptor

Reputation: 34145

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!()
    }
}

Upvotes: 5

Related Questions