1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
extern crate backtrace;
extern crate libc;

use std::fmt;
use std::ops::Deref;
use std::io;
use std::string::FromUtf8Error;

use self::backtrace::Backtrace;
use self::backtrace::BacktraceFrame;

#[derive(Debug)]
pub struct RError<E> {
    e: E,
    bt: Option<Backtrace>,
}

pub fn is_enoent(e: &io::Error) -> bool {
    return e.kind() == io::ErrorKind::NotFound;
}

pub fn try_enoent(e: io::Error) -> Result<bool> {
    if is_enoent(&e) {
        return Ok(true);
    } else {
        return Err(RError::from(e));
    }
}

pub fn propagate<T>(e: io::Error) -> Result<T> {
    return Err(RError::propagate(e));
}

pub fn errno(e: &RError<io::Error>) -> libc::c_int {
    if RError::expected(e) {
        return e.e.raw_os_error().unwrap();
    } else {
        return libc::EIO;
    }
}


impl<E> RError<E> {
    pub fn propagate(e: E) -> RError<E> {
        RError {
            e: e,
            bt: Default::default(),
        }
    }

    pub fn from(e: E) -> RError<E> {
        let mut bt = Backtrace::new();
        let mut i: usize = 0;
        let mut chop: usize = 0;
        for f in bt.frames() {
            if let Some(p) = f.symbols()[0].filename() {
                if p.file_name().unwrap() == "error.rs" {
                    chop = i;
                    break;
                }
            }
            i += 1;
        }

        if chop != 0 {
            let mut frames: Vec<BacktraceFrame> = bt.into();
            let _: Vec<_> = frames.drain(0..i).collect();
            bt = Backtrace::from(frames);
        }

        RError { e: e, bt: Some(bt) }
    }

    fn expected(&self) -> bool {
        return self.bt.is_none();
    }
}

impl RError<io::Error> {
    pub fn errno(&self) -> i32 {
        return self.e.raw_os_error().unwrap();
    }
}

impl fmt::Display for RError<io::Error> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.bt {
            Some(ref bt) => write!(f, "{} {:?}", self.e, bt),
            None => write!(f, "{}", self.e),
        }

    }
}

impl<E> Deref for RError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.e
    }
}

// XXX not really a clone
impl Clone for RError<io::Error> {
    fn clone(&self) -> Self {
        RError {
            e: io::Error::from_raw_os_error(self.e.raw_os_error().unwrap()),
            bt: Default::default(),
        }
    }
}

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

impl From<FromUtf8Error> for RError<FromUtf8Error> {
    fn from(e: FromUtf8Error) -> RError<FromUtf8Error> {
        RError::from(e)
    }
}

pub type Result<T> = ::std::result::Result<T, RError<io::Error>>;