Nagaraj M
Nagaraj M

Reputation: 447

How to get a value from a Result?

How can I get the value of a struct which is returned in a Result from another function? Example below.

#[derive(Debug)]
pub struct Keypair(ed25519_dalek::Keypair);

pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>> {
    let dalek_keypair = ed25519_dalek::Keypair { secret, public };
    Ok(Keypair(dalek_keypair))
}
fn main(){
  //here seed_bytes is mnemonics
  let sk = keypair_from_seed(&seed_bytes);
  //sk contains the secret key and public key, i want to extract it different secret key & public key
}

Upvotes: 30

Views: 39605

Answers (3)

prog-fh
prog-fh

Reputation: 16850

If you feel very confident

let sk = keypair_from_seed(&seed_bytes).unwrap();

or

let sk = keypair_from_seed(&seed_bytes).expect("my own failure message");

However, it is recommended to proceed like this

if let Ok(sk) = keypair_from_seed(&seed_bytes) {
    // ... use sk ...
} else {
    // ... sk is not available, may be should
    // we warn the user, ask for an alternative ... 
}

or, if you want to explicitly handle the error

match keypair_from_seed(&seed_bytes) {
    Ok(sk) => { 
        // ... use sk ...
    },
    Err(e) => {
        // ... sk is not available, and e explains why ...
    },
}

Note that, if the function containing these lines is also able to return an error, you can just propagate it with the ? notation (if the error returned by keypair_from_seed() is convertible into the error returned by your function)

let sk = keypair_from_seed(&seed_bytes)?;

see unwrap, expect, if let, match, ?

Upvotes: 55

prateeknischal
prateeknischal

Reputation: 792

The returned result from the function is of the type Result<Keypair, Box<dyn error::Error>>.

There are multiple ways to extract a result from the Result container. Basically rust wants you to check for any errors and handle it. If no errors, you can extract the result and use it.

if let Ok(sk) = keypair_from_seed(&seed) {
    let public = sk.0.public;
    let secret = sk.0.secret;
    /* use your keys */
}

Notice the sk.0 since you are using a struct of a tuple type. If your struct had multiple variables, something like

pub struct KeyTuple(ed25519_dalek::Keypair, i32, &str);

You would have used it as

let kt = keytuple_from_seed(&seed).unwrap();
let kp: ed25519_dalek::Keypair = kt.0;
let le: i32 = kt.1;
let st: &str = kt.2;

Upvotes: 2

Aiono
Aiono

Reputation: 396

Lets look the definition of Result in Rust documentation

enum Result<T, E> {
   Ok(T),
   Err(E),
}

So a Result is either Ok which contains a value with type T, or Err which contains a value with type E.

You have couple options to extract the value.

1- result.unwrap() or result.expect("error message")

This function returns the Ok value if result is Ok or panics the program (program is terminated). If you are sure that it doesn't contain error or you just want to write the correct case first and deal with error handling later it makes sense but you shouldn't use it all the time since it directly crashes the app when the value is not Ok. You can use it like this

let val = result.unwrap();
// or
let val = result.expect("oops not Ok");

Only difference of expect you can provide the error message yourself instead of the standard error message of unwrap.

2- Pattern matching

In Rust, pattern matching is used for enum types so that user can do the necessary thing based on the current variant of the enum. You can use it like this

match result {
    Ok(val) => {
        // Use val here....
    },
    Err(err) => {
        // Do something with the error if you want
    }
}

If you are going to handle only one variant, you can also use if let statement like this

if let Some(val) = result {
    // Do something with val
}

Upvotes: 10

Related Questions