Rust lang series episode #2 4 —  user error types (#rust-series)

in #rust-series8 years ago (edited)

Hello everyone, new episode of rust series is here, today we will close Error handling in Rust. We will finish our error handling sub-series with user error types and brief summary.

Content

  • From trait
  • Implementing own Error types
  • Boxed Error and String error type
  • Summary

From trait

From trait is very usefull and it's also used by try! macro that we discussed before to convert one error type to another.

trait From<T> {
    fn from(T) -> Self;
}

Implementing own Error type

We will implement our user error type enum MyError and will work with that.

use std::io;
use std::fs::File;
use std::io::prelude::*;
use std::io::{Error, ErrorKind};

#[derive(Debug)]
enum MyError {
    FileWriteError
}

impl From<io::Error> for MyError {
    fn from(e: io::Error) -> MyError {
        MyError::FileWriteError
    }
}

fn do_some_io() -> Result<i32, MyError> {
    let original_error = Err(io::Error::new(ErrorKind::Other, "Fake IO error"));

    match original_error {
        Ok(v) => v,
        Err(e) => {
            Err(From::from(e))
        }
    }
}

fn main() {
    let res = do_some_io();

    match res {
        Ok(v) => println!("{}", v),
        Err(err) => {
            println!("my_error: {:?}", err);
        }
    }
}

# output
my_error: FileWriteError

Simplified version with try!

We can simplify do_some_io function with try! macro significantly

fn do_some_io() -> Result<i32, MyError> {
    let original_error = Err(io::Error::new(ErrorKind::Other, "Fake IO error"));

    try!(original_error)
}

Boxed Error

If you want to simplify your work you can also use Box<Error> construction where
conversion works just fine for you. Let's see this example.

use std::io;
use std::error::Error;

fn do_some_io() -> Result<i32, Box<Error>> {
    let original_error = io::Error::new(io::ErrorKind::Other, "Fake IO error");
    Err(From::from(original_error))

}

fn main() {
    let res = do_some_io();

    match res {
        Ok(v) => println!("{}", v),
        Err(err) => {
            println!("my_error: {:?}", err);
        }
    }
}

# output
my_error: Error { repr: Custom(Custom { kind: Other, error: StringError("Fake IO error") }) }

Boxed String error type

You can also simply construct our won StringError that can be passed further as Box<Error>

use std::error::Error;

fn do_some_io() -> Result<i32, Box<Error>> {
    Err(From::from("fake IO error occured"))
}

fn main() {
    let res = do_some_io();

    match res {
        Ok(v) => println!("{}", v),
        Err(err) => {
            println!("my_error: {:?}", err);
        }
    }

# output
my_error: StringError("fake IO error occured")    

Summary of error handling

Error handling can be performed in various ways, let's list them from most simple approach to the most complex one.

  • panic!
  • unwrap()
  • String or Box error type
  • Own type, From and std::error::Error
  • Combinators (map, and_then, map_err, ...)

Congratulations! If you have passed all four episodes you should understand Rust error handling fundamentals. Now you just need to practice.

Postfix

That's all for handling, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). May Jesus bless your programming skills, use them wisely and see you next time.

Meanwhile you can also check the official documentation for more details if you wish.

#rust-series
#rust-lang
#rust

Coin Marketplace

STEEM 0.16
TRX 0.16
JST 0.030
BTC 59228.82
ETH 2524.07
USDT 1.00
SBD 2.52