Initial commit
This commit is contained in:
commit
c387ea0685
4 changed files with 167 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
31
Cargo.lock
generated
Normal file
31
Cargo.lock
generated
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "b32"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://git.hitchhiker-linux.org/jeang3nie/b32_rs.git#8ceaeff9b70aec6d271ba5f1be45d2c42e2894c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base32"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"b32",
|
||||||
|
"getopts",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getopts"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "base32"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
b32 = { git = "https://git.hitchhiker-linux.org/jeang3nie/b32_rs.git" }
|
||||||
|
getopts = "0.2"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
strip = true
|
||||||
|
|
121
src/main.rs
Normal file
121
src/main.rs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
use {
|
||||||
|
b32::{Decoder, Encoder},
|
||||||
|
getopts::Options,
|
||||||
|
std::{
|
||||||
|
env,
|
||||||
|
error::Error,
|
||||||
|
fs::File,
|
||||||
|
io::{self, BufReader, BufWriter, Write},
|
||||||
|
os::fd::AsFd,
|
||||||
|
path::Path
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Operation {
|
||||||
|
Encode,
|
||||||
|
Decode,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Input {
|
||||||
|
Stdin,
|
||||||
|
Filename(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_usage(program: &str, opts: Options) {
|
||||||
|
let brief = format!("Usage: {} FILE [options]", program);
|
||||||
|
print!("{}", opts.usage(&brief));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let args = env::args().collect::<Vec<String>>();
|
||||||
|
let progname = Path::new(&args[0])
|
||||||
|
.file_name()
|
||||||
|
.map(|x| x.to_string_lossy())
|
||||||
|
.unwrap();
|
||||||
|
let mut opts = Options::new();
|
||||||
|
opts.optflag("h", "help", "print this help message");
|
||||||
|
opts.optflag("d", "decode", "decode instead of encoding");
|
||||||
|
opts.optflag("i", "ignore", "ignore whitespace when decoding");
|
||||||
|
opts.optopt("o", "output", "output to FILE instead of STDOUT", "FILE");
|
||||||
|
opts.optflag("q", "quiet", "never print headers giving file names");
|
||||||
|
opts.optflag("v", "verbose", "always print headers giving file names");
|
||||||
|
opts.optopt("w", "wrap", "wrap at columns", "COLS");
|
||||||
|
let matches = match opts.parse(&args[1..]) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(f) => {
|
||||||
|
panic!("{}", f.to_string())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if matches.opt_present("h") {
|
||||||
|
print_usage(&progname, opts);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let op = if matches.opt_present("d") {
|
||||||
|
Operation::Decode
|
||||||
|
} else {
|
||||||
|
Operation::Encode
|
||||||
|
};
|
||||||
|
let ignore = matches.opt_present("i");
|
||||||
|
let wrap: usize = if let Some(w) = matches.opt_str("w") {
|
||||||
|
w.parse()?
|
||||||
|
} else {
|
||||||
|
76
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut infiles = matches
|
||||||
|
.free
|
||||||
|
.iter()
|
||||||
|
.map(|x| {
|
||||||
|
if x == "-" {
|
||||||
|
Input::Stdin
|
||||||
|
} else {
|
||||||
|
Input::Filename(x.to_string())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if infiles.is_empty() {
|
||||||
|
infiles.push(Input::Stdin)
|
||||||
|
}
|
||||||
|
if matches.opt_present("q") && matches.opt_present("v") {
|
||||||
|
eprintln!("Error: conflicting options \"verbose\" and \"quiet\" are both present.");
|
||||||
|
print_usage(&progname, opts);
|
||||||
|
return Err("Conflicting options".into());
|
||||||
|
}
|
||||||
|
let verbose = matches.opt_present("v") || (matches.free.len() > 1 && !matches.opt_present("q"));
|
||||||
|
for f in &infiles {
|
||||||
|
let mut writer = if let Some(o) = matches.opt_str("o") {
|
||||||
|
if matches.free.len() < 2 || op == Operation::Encode {
|
||||||
|
BufWriter::new(File::open(o)?)
|
||||||
|
} else {
|
||||||
|
panic!("Attempt to decode multiple files into single file");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BufWriter::new(File::from(io::stdout().as_fd().try_clone_to_owned()?))
|
||||||
|
};
|
||||||
|
let reader = match f {
|
||||||
|
Input::Stdin => BufReader::new(File::from(io::stdin().as_fd().try_clone_to_owned()?)),
|
||||||
|
Input::Filename(f) => BufReader::new(File::open(f)?),
|
||||||
|
};
|
||||||
|
if verbose {
|
||||||
|
let fname = match f {
|
||||||
|
Input::Stdin => "Stdin",
|
||||||
|
Input::Filename(f) => f,
|
||||||
|
};
|
||||||
|
writer.write_fmt(format_args!("==> {fname} <==\n"))?;
|
||||||
|
}
|
||||||
|
match op {
|
||||||
|
Operation::Decode => {
|
||||||
|
let decoder = Decoder::new(reader, writer, None, ignore);
|
||||||
|
decoder.decode()?;
|
||||||
|
}
|
||||||
|
Operation::Encode => {
|
||||||
|
let mut encoder = Encoder::new(reader, writer, None, Some(wrap));
|
||||||
|
encoder.encode()?;
|
||||||
|
encoder.output().write_all(&[b'\n'])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue