How to lifetime annotate From trait in rust when indexing vector

Viewed 20

I'd like to use the From trait to extract values from a json input into my struct CreateUser. If I extract the full etc vector as etc: Vec<String> it works fine, but I only need the second field of etc which is 2 in the CreateUser struct. Following the compiler hints I also couldn't get it to work.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=563063a1cc9a722e7f41aa17b74c8f57

The code:

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

static INPUT: &str = r#"{
    "email" : "",
    "password" : "",
    "etc" : ["1", "2"]
}"#;

#[derive(Serialize, Deserialize, Debug)]
struct InputUser {
    email: String,
    password: String,
    etc: Vec<String>,
}

struct CreateUser<'a> { 
    email: String,
    password: String,
    only_second_field_in_etc_vector: &'a str,
}

impl From<InputUser> for CreateUser {
    fn from(i: InputUser) -> CreateUser {
        CreateUser {
            email: i.email,
            password: i.password,
            // Problem here
            only_second_field_in_etc_vector: &i.etc[1],
        }
    }
}

fn main() {
    let input: InputUser = serde_json::from_str(INPUT).unwrap();
    let create_user = CreateUser::from(input);
}
1 Answers

Since the From trait will drop the input you cannot reference the field by reference, you will have to take the whole String value. The following code will take the second value into the given field.

extern crate serde;
extern crate serde_json;

use serde::Serialize;
use serde::Deserialize;

static INPUT: &str = r#"{
    "email" : "",
    "password" : "",
    "etc" : ["1", "2"]
}"#;

#[derive(Serialize, Deserialize, Debug)]
struct InputUser {
    email: String,
    password: String,
    etc: Vec<String>,
}

#[derive(Debug)]
struct CreateUser {
    email: String,
    password: String,
    only_second_field_in_etc_vector: String,
}

impl From<InputUser> for CreateUser {
    fn from(i: InputUser) -> CreateUser {
        CreateUser {
            email: i.email,
            password: i.password,
            // Problem here
            only_second_field_in_etc_vector: i.etc.into_iter().skip(1).next().unwrap(),
        }
    }
}

fn main() {
    let input: InputUser = serde_json::from_str(INPUT).unwrap();
    eprintln!("{:?}", CreateUser::from(input));
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=f08a8613bfadb15001ae5d03b5f262a1

Related