Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add an item to a struct member that is an `Option<Vec<...>>`?

Tags:

rust

How can I add an item to a struct member that is an Option<Vec<...>>?

In other words, what do I need to to to make add_foo below work?

struct Foo {
    value: u32,
}

struct Bar {
    foos: Option<Vec<Foo>>, 
}

impl Bar {
    fn add_foo(&mut self, foo: Foo) {
        if self.foos.is_none() {
            self.foos = Some(vec![]);
        }
        self.foos.unwrap().push(foo);
//      ^^^^^^^^^ move occurs because `self.foos` has type `Option<Vec<Foo>>`, which does not implement the `Copy` trait        
    }
}

fn main() {
    let mut bar = Bar{foos: None};
    bar.add_foo(Foo{value:42});
}

The error message suggests adding as_ref() but that doesn't help:

        self.foos.as_ref().unwrap().push(foo);
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

I though there might be something as as_mutref() but there is no such thing. Since I already hold a mutable reference to the Bar struct, I would expect to be able to change the foos field in the Bar struct.

Apologies if my terminology is off; still getting used to the whole Rust ownership concept.

like image 379
Bruno Rijsman Avatar asked Oct 24 '25 01:10

Bruno Rijsman


1 Answers

Something like the following might be what you're looking for:

fn add_foo(&mut self, foo: Foo) {
  if let Some(foos) = self.foos.as_mut() {
    // foos has type: &mut Vec<Foo>
    foos.push(foo);
  } else {
    self.foos = Some(vec![foo]);
  }
}

In general, using an if let or match or some other destructuring syntax is considered more idiomatic than using a is_some() check followed by an unwrap(). At the very least it saves on a comparison, but more importantly is harder to make accidentally panic.

like image 169
cameron1024 Avatar answered Oct 26 '25 18:10

cameron1024



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!