aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBryan Newbold <bnewbold@archive.org>2020-05-31 15:38:58 -0700
committerBryan Newbold <bnewbold@archive.org>2020-05-31 15:39:05 -0700
commitaa85a4e665c56d00830d948465e396d566dab0c1 (patch)
tree85a31083b483cd25feb2eb6c29ae353f52b49d23 /src
parentfbdeaed50be59a5b9574674a51bede021458c45c (diff)
downloadaft-aa85a4e665c56d00830d948465e396d566dab0c1.tar.gz
aft-aa85a4e665c56d00830d948465e396d566dab0c1.zip
implement aft-head
Diffstat (limited to 'src')
-rw-r--r--src/bin/aft-head.rs69
1 files changed, 66 insertions, 3 deletions
diff --git a/src/bin/aft-head.rs b/src/bin/aft-head.rs
index b8c848c..3fecfa2 100644
--- a/src/bin/aft-head.rs
+++ b/src/bin/aft-head.rs
@@ -1,8 +1,71 @@
-
/*
* Takes the first n lines of input, passes to stdout.
*/
-fn main() {
- println!("Hello, world2!");
+use std::error::Error;
+use std::io::{self, Read, Write, BufRead};
+use structopt::StructOpt;
+use std::path::PathBuf;
+
+#[derive(StructOpt)]
+#[structopt(rename_all = "kebab-case", about = "take first N rows of input (AFT-aware)" )]
+struct Opt {
+ #[structopt(long = "--lines", short = "-n", default_value = "10")]
+ lines: u64,
+
+ #[structopt(parse(from_os_str))]
+ input: Option<PathBuf>,
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+
+ let opt = Opt::from_args();
+
+ // treat "-" as "use stdin"
+ let input = match opt.input {
+ Some(s) if s.to_string_lossy() == "-" => None,
+ other => other,
+ };
+ let stdin = io::stdin();
+ let stdin = stdin.lock();
+ let mut input: Box<dyn BufRead> = match input {
+ None => {
+ Box::new(io::BufReader::new(stdin))
+ },
+ Some(path) => {
+ let f = std::fs::File::open(path)?;
+ Box::new(io::BufReader::new(f))
+ },
+ };
+ let mut stdout = io::stdout();
+
+ // read first byte of input to check if we are getting AFT; if not just pass through
+ let mut first_byte = [0; 1];
+ let got = input.read(&mut first_byte)?;
+ if got != 1 {
+ panic!("couldn't read a byte from input");
+ };
+
+ let is_aft = first_byte[0] == 0x01;
+ if !is_aft {
+ // simple implementation of lines
+ stdout.write(&first_byte)?;
+ for l in input.lines().take(opt.lines as usize) {
+ writeln!(stdout, "{}", l?)?;
+ }
+ return Ok(())
+ };
+
+ let mut header_bytes = vec![];
+ // TODO: sanity limit on length
+ input.read_until(0x02, &mut header_bytes)?;
+ if header_bytes[header_bytes.len()-1] != 0x02 {
+ panic!("expected an AFT header");
+ };
+ stdout.write(&first_byte)?;
+ stdout.write(&header_bytes)?;
+ for l in input.lines().take(opt.lines as usize) {
+ writeln!(stdout, "{}", l?)?;
+ }
+ Ok(())
}