Impl FromStr for tuple struct with &str

how do I resolve the lifetime error for &str, if I use String it works

also how to use statements in match branch? the commented out part doesnot work

thanks


use std::string::ParseError;

#[derive(Debug, PartialEq)]
struct MyType<'a>(&'a str);

impl<'a> FromStr for MyType<'a> {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let t = s.trim();

        // match t.is_empty() {
        //     true => Ok(MyType("my")),
        //     _ => {
        //         let cs: Vec<&str> = t.split(',').collect();
        //         Ok(MyType(cs[0]))
        //     }
        // }

        if t.is_empty() {
            return Ok(MyType("my"));
        }

        let cs: Vec<&str> = t.split(',').collect();
        return Ok(MyType(cs[0]));
    }
}

You have to accept &'a str, otherwise there's no guarantee that the input string will be alive as long as MyType is.

2 Likes

You cannot implement FromStr (in a reasonable manner) for such a type. That trait is for fairly simple parsing and implementations cannot out restrictions in the lifetime of the passed str. Consider either of the following

  • just use a custom (associated) function, not thr FromStr trait's, and have it take &'a str argument with appropriately matching lifetime
  • implement From<&'a str> with matching lifetime
  • if you want to support parsing, serde has an infrastructure to deserialize without copying the input, so if you want to use your type with serde, that would work
  • make it struct MyType(String); if you do need the full capabilities of the FromStr to create an owned value from an arbitrarily short-lived string. Then you can implement FromStr.
2 Likes

@Cerber-Ursi you mean changing the signature to fn from_str(s: &'a str) -> Result<Self, Self::Err> {?

No, you can't do that, because that's not what is specified in the trait. If you want to accept an &'a str, you will have to implement your own method.

2 Likes

String is the correct type to use here. You're returning a new object, not a temporary view into an old one.

BTW: t.split(',').next().unwrap() is a faster way to chop off the text.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.