Browse Source

Switch over to Failure instead of custom errors

Getty Ritter 6 years ago
parent
commit
54f9ea9ee1
5 changed files with 71 additions and 52 deletions
  1. 1 0
      Cargo.toml
  2. 23 5
      src/lib.rs
  3. 3 0
      src/tools/common.rs
  4. 6 41
      src/tools/format.rs
  5. 38 6
      src/tools/select.rs

+ 1 - 0
Cargo.toml

@@ -13,6 +13,7 @@ serde = "*"
 serde_json = "*"
 clap = "2.27.1"
 rustache = "*"
+failure = "*"
 
 [[bin]]
 name = "rr-pretty"

+ 23 - 5
src/lib.rs

@@ -1,3 +1,5 @@
+#[macro_use] extern crate failure;
+
 pub mod contlines;
 
 use contlines::ContinuationLines;
@@ -55,9 +57,27 @@ impl Recfile {
     }
 }
 
+#[derive(Debug, Fail)]
+pub enum RecError {
+    #[fail(display = "Error parsing records: {}", message)]
+    GenericError {
+        message: String,
+    },
+
+    #[fail(display = "Found cont line in nonsensical place: {}", ln)]
+    BadContLine {
+        ln: String,
+    },
+
+    #[fail(display = "Invalid line: {}", ln)]
+    InvalidLine {
+        ln: String,
+    },
+}
+
 
 impl Recfile {
-    pub fn parse<I>(i: I) -> Result<Recfile, String>
+    pub fn parse<I>(i: I) -> Result<Recfile, RecError>
         where I: std::io::BufRead
     {
         let mut iter = ContinuationLines::new(i.lines());
@@ -93,9 +113,7 @@ impl Recfile {
                             &ln[1..]
                         });
                 } else {
-                    return Err(format!(
-                        "Found continuation line in nonsensical place: {}",
-                        ln));
+                    return Err(RecError::BadContLine{ ln: ln.to_owned() });
                 }
             } else if let Some(pos) = ln.find(':') {
                 let (key, val) = ln.split_at(pos);
@@ -106,7 +124,7 @@ impl Recfile {
                     ctx.current_record_type = Some(val[1..].trim_left().to_owned());
                 }
             } else {
-                return Err(format!("Invalid line: {:?}", ln));
+                return Err(RecError::InvalidLine { ln: ln.to_owned() });
             }
         }
 

+ 3 - 0
src/tools/common.rs

@@ -1,5 +1,8 @@
+#![allow(dead_code)]
+
 use std::{fs,io};
 
+/// This can be changed to modify all the tool metadata all at once
 pub const VERSION: &'static str = "0.0";
 pub const AUTHOR: &'static str =
     "Getty Ritter <rrecutils@infinitenegativeutility.com>";

+ 6 - 41
src/tools/format.rs

@@ -1,10 +1,9 @@
 extern crate clap;
 extern crate rrecutils;
 extern crate rustache;
+#[macro_use] extern crate failure;
 
 use std::{fs,io};
-use std::convert::From;
-use std::string::FromUtf8Error;
 
 mod common;
 
@@ -33,37 +32,6 @@ impl Render for R {
     }
 }
 
-enum FormatErr {
-    IOError(io::Error),
-    Utf8Error(FromUtf8Error),
-    Rustache(rustache::RustacheError),
-    Generic(String),
-}
-
-impl From<io::Error> for FormatErr {
-    fn from(err: io::Error) -> FormatErr {
-        FormatErr::IOError(err)
-    }
-}
-
-impl From<FromUtf8Error> for FormatErr {
-    fn from(err: FromUtf8Error) -> FormatErr {
-        FormatErr::Utf8Error(err)
-    }
-}
-
-impl From<rustache::RustacheError> for FormatErr {
-    fn from(err: rustache::RustacheError) -> FormatErr {
-        FormatErr::Rustache(err)
-    }
-}
-
-impl From<String> for FormatErr {
-    fn from(err: String) -> FormatErr {
-        FormatErr::Generic(err)
-    }
-}
-
 
 fn rr_format_args() -> clap::ArgMatches<'static> {
     clap::App::new("rr-format")
@@ -105,7 +73,7 @@ fn rr_format_args() -> clap::ArgMatches<'static> {
         .get_matches()
 }
 
-fn run() -> Result<(), FormatErr> {
+fn run() -> Result<(), failure::Error> {
     let matches = rr_format_args();
 
     let input = common::input_from_spec(
@@ -120,7 +88,7 @@ fn run() -> Result<(), FormatErr> {
             fs::File::open(path)?.read_to_end(&mut buf)?;
             String::from_utf8(buf)?
         },
-        None => Err(format!("No template specified!"))?,
+        None => bail!("No template specified!"),
     };
 
     let mut recfile = rrecutils::Recfile::parse(input)?;
@@ -140,19 +108,16 @@ fn run() -> Result<(), FormatErr> {
             output.write(j.as_bytes())?;
             output.write(&['\n' as u8])?;
         }
-        R { rec: r }.render(&template, &mut output.as_mut())?;
+        R { rec: r }.render(&template, &mut output.as_mut())
+            .map_err(|e| format_err!("Rustache error: {:?}", e))?;
     }
 
     Ok(())
 }
 
 fn main() {
-    use FormatErr::*;
     match run() {
         Ok(()) => (),
-        Err(IOError(_)) => panic!("IO Error"),
-        Err(Utf8Error(_)) => panic!("Cannot decode as UTF-8"),
-        Err(Rustache(r)) => panic!("Rustache error: {:?}", r),
-        Err(Generic(s)) => panic!("{}", s),
+        Err(e) => println!("{}", e),
     }
 }

+ 38 - 6
src/tools/select.rs

@@ -1,14 +1,29 @@
 extern crate clap;
 extern crate rrecutils;
+extern crate failure;
 
 mod common;
 
-fn main() {
-    let matches = clap::App::new("rr-sel")
+use failure::Error;
+
+fn rr_select_args() -> clap::ArgMatches<'static> {
+    clap::App::new("rr-sel")
         .version(common::VERSION)
         .author(common::AUTHOR)
         .about("Print records from a recfile")
 
+        .arg(clap::Arg::with_name("input")
+             .short("i")
+             .long("input")
+             .value_name("FILE")
+             .help("The input recfile (or - for stdin)"))
+
+        .arg(clap::Arg::with_name("output")
+             .short("o")
+             .long("output")
+             .value_name("FILE")
+             .help("The desired output location (or - for stdout)"))
+
         .arg(clap::Arg::with_name("type")
              .long("type")
              .short("t")
@@ -39,14 +54,31 @@ fn main() {
              .required(false)
              .takes_value(true))
 
-        .get_matches();
+        .get_matches()
+}
+
+fn run() -> Result<(), Error> {
+    let matches = rr_select_args();
 
-    let source = std::io::stdin();
-    let mut records = rrecutils::Recfile::parse(source.lock()).unwrap();
+    let input = common::input_from_spec(
+        matches.value_of("input"))?;
+    let mut output = common::output_from_spec(
+        matches.value_of("output"))?;
+
+    let mut records = rrecutils::Recfile::parse(input)?;
 
     if let Some(typ) = matches.value_of("type") {
         records.filter_by_type(typ);
     }
 
-    records.write(&mut std::io::stdout());
+    records.write(&mut output)?;
+
+    Ok(())
+}
+
+fn main() {
+    match run() {
+        Ok(()) => (),
+        Err(e) => println!("{}", e),
+    }
 }