Skip to content

Instantly share code, notes, and snippets.

@Phaiax
Created June 20, 2017 13:15

Revisions

  1. Phaiax created this gist Jun 20, 2017.
    106 changes: 106 additions & 0 deletions error_chain_extension.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    #[macro_use] extern crate error_chain;


    // All errors that can occour everywhere in the crate
    pub mod errors {
    error_chain!{
    errors {
    Pig { description("Pig-Descr") display("Pig-Display")}
    Bat {}
    Uhu {}
    }
    }
    }

    pub use errors::*;



    // Every public fn is preceeded by this macro which indicates the valid
    // variants of errors that can occour.
    // can_err!( AErrorKinds, AResult, {Pig, Bat})
    ////////////////////////////////////////////////////////
    ////////// THIS WOULD BE GENERATED BY THE MACRO can_err!
    ////////////////////////////////////////////////////////
    #[derive(Debug)]
    pub enum AErrorKinds {
    Pig{k : Error},
    Bat{k : Error}
    }
    pub type AResult<T> = std::result::Result<T, AErrorKinds>;
    impl AErrorKinds {
    pub fn kind(&self) -> &ErrorKind {
    match self {
    &AErrorKinds::Pig { ref k } => k.kind(),
    &AErrorKinds::Bat { ref k } => k.kind(),
    }
    }
    pub fn kind_reduced(&self) -> &AErrorKinds {
    self
    }
    pub fn description(&self) -> &str {
    self.kind().description()
    }
    }
    impl std::fmt::Display for AErrorKinds {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
    //use std::fmt::Display;
    self.kind().fmt(fmt)
    }
    }
    impl From<ErrorKind> for AErrorKinds {
    fn from(ek: ErrorKind) -> Self {
    let e : Error = ek.into();
    let n = match e.kind() {
    &ErrorKind::Pig{..} => 1,
    &ErrorKind::Bat{..} => 2,
    _ => unreachable!()
    };
    match n {
    1 => AErrorKinds::Pig { k:e },
    2 => AErrorKinds::Bat { k:e },
    _ => unreachable!()
    }
    }
    }
    ////////////////////////////////////////////////////////
    /////////////////// END MACRO
    ////////////////////////////////////////////////////////

    fn some_internal_helper() -> AResult<u8> {
    // Uhu is an invalid error for this
    // function, so the following line will go to unreachable! and panic.
    Err(ErrorKind::Uhu.into())
    }



    #[cfg(test)]
    mod tests {

    use super::*;

    #[test]
    fn it_works() {

    if let Err(err) = some_internal_helper() {
    match *err.kind() {
    ErrorKind::Msg(_) => {}
    ErrorKind::Pig => {},
    ErrorKind::Bat => {}
    ErrorKind::Uhu => {}
    }
    // the actual errors that can be generated by the function
    // are combined in a distict enum that allows exhaustive
    // matching
    match *err.kind_reduced() {
    AErrorKinds::Pig{..} => {},
    AErrorKinds::Bat{..} => {}
    }
    println!("Descr: {}", err.description());
    println!("Displ: {}", err);
    println!("Debug: {:?}", err);
    }

    }
    }