From 41b7a7d3beaf5da74a64a722dbd0a57844ef8ad0 Mon Sep 17 00:00:00 2001 From: pjsier Date: Thu, 3 Oct 2019 20:57:06 -0500 Subject: [PATCH] Support reading from stdin in join --- src/cmd/join.rs | 9 ++++----- src/config.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/cmd/join.rs b/src/cmd/join.rs index 98fbbd3501..e60076f83b 100644 --- a/src/cmd/join.rs +++ b/src/cmd/join.rs @@ -1,6 +1,5 @@ use std::collections::hash_map::{HashMap, Entry}; use std::fmt; -use std::fs; use std::io; use std::iter::repeat; use std::str; @@ -9,7 +8,7 @@ use byteorder::{WriteBytesExt, BigEndian}; use csv; use CliResult; -use config::{Config, Delimiter}; +use config::{Config, Delimiter, SeekRead}; use index::Indexed; use select::{SelectColumns, Selection}; use util; @@ -278,7 +277,7 @@ impl IoState { impl Args { fn new_io_state(&self) - -> CliResult>> { + -> CliResult, Box>> { let rconf1 = Config::new(&Some(self.arg_input1.clone())) .delimiter(self.flag_delimiter) .no_headers(self.flag_no_headers) @@ -288,8 +287,8 @@ impl Args { .no_headers(self.flag_no_headers) .select(self.arg_columns2.clone()); - let mut rdr1 = rconf1.reader_file()?; - let mut rdr2 = rconf2.reader_file()?; + let mut rdr1 = rconf1.reader_file_stdin()?; + let mut rdr2 = rconf2.reader_file_stdin()?; let (sel1, sel2) = self.get_selections( &rconf1, &mut rdr1, &rconf2, &mut rdr2)?; Ok(IoState { diff --git a/src/config.rs b/src/config.rs index 1816fa1cb0..7cb42230a5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -70,6 +70,10 @@ pub struct Config { quoting: bool, } +// Empty trait as an alias for Seek and Read that avoids auto trait errors +pub trait SeekRead: io::Seek + io::Read {} +impl SeekRead for T {} + impl Config { pub fn new(path: &Option) -> Config { let (path, delim) = match *path { @@ -212,6 +216,21 @@ impl Config { } } + pub fn reader_file_stdin(&self) -> io::Result>> { + Ok(match self.path { + None => { + // Create a buffer in memory when stdin needs to be indexed + let mut buffer: Vec = Vec::new(); + let stdin = io::stdin(); + stdin.lock().read_to_end(&mut buffer)?; + self.from_reader(Box::new(io::Cursor::new(buffer))) + }, + Some(ref p) => { + self.from_reader(Box::new(fs::File::open(p).unwrap())) + }, + }) + } + pub fn index_files(&self) -> io::Result, fs::File)>> { let (csv_file, idx_file) = match (&self.path, &self.idx_path) {