expectocat/src/main.rs

92 lines
1.7 KiB
Rust

use std::{
env,
io::{
self,
Read,
Write,
},
};
use anyhow::{
Result,
bail,
};
use sha2::Digest;
fn main () -> Result <()> {
let mut opts = parse_opts (env::args ())?;
let mut stdin = io::stdin ().lock ();
let mut stdout = io::stdout ().lock ();
let buffer_size = 512 * 1_024;
loop {
let mut buf = vec! [0u8; buffer_size];
let bytes_read = stdin.read (&mut buf)?;
if bytes_read == 0 {
break;
}
let buf = &buf [0..bytes_read];
if let Some ((h, _)) = opts.sha384.as_mut () {
h.update (buf);
}
if let Some ((h, _)) = opts.blake3.as_mut () {
h.update (buf);
}
stdout.write_all (&buf)?;
}
if let Some ((h, expected)) = opts.sha384 {
let actual = hex::encode (h.finalize ());
if expected != actual {
bail! ("SHA384 doesn't match. Expected {}, actual {}", expected, actual);
}
}
if let Some ((h, expected)) = opts.blake3 {
let actual = h.finalize ();
if expected != actual {
bail! ("BLAKE3 doesn't match. Expected {:?}, actual {:?}", expected, actual);
}
}
Ok (())
}
#[derive (Default)]
struct Opts {
blake3: Option <(blake3::Hasher, blake3::Hash)>,
sha384: Option <(sha2::Sha384, String)>,
}
fn parse_opts <I: Iterator <Item=String>> (mut args: I)
-> Result <Opts>
{
let mut opts = Opts::default ();
loop {
let arg = match args.next () {
None => return Ok (opts),
Some (x) => x,
};
if arg == "--blake3" {
match args.next () {
None => bail! ("Missing argument for --blake3"),
Some (x) => opts.blake3 = Some ((blake3::Hasher::new (), blake3::Hash::from_hex (x)?)),
}
}
else if arg == "--sha384" {
match args.next () {
None => bail! ("Missing argument for --sha384"),
Some (x) => opts.sha384 = Some ((sha2::Sha384::new (), x)),
}
}
}
}