Search code examples
vectorstructrustmutable

How to work w/ mutable vector attached to a struct instance in rust


I'm new in rust. I'm trying to create a json parser and I need a struct instance to hold a mutable vector that can be populated with more and more items.

Here is my code:

#[derive(Debug, PartialEq)]
pub enum Token {
    BegKey,
    EndKey
}

#[derive(Debug)]
struct TokenData {
    token: Token,
    data: Vec<u8>
}

impl TokenData {
    fn new(token: Token, v: Option<u8>) -> Self {
        let mut data: Vec<u8> = vec![];
        for &val in v.iter() {
            data.push(val);
        }
        TokenData{token: token, data: data }
    }
}

pub fn read_json_stream(buf: &[u8], size: usize, tokens: &mut Vec<TokenData>, on_obj: fn() -> ()) {
    let mut i = 0;
    while i < size {
        let token = tokens.last();
        match token {
//           ^^^^^^^ 
// cannot move out of `token.0.data` which is behind a shared reference

// note: move occurs because these variables have types that don't implement the `Copy` traitrustc(E0507)


           Some(&TokenData{token: Token::BegKey, data: mut data}) => match buf[i] {
                b'"' if data.last() == Some(&b'\\') => data.push(b'"'),
                b'"' => tokens.push(TokenData::new(Token::EndKey, None)),
                k => data.push(k),
            },
            _ => {}
        }
      i += 1;
    }
}

Solution

  • You need to use .last_mut() to get a mutable reference. Then remove & and mut data from the match arm to let match ergonomics take care of the rest:

    let token = tokens.last_mut();
    match token {
        Some(TokenData { token: Token::BegKey, data }) => ...
    

    Playground