use std::env;
use std::io::{self, Read, Write};
fn main() {
let args: Vec<String> = env::args().collect();
if args.iter().any(|a| a == "-h" || a == "--help") {
println!("base256 - dense byte to unicode encoding");
println!();
println!("Usage: base256 [OPTIONS]");
println!();
println!("Options:");
println!(" -e, --encode Encode raw bytes to base256 (default)");
println!(" -d, --decode Decode base256 to raw bytes");
println!(" -x, --hex Use hex format for output");
println!(" -X, --from-hex Read hex format as input");
println!(" -h, --help Show this help message");
println!();
println!("Examples:");
println!(" # Encode 32 bytes to base256");
println!(" head -c 32 /dev/urandom | base256");
println!();
println!(" # Decode base256 to raw bytes");
println!(" echo '_Гî┤gÅωυ3î·ж┤;m<ÆñûЩ;ÏÌЦXXλÎ2M÷·' | base256 -d | xxd");
println!();
println!(" # Encode bytes to hex");
println!(" head -c 32 /dev/urandom | base256 -x");
println!();
println!(" # Convert hex to base256");
println!(
" echo '3ad8a5417c8d6ef7477d97f734cb85296e2502e1c781ec3aef8e0b9a5acdde0b' | base256 -X"
);
println!();
println!(" # Convert base256 to hex");
println!(" echo '_Гî┤gÅωυ3î·ж┤;m<ÆñûЩ;ÏÌЦXXλÎ2M÷·' | base256 -dx");
println!();
println!(" # Convert hex to raw bytes");
println!(
" echo '3ad8a5417c8d6ef7477d97f734cb85296e2502e1c781ec3aef8e0b9a5acdde0b' | base256 -Xd"
);
return;
}
let mut decode = false;
let mut hex_out = false;
let mut hex_in = false;
for arg in &args[1..] {
if arg.starts_with('-') && !arg.starts_with("--") {
for ch in arg.chars().skip(1) {
match ch {
'd' => decode = true,
'x' => hex_out = true,
'X' => hex_in = true,
'e' => {} _ => {}
}
}
} else if arg == "--decode" {
decode = true;
} else if arg == "--hex" {
hex_out = true;
} else if arg == "--from-hex" {
hex_in = true;
} else if arg == "--encode" {
}
}
let mut input = Vec::new();
io::stdin().read_to_end(&mut input).unwrap();
if input.is_empty() {
return;
}
let trimmed = if input.ends_with(b"\n") {
&input[..input.len() - 1]
} else {
&input[..]
};
match (hex_in, decode, hex_out) {
(true, false, false) => {
if trimmed.len() != 64 {
eprintln!("error: expected 64 hex chars, got {}", trimmed.len());
std::process::exit(1);
}
let mut hex_array = [0u8; 64];
hex_array.copy_from_slice(&trimmed[..64]);
match b256::Base256::from_hex(&hex_array) {
Some(encoded) => {
for c in &encoded {
print!("{}", c);
}
println!();
}
None => {
eprintln!("error: invalid hex input");
std::process::exit(1);
}
}
}
(true, true, false) => {
if trimmed.len() != 64 {
eprintln!("error: expected 64 hex chars, got {}", trimmed.len());
std::process::exit(1);
}
let mut hex_array = [0u8; 64];
hex_array.copy_from_slice(&trimmed[..64]);
match b256::Base256::hex_to_bytes(&hex_array) {
Some(bytes) => {
io::stdout().write_all(&bytes).unwrap();
}
None => {
eprintln!("error: invalid hex input");
std::process::exit(1);
}
}
}
(true, false, true) => {
if trimmed.len() != 64 {
eprintln!("error: expected 64 hex chars, got {}", trimmed.len());
std::process::exit(1);
}
let mut hex_array = [0u8; 64];
hex_array.copy_from_slice(&trimmed[..64]);
if b256::Base256::hex_to_bytes(&hex_array).is_none() {
eprintln!("error: invalid hex input");
std::process::exit(1);
}
io::stdout().write_all(trimmed).unwrap();
println!();
}
(false, true, true) => {
let s = std::str::from_utf8(trimmed).unwrap_or_else(|_| {
eprintln!("error: invalid UTF-8 input");
std::process::exit(1);
});
let chars: Vec<char> = s.chars().collect();
if chars.len() != 32 {
eprintln!("error: expected 32 chars, got {}", chars.len());
std::process::exit(1);
}
let mut char_array = ['\0'; 32];
char_array.copy_from_slice(&chars);
match b256::Base256::to_hex(&char_array) {
Some(hex) => {
io::stdout().write_all(&hex).unwrap();
println!();
}
None => {
eprintln!("error: invalid base256 character");
std::process::exit(1);
}
}
}
(false, true, false) => {
let s = std::str::from_utf8(trimmed).unwrap_or_else(|_| {
eprintln!("error: invalid UTF-8 input");
std::process::exit(1);
});
let chars: Vec<char> = s.chars().collect();
if chars.len() != 32 {
eprintln!("error: expected 32 chars, got {}", chars.len());
std::process::exit(1);
}
let mut char_array = ['\0'; 32];
char_array.copy_from_slice(&chars);
match b256::Base256::decode(&char_array) {
Some(bytes) => {
io::stdout().write_all(&bytes).unwrap();
}
None => {
eprintln!("error: invalid base256 character");
std::process::exit(1);
}
}
}
(false, false, true) => {
if trimmed.len() != 32 {
eprintln!("error: expected 32 bytes, got {}", trimmed.len());
std::process::exit(1);
}
let mut byte_array = [0u8; 32];
byte_array.copy_from_slice(&trimmed[..32]);
let hex = b256::Base256::bytes_to_hex(&byte_array);
io::stdout().write_all(&hex).unwrap();
println!();
}
(false, false, false) => {
if trimmed.len() != 32 {
eprintln!("error: expected 32 bytes, got {}", trimmed.len());
std::process::exit(1);
}
let mut byte_array = [0u8; 32];
byte_array.copy_from_slice(&trimmed[..32]);
let encoded = b256::Base256::encode(&byte_array);
for c in &encoded {
print!("{}", c);
}
println!();
}
(true, true, true) => {
eprintln!("error: -Xdx makes no sense (hex to hex through decode)");
std::process::exit(1);
}
}
}