use self::super::util::uppercase_first; use std::io::Write; /// Enum representing all possible ways the application can fail. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Error { /// An I/O error occured. /// /// This includes higher-level I/O errors like FS ones. Io { /// The file the I/O operation regards. desc: &'static str, /// The failed operation. /// /// This should be lowercase and imperative ("create", "open"). op: &'static str, /// Additional data. more: Option<&'static str>, }, /// A parsing error occured. Parse { /// What failed to parse. /// /// Something like "URL", "datetime". tp: &'static str, /// Where the thing that failed to parse would go, were it to parse properly. wher: &'static str, /// Additional data. more: Option<&'static str>, }, } impl Error { /// Write the error message to the specified output stream. /// /// # Examples /// /// ``` /// # use dumplingh::Error; /// # use std::iter::FromIterator; /// let mut out = Vec::new(); /// Error::Io { /// desc: "network", /// op: "write", /// more: Some("full buffer"), /// }.print_error(&mut out); /// assert_eq!(&out[..], /// &b"Writing network failed: full buffer.\n"[..]); /// ``` pub fn print_error(&self, err_out: &mut W) { match *self { Error::Io { desc, op, more } => { // Strip the last 'e', if any, so we get correct inflection for continuous tenses let op = uppercase_first(if op.ends_with('e') { &op[..op.len() - 1] } else { op }); write!(err_out, "{}ing {} failed", op, desc).unwrap(); if let Some(more) = more { write!(err_out, ": {}", more).unwrap(); } writeln!(err_out, ".").unwrap(); } Error::Parse { tp, wher, more } => { write!(err_out, "Failed to parse {} for {}", tp, wher).unwrap(); if let Some(more) = more { write!(err_out, ": {}", more).unwrap(); } writeln!(err_out, ".").unwrap(); } } } /// Get the executable exit value from an `Error` instance. /// /// # Examples /// /// ``` /// # use dumplingh::Error; /// assert_eq!(Error::Io { /// desc: "", /// op: "", /// more: None, /// }.exit_value(), 1); /// ``` pub fn exit_value(&self) -> i32 { match *self { Error::Io { .. } => 1, Error::Parse { .. } => 2, } } }