« Back to Index

Rust: parse string to custom type

View original Gist on GitHub

Tags: #rust #trait

main.rs

// https://twitter.com/integralist/status/1508844091504836612
//
// Learning #rustlang and (yes it's a contrived example) 
// I'm liking being able to piggy back off existing methods like .parse() 
// and having it serialise data into a custom type via the FromStr trait.
//
// EXPLANATION:
// Roughly what is happening here is when we call parse() on the given 
// string "beep" the compiler checks the type (in this case Foo is 
// assigned to the variable f) and so it knows that Foo needs to 
// implement the FromStr trait (which it sees that it does). So when the 
// compiler then calls FromStr::from_self(self) (the self evaluating to 
// the string "beep" and subsequently the correlating type Foo) it's able 
// to swap out the traits from_self with the `impl std::str::FromStr for 
// Foo` implementation.
//
// A similar example of this 'inference' of an implementation, and being 
// able to call a trait method that has no default implementation, is:
//
// fn takes_vec(v: Vec<i32>) {}
// fn main() {
//   takes_vec(FromIterator::from_iter(0..10));
// }
//
// Internally the range (0..10) is called with .collect() like so:
//
// (0..10).collect()
//
// Which means the compiler knows that the range must be collected into
// a Vect<i32>, and from there the compiler then knows to swap out the
// call to FromIterator::from_iter with the Vector's own implementation.

#[derive(Debug)]
struct Foo {
    bar: String,
}

// http://doc.rust-lang.org/1.59.0/std/str/trait.FromStr.html
impl std::str::FromStr for Foo {
    type Err = Box<dyn std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Foo{bar: s.to_string()})
    }
}

fn main() {
    let f = Foo{bar: "baz".to_string()};
    println!("{:#?}", f);
    println!("{:#?}", f.bar);

    let f: Foo = "beep".parse().unwrap();
    println!("{:#?}", f);
}