use clap::Parser;
use std::{fs::*, io::*, os::unix::fs::FileExt};
#[derive(Parser)]
struct Cli {
#[arg(default_value_t = 1)]
val: u8,
#[arg(default_value_t = String::new(), short, long)]
r#if: String,
#[arg(default_value_t = String::new(), short, long)]
of: String,
#[arg(default_value_t = 1, short, long)]
bs: u64,
#[arg(default_value_t = 7, short, long)]
append: u8,
#[arg(default_value_t = 0, short, long)]
nonstop: u8,
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
let val: [u8; 1] = if args.val == 0 {
[0b0000_0000]
} else if args.val == 1 {
[0b1111_1111]
} else {
[args.val]
};
let d = |mut f: File| f.flush();
let append = if args.append > 0 { true } else { false };
let of = || {
OpenOptions::new()
.create(true)
.write(true)
.append(append)
.open(&args.of)
.unwrap()
};
let w: Box<dyn Fn(&[u8], u64) -> Result<()>> = if args.of == String::new() {
Box::new(|v, _| stdout().write_all(v))
} else {
Box::new(|v, p| {
let mut f = of();
let mut h = Ok(());
if append {
if let Err(e) = f.write_all(v) {
h = Err(e)
} else {
if let Err(e) = d(f) {
h = Err(e)
}
}
} else {
if let Err(e) = f.write_at(v, p) {
h = Err(e)
} else {
if let Err(e) = d(f) {
h = Err(e)
}
}
}
h
})
};
let w: Box<dyn Fn() -> Result<()>> = if args.r#if == String::new() {
Box::new(|| w(&val, 0))
} else {
Box::new(|| {
let f = File::open(&args.r#if).unwrap();
let mut b = vec![0u8; args.bs.try_into().unwrap()];
let mut h = Ok(());
for i in 0..=u64::MAX / args.bs {
if let Ok(0) = f.read_at(&mut b, args.bs * i) {
break;
} else if let Err(e) = f.read_at(&mut b, args.bs * i) {
h = Err(e);
break;
} else if let Err(e) = w(&b, args.bs * i) {
h = Err(e);
break;
} else {
}
}
h
})
};
if args.nonstop > 0 {
loop {
if let Err(e) = w() {
break Err(Box::new(e));
}
}
} else {
if let Err(e) = w() {
Err(Box::new(e))
} else {
Ok(())
}
}
}