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 = false, short, long)]
append: bool,
#[arg(default_value_t = 0, short, long)]
nonstop: u8,
}
fn main() -> Result<()> {
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 of = || {
let f = OpenOptions::new()
.create(true)
.write(true)
.append(args.append)
.open(&args.of)
.unwrap();
f
};
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 f = of();
if let Err(e) = f.write_at(v, p) {
Err(e)
} else {
let mut h = Ok(());
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)?;
let mut b = [0u8; 1];
let mut p = 0u64;
loop {
if let Ok(0) = f.read_at(&mut b, p) {
break Ok(());
}
if let Err(e) = w(&b, p) {
break Err(e);
}
p += 1
}
})
};
if args.nonstop > 0 {
loop {
if let Err(e) = w() {
break Err(e);
}
}
} else {
w()
}
}