Warlock
Warlock

Reputation: 7471

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;
    }
}

Upvotes: 1

Views: 408

Answers (2)

kmdreko
kmdreko

Reputation: 60517

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

Upvotes: 1

Netwave
Netwave

Reputation: 42776

What you want is the last item, but owned Option<T>, for that use pop instead of last (which returns an Option<&T>):

let token = tokens.pop();

Playground

Upvotes: 0

Related Questions