I'm a Rust newbie! What's the best way to convert from an Option<T> to a Result<T, ()>?
The TryFrom trait seems prevalent and returns a Result. The popular num_traits' NumCast has many conversions but they all return an Option<T>. Similarly, as do the NonZero* constructors such as NonZeroI32 in the Rust Standard Library. I then noticed that NumCast implements a from() that returns an Option<T> so I was thinking that maybe it had a non-standard way of doing things in general but then I saw the NonZero* implementations and questioned that idea.
Regardless, converting from Options to Results seem frequent and I haven't found a neat way to do yet. E.g.:
/// Add common conversion from an i32 to a non-zero i32.
impl TryFrom<Container<i32>> for Container<NonZeroI32> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NonZeroI32::new() returns an Option not a Result. Try a helper.
Ok(Self(option_to_result(NonZeroI32::new(container.0))?))
}
}
/// Helper function to convert from an Option to a Result (both types are
/// foreign and so is From).
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
if let Some(some) = option {
Ok(some)
} else {
Err(())
}
}
/// Add another common conversion from an i32 to an i16.
impl TryFrom<Container<i32>> for Container<i16> {
type Error = ();
fn try_from(container: Container<i32>) -> Result<Self, ()> {
// NumCast::from() also returns an Option not a Result. Try map_or() instead
// of the helper.
Ok(Self(NumCast::from(container.0).map_or(Err(()), |x| Ok(x))?))
}
}
(Above examples in the Rust Playground.)
These NumCast, NonZero*, and TryFrom conversions seem common enough but my approach feels clumsy as though I'm pitting the Option and Result types against each other. I struggle with these conversions and also miss the fundamental point of the Option type given Result<T,()> feels similar.
So, what's the idiomatic way to convert an Option<T> to Result<T,()> in Rust 2018?
Option has the ok_or method, usable for exactly this (well, for more wide case, in fact, but your request fits here too):
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
option.ok_or(())
}
Modified playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With