Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to idiomatically convert from Option<T> to Result<T, ()>?

Tags:

rust

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?

like image 360
Stephen Niedzielski Avatar asked Dec 03 '25 05:12

Stephen Niedzielski


1 Answers

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

like image 85
Cerberus Avatar answered Dec 06 '25 01:12

Cerberus



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!