• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::ffi;
2 use std::ffi::CString;
3 use std::fmt;
4 use std::str;
5 
6 use libc::c_char;
7 use regex;
8 
9 #[derive(Debug)]
10 pub struct Error {
11     message: Option<CString>,
12     kind: ErrorKind,
13 }
14 
15 #[derive(Debug)]
16 pub enum ErrorKind {
17     None,
18     Str(str::Utf8Error),
19     Regex(regex::Error),
20     Nul(ffi::NulError),
21 }
22 
23 impl Error {
new(kind: ErrorKind) -> Error24     pub fn new(kind: ErrorKind) -> Error {
25         Error { message: None, kind: kind }
26     }
27 
is_err(&self) -> bool28     pub fn is_err(&self) -> bool {
29         match self.kind {
30             ErrorKind::None => false,
31             ErrorKind::Str(_) | ErrorKind::Regex(_) | ErrorKind::Nul(_) => {
32                 true
33             }
34         }
35     }
36 }
37 
38 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result39     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40         match self.kind {
41             ErrorKind::None => write!(f, "no error"),
42             ErrorKind::Str(ref e) => e.fmt(f),
43             ErrorKind::Regex(ref e) => e.fmt(f),
44             ErrorKind::Nul(ref e) => e.fmt(f),
45         }
46     }
47 }
48 
49 ffi_fn! {
50     fn rure_error_new() -> *mut Error {
51         Box::into_raw(Box::new(Error::new(ErrorKind::None)))
52     }
53 }
54 
55 ffi_fn! {
56     fn rure_error_free(err: *mut Error) {
57         unsafe { drop(Box::from_raw(err)); }
58     }
59 }
60 
61 ffi_fn! {
62     fn rure_error_message(err: *mut Error) -> *const c_char {
63         let err = unsafe { &mut *err };
64         let cmsg = match CString::new(format!("{}", err)) {
65             Ok(msg) => msg,
66             Err(err) => {
67                 // I guess this can probably happen if the regex itself has a
68                 // NUL, and that NUL re-occurs in the context presented by the
69                 // error message. In this case, just show as much as we can.
70                 let nul = err.nul_position();
71                 let msg = err.into_vec();
72                 CString::new(msg[0..nul].to_owned()).unwrap()
73             }
74         };
75         let p = cmsg.as_ptr();
76         err.message = Some(cmsg);
77         p
78     }
79 }
80