92 lines
1.7 KiB
Rust
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)),
|
|
}
|
|
}
|
|
}
|
|
}
|