1

I have a find function defined on a basic in-memory storage solution. I'm trying to find a way to flexibly pass conditional search options by creating a struct called SearchOpts:

trait HasRecords {
    fn find(&self, opts: &SearchOpts) -> ();
}

pub struct SearchOpts {
    sensorId: Option<String>,
}

struct MemDb {
    id: u32,
}

impl HasRecords for MemDb {
    fn find(&self, opts: &SearchOpts) -> () {
        println!("Hello {}", opts.sensorId.unwrap());
    }
}

fn main() {
    let _x = MemDb { id: 42 };
}

playground

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:15:30
   |
15 |         println!("Hello {}", opts.sensorId.unwrap());
   |                              ^^^^ cannot move out of borrowed content

I don't know if this is the best way to implement this sort of functionality, but I also don't understand how to please the borrow checker in this instance (which is the thing I'd like to learn first).

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
GTF
  • 8,031
  • 5
  • 36
  • 59

1 Answers1

1

The key is that since you only have a reference to the SearchOpts struct in your function, you can't move out of it.

Looking at the definition of Option::unwrap:

pub fn unwrap(self) -> T

It takes the Option argument by value, so it would move out of the struct. No good! The key to fixing this is Option::as_ref:

pub fn as_ref(&self) -> Option<&T>

As the signature implies, it transforms &Option<T> to Option<&T>. This latter type can be unwrapped (resulting in &T) without moving anything. So you can write:

if opts.sensorId.is_some() && &d.sensorId != opts.sensorId.as_ref().unwrap() {
     return false;
}

However, I would write it like this:

if opts.sensorId.as_ref().map_or(false, |id| id != &d.sensorId) {
    return false;
}
durka42
  • 1,502
  • 10
  • 17