APIs in the project I'm working on, take a lot of Option<&PartInfo>
arguments. In the implementation, I need to call some methods on PartInfo
so I need to unwrap it or create a Default PartInfo
.
I want it to be as ergonomic as possible, so I'm looking for different approaches to this.
As we know,
// part is Option<&PartInfo>
let part = part.unwrap_or_default();
Won't work due to the different types (&T
vs T
). One solution could be:
let part = part.cloned().unwrap_or_default()
but this requires T: Clone
and it's not cheap.
This won't work too, due to ToOwned
bound on Cow
:
let part = part.map(Cow::Borrow).unwrap_or_else(||Cow::Owned(PartInfo::default)));
Of course, I can always do:
let tmp;
let part = match part {
Some(r) => r,
None => {
tmp = PartInfo::default();
&tmp
}
}
I even have a macro for this.
But I'm not satisfied with this, I feel like Rust should offer something for this case in std
. A type the whole purpose of which is to be either a reference or a value and provide a Deref
for it. That's it, nothing more.
I went ahead and made a simple one for my lib (Rov - RefenceOrValue)
enum Rov<'a, T: Sized> {
Ref(&'a T),
Val(T)
}
impl<'a, T> Deref for Rov<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Row::Ref(r) => r,
Row::Val(v) => &v
}
}
}
I'm wondering, should Rust have a type like this?
I know there are a bunch of Cow
-like crates that do exactly this (and more) but again, to me, it feels like it should be in std
.
Now, the second part. To solve my problem with unwrapping an Option<&T>
I wrote this:
pub(crate) trait UnwrapAsRov<'a, T> {
fn unwrap_or_default_rov(&self) -> Rov<'a, T>;
}
impl<'a, T> UnwrapAsRov<'a, T> for Option<&'a T>
where T: Default
{
fn unwrap_or_default_rov(&self) -> Rov<'a, T> {
match self {
Some(v) => Rov::Ref(*v),
None => Rov::Val(T::default())
}
}
}
Now I can easily do
let part = part.unwrap_or_default_rov();
part.some_method()
I'd like to hear how others approach this and do you think Rust could/should provide a type like Rov
and maybe even provide a method on Option
to deal with it?