I have a set of structs that are nested, and all the data is optional. Structs are similar to the following (for simplicity I've removed some of the Optionals):
#[derive(Debug, Serialize, Deserialize)]
pub struct Device {
#[serde(rename = "_id")]
pub id: Option<bson::oid::ObjectId>,
pub system: Option<System>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct System {
pub id: Option<u32>,
pub mac: Option<String>,
}
When I query the db, I get the data:
Ok(Some(Device { id: Some(ObjectId("...")), system: Some(System { id: Some(123), mac: Some("1234") })}))
I am trying to access the id value within the System struct. I can access it easily with a few nested match statements, but I was wondering if there is an easier solution. I've been looking at unwrap_or, unwrap_or_else, but I haven't been able to get the syntax correct. Ideally returning a 0 will suffice, as that value is used to denote an error within the application structure. The nested match statements work fine - it is just a bit verbose.
Alternatively I could also just use the aggregation pipeline to get the value. I'm just curious about alternatives.
Thanks.
CodePudding user response:
You can use and_then
to apply a function to the contained Ok
value, and leave None
s unchanged. For example, imagine the following structure:
struct Foo {
bar: Option<Bar>
}
struct Bar {
baz: Option<Baz>
}
struct Baz {
value: Option<i32>
}
You can then query the nested data like:
fn read_value(foo: Foo) -> Option<i32> {
foo.bar
.and_then(|bar| bar.baz)
.and_then(|baz| baz.value)
}
If any of the Option
's are None
, the whole expression will be None
, otherwise it will be the contained Some(value)