rustep/
error.rs

1use std::{
2    fmt,
3    fmt::Display,
4};
5
6use failure::{
7    Context,
8    Fail,
9    Backtrace,
10};
11
12#[derive(Debug)]
13pub struct RustepError {
14    inner: Context<RustepErrorKind>
15}
16
17#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
18pub enum RustepErrorKind {
19    #[fail(display = "Unsupported ELF class value {}", _0)]
20    UnsupportedElfClass(u8),
21    #[fail(display = "Parsing error")]
22    Parse,
23    #[fail(display = "Not enough byte, {} bytes needed", _0)]
24    Incomplete(usize),
25    #[fail(display = "Not enough byte, unknown bytes needed")]
26    IncompleteUnknown,
27    #[fail(display = "Segment type {} not resolved", _0)]
28    SegmentType(u64),
29    #[fail(display = "Section type {} not resolved", _0)]
30    SectionType(u64),
31    #[fail(display = "Segment flag {} invalid", _0)]
32    SegmentFlag(u64),
33    #[fail(display = "Section flag {} invalid", _0)]
34    SectionFlag(u64),
35    #[fail(display = "Unknown elf type {}", _0)]
36    ElfType(u64),
37    #[fail(display = "Unknown elf machine {}", _0)]
38    ElfMachine(u64),
39    #[fail(display = "Not an Elf file")]
40    NotElf,
41}
42
43impl Fail for RustepError {
44    fn cause(&self) -> Option<&Fail> {
45        self.inner.cause()
46    }
47
48    fn backtrace(&self) -> Option<&Backtrace> {
49        self.inner.backtrace()
50    }
51}
52
53impl Display for RustepError {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        Display::fmt(&self.inner, f)
56    }
57}
58
59impl RustepError {
60    pub fn kind(&self) -> RustepErrorKind {
61        *self.inner.get_context()
62    }
63}
64
65impl From<RustepErrorKind> for RustepError {
66    fn from(kind: RustepErrorKind) -> RustepError {
67        RustepError { inner: Context::new(kind) }
68    }
69}
70
71impl From<Context<RustepErrorKind>> for RustepError {
72    fn from(inner: Context<RustepErrorKind>) -> RustepError {
73        RustepError { inner: inner }
74    }
75}
76
77/// Crate `Failure` has not supported `nom`, or `nom` not supported `Failure`.
78/// To avoid to do error handling manually, this macro is used to emulate the try method to be
79/// better to use along with `Failure`.
80///
81/// # Examples
82/// ```
83/// use nom::*;
84/// 
85/// let res = tag!(b"abc", "bcd"); // Here will be an IResult returned from nom.
86/// let res_err = nom_try!(res); // This is almost like `res?`, it will return early
87/// let res = tag!(b"abc", "abc"); // This will be accepted
88/// let res_noerr = nom_try!(res); // The Done part of nom will be extracted
89/// ```
90macro_rules! nom_try {
91
92    ($arg:expr) => {
93        match $arg {
94            Done(_i, res) => {
95                res
96            },
97            Error(e) => {
98                Err(format_err!("Parse Error {}", e.to_string()).context(RustepErrorKind::Parse))?
99            },
100            Incomplete(needed) => {
101                match needed {
102                    Size(s) => Err(RustepErrorKind::Incomplete(s))?,
103                    Unknown => Err(RustepErrorKind::IncompleteUnknown)?,
104                }
105            }
106        }
107    }
108}