Browse Source

Start using a common helper module for all binaries

This also introduces a tiny abstraction over the common "stdin or
file" pattern that shows up regularly in these tools
Getty Ritter 6 years ago
parent
commit
236bcc00c6
4 changed files with 96 additions and 41 deletions
  1. 63 0
      src/tools/common.rs
  2. 14 17
      src/tools/format.rs
  3. 4 2
      src/tools/select.rs
  4. 15 22
      src/tools/tojson.rs

+ 63 - 0
src/tools/common.rs

@@ -0,0 +1,63 @@
+use std::{fs,io};
+
+pub const VERSION: &'static str = "0.0";
+pub const AUTHOR: &'static str =
+    "Getty Ritter <rrecutils@infinitenegativeutility.com>";
+
+pub enum Input {
+    Stdin(io::BufReader<io::Stdin>),
+    File(io::BufReader<fs::File>),
+}
+
+impl io::Read for Input {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        match self {
+            &mut Input::Stdin(ref mut stdin) =>
+                stdin.read(buf),
+            &mut Input::File(ref mut file) =>
+                file.read(buf),
+        }
+    }
+}
+
+impl io::BufRead for Input {
+    fn fill_buf(&mut self) -> io::Result<&[u8]> {
+        match self {
+            &mut Input::Stdin(ref mut stdin) =>
+                stdin.fill_buf(),
+            &mut Input::File(ref mut file) =>
+                file.fill_buf(),
+        }
+    }
+
+    fn consume(&mut self, amt: usize) {
+        match self {
+            &mut Input::Stdin(ref mut stdin) =>
+                stdin.consume(amt),
+            &mut Input::File(ref mut file) =>
+                file.consume(amt),
+        }
+    }
+}
+
+pub fn input_from_spec<'a>(
+    spec: Option<&'a str>
+) -> io::Result<Input> {
+    match spec.unwrap_or("-") {
+        "-" => Ok(Input::Stdin(io::BufReader::new(io::stdin()))),
+        path => {
+            let f = fs::File::open(path)?;
+            Ok(Input::File(io::BufReader::new(f)))
+        }
+    }
+}
+
+pub fn output_from_spec<'a>(
+    spec: Option<&'a str>
+) -> io::Result<Box<io::Write>>
+{
+    match spec.unwrap_or("-") {
+        "-" => Ok(Box::new(io::stdout())),
+        path => Ok(Box::new(fs::File::open(path)?)),
+    }
+}

+ 14 - 17
src/tools/format.rs

@@ -6,6 +6,8 @@ use std::{fs,io};
 use std::convert::From;
 use std::string::FromUtf8Error;
 
+mod common;
+
 use rustache::Render;
 
 struct R {
@@ -63,10 +65,10 @@ impl From<String> for FormatErr {
 }
 
 
-fn run() -> Result<(), FormatErr> {
-    let matches = clap::App::new("rr-format")
-        .version("0.0")
-        .author("Getty Ritter <rrecutils@infinitenegativeutility.com>")
+fn rr_format_args() -> clap::ArgMatches<'static> {
+    clap::App::new("rr-format")
+        .version(common::VERSION)
+        .author(common::AUTHOR)
         .about("Display the Rust AST for a Recutils file")
 
         .arg(clap::Arg::with_name("input")
@@ -100,16 +102,16 @@ fn run() -> Result<(), FormatErr> {
              .value_name("STRING")
              .help("The string used to separate each fragment"))
 
-        .get_matches();
+        .get_matches()
+}
 
-    let stdin = io::stdin();
+fn run() -> Result<(), FormatErr> {
+    let matches = rr_format_args();
 
-    let input: Box<io::BufRead> =
-        match matches.value_of("input").unwrap_or("-") {
-            "-" => Box::new(stdin.lock()),
-            path =>
-                Box::new(io::BufReader::new(fs::File::open(path)?)),
-        };
+    let input = common::input_from_spec(
+        matches.value_of("input"))?;
+    let mut output = common::output_from_spec(
+        matches.value_of("output"))?;
 
     let template: String = match matches.value_of("mustache") {
         Some(path) => {
@@ -127,11 +129,6 @@ fn run() -> Result<(), FormatErr> {
         recfile.filter_by_type(typ);
     }
 
-    let mut output: Box<io::Write> =
-        match matches.value_of("output").unwrap_or("-") {
-            "-" => Box::new(io::stdout()),
-            path => Box::new(fs::File::open(path)?),
-        };
 
     let joiner = matches.value_of("joiner");
 

+ 4 - 2
src/tools/select.rs

@@ -1,10 +1,12 @@
 extern crate clap;
 extern crate rrecutils;
 
+mod common;
+
 fn main() {
     let matches = clap::App::new("rr-sel")
-        .version("0.0")
-        .author("Getty Ritter <rrecutils@infinitenegativeutility.com>")
+        .version(common::VERSION)
+        .author(common::AUTHOR)
         .about("Print records from a recfile")
 
         .arg(clap::Arg::with_name("type")

+ 15 - 22
src/tools/tojson.rs

@@ -2,7 +2,9 @@ extern crate clap;
 extern crate rrecutils;
 extern crate serde_json;
 
-use std::{fmt,fs,io};
+mod common;
+
+use std::fmt;
 
 use serde_json::Value;
 use serde_json::map::Map;
@@ -29,8 +31,8 @@ fn unwrap_err<L, R: fmt::Debug>(value: Result<L, R>) -> L {
 
 fn main() {
     let matches = clap::App::new("rr-to-json")
-        .version("0.0")
-        .author("Getty Ritter <rrecutils@infinitenegativeutility.com>")
+        .version(common::VERSION)
+        .author(common::AUTHOR)
         .about("Display the Rust AST for a Recutils file")
         .arg(clap::Arg::with_name("pretty")
              .short("p")
@@ -48,26 +50,17 @@ fn main() {
              .help("The desired output location (or - for stdout)"))
         .get_matches();
 
-    let stdin = io::stdin();
-
-    let input: Box<io::BufRead> =
-        match matches.value_of("input").unwrap_or("-") {
-            "-" => Box::new(stdin.lock()),
-            path =>
-                Box::new(io::BufReader::new(unwrap_err(fs::File::open(path)))),
-        };
-
-    let json = Value::Array(unwrap_err(rrecutils::Recfile::parse(input))
-                            .records
-                            .iter()
-                            .map(|x| record_to_json(x))
-                            .collect());
+    let input = unwrap_err(common::input_from_spec(
+        matches.value_of("input")));
+    let mut output = unwrap_err(common::output_from_spec(
+        matches.value_of("output")));
 
-    let mut output: Box<io::Write> =
-        match matches.value_of("output").unwrap_or("-") {
-            "-" => Box::new(io::stdout()),
-            path => Box::new(unwrap_err(fs::File::open(path))),
-        };
+    let json = Value::Array(
+        unwrap_err(rrecutils::Recfile::parse(input))
+            .records
+            .iter()
+            .map(|x| record_to_json(x))
+            .collect());
 
     let serialized = if matches.is_present("pretty") {
         unwrap_err(serde_json::to_string_pretty(&json))