From 265ab0902b1945debc2668b84e0563c14bedba81 Mon Sep 17 00:00:00 2001 From: "Christoph J. Scherr" Date: Fri, 6 Sep 2024 11:27:18 +0200 Subject: [PATCH] refactor: write in binary now --- src/format.rs | 89 +++++++++++++++++++++++++++++++++------------------ src/main.rs | 9 ++++-- 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/format.rs b/src/format.rs index 6bc0ae3..7fbeb04 100644 --- a/src/format.rs +++ b/src/format.rs @@ -35,6 +35,8 @@ pub enum Format { Octal, Base64, Base32, + /// Write raw data to stdout, not text + Raw, } /// Describes what the formatter should do @@ -59,7 +61,7 @@ Author: {author-with-newline} )] #[clap(group( ArgGroup::new("format") - .args(&["hex", "bin", "oct", "dec", "base64", "base32"]), + .args(&["hex", "bin", "oct", "dec", "base64", "base32", "raw"]), ))] pub struct FormatOptions { #[arg(short, long)] @@ -86,6 +88,9 @@ pub struct FormatOptions { #[arg(short = 's', long)] /// format to base64 base64: bool, + #[arg(short = 'a', long)] + /// format raw, no text + raw: bool, #[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser::)] /// output random numbers /// @@ -148,9 +153,11 @@ impl FormatOptions { self.dec = false; self.hex = false; self.base64 = false; + self.raw = false; self.base32 = false; match format { Format::Bin => self.bin = true, + Format::Raw => self.raw = true, Format::Hex => self.hex = true, Format::Octal => self.oct = true, Format::Base64 => self.base64 = true, @@ -223,6 +230,7 @@ impl Default for FormatOptions { oct: false, hex: true, bin: false, + raw: false, base32: false, base64: false, dec: false, @@ -234,52 +242,69 @@ impl Default for FormatOptions { } impl Format { + pub fn prefix_str(&self) -> String { + String::from_utf8_lossy(&self.prefix()).to_string() + } + /// Get the perfix for that [Format] - pub fn prefix(&self) -> String { + pub fn prefix(&self) -> Vec { match self { // apperently used nowhere, sometimes 0 is used as a prefix but I // think this makes it more clear that this is decimal - Format::Dec => "0d", + Format::Dec => b"0d".to_vec(), + Format::Raw => [].to_vec(), // TODO: find a better way to deal with this // very common - Format::Hex => "0x", + Format::Hex => b"0x".to_vec(), // very common - Format::Bin => "0b", + Format::Bin => b"0b".to_vec(), // somewhat common - Format::Octal => "0o", + Format::Octal => b"0o".to_vec(), // perl and a few other programs seem to use this too - Format::Base64 => "0s", + Format::Base64 => b"0s".to_vec(), // no idea, I made this up - Format::Base32 => "032s", + Format::Base32 => b"032s".to_vec(), } - .to_string() } /// format a number with a [Format] and [FormatOptions] - pub fn format(&self, num: NumberType, options: &FormatOptions) -> String { - let mut buf = String::new(); + pub fn format(&self, num: NumberType, options: &FormatOptions) -> Vec { + let mut buf: Vec = Vec::new(); if options.prefix() { - buf += &self.prefix(); + buf.append(&mut self.prefix()); } match self { Format::Hex => { if options.padding() { let tmp = &format!("{num:X}"); - buf += &("0".repeat((2 - tmp.len() % 2) % 2) + tmp); + let tmp1 = &("0".repeat((2 - tmp.len() % 2) % 2) + tmp); + buf.append(&mut tmp1.as_bytes().to_owned()); } else { - buf += &format!("{num:X}"); + buf.append(&mut format!("{num:X}").as_bytes().to_owned()); } } Format::Bin => { if options.padding() { let tmp = &format!("{num:b}"); - buf += &("0".repeat((8 - tmp.len() % 8) % 8) + tmp); + let tmp1 = &("0".repeat((8 - tmp.len() % 8) % 8) + tmp); + buf.append(&mut tmp1.as_bytes().to_owned()); } else { - buf += &format!("{num:b}"); + buf.append(&mut format!("{num:b}").as_bytes().to_owned()); } } - Format::Octal => buf += &format!("{num:o}"), - Format::Dec => buf += &format!("{num}"), - Format::Base64 => buf += &fast32::base64::RFC4648.encode(&split::unsigned_to_vec(num)), - Format::Base32 => buf += &fast32::base32::RFC4648.encode(&split::unsigned_to_vec(num)), + Format::Octal => buf.append(&mut format!("{num:o}").as_bytes().to_owned()), + Format::Dec => buf.append(&mut format!("{num}").as_bytes().to_owned()), + Format::Base64 => buf.append( + &mut fast32::base64::RFC4648 + .encode(&split::unsigned_to_vec(num)) + .as_bytes() + .to_owned(), + ), + Format::Base32 => buf.append( + &mut fast32::base32::RFC4648 + .encode(&split::unsigned_to_vec(num)) + .as_bytes() + .to_owned(), + ), + Format::Raw => buf.append(&mut split::unsigned_to_vec(num)), } buf } @@ -324,8 +349,8 @@ where >::Error: std::marker::Sync, >::Error: 'static, { - if s.starts_with(&Format::Dec.prefix()) || s.parse::().is_ok() { - let s = match s.strip_prefix(&Format::Dec.prefix()) { + if s.starts_with(&Format::Dec.prefix_str()) || s.parse::().is_ok() { + let s = match s.strip_prefix(&Format::Dec.prefix_str()) { Some(sr) => sr, None => s, }; @@ -336,8 +361,8 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Hex.prefix()) { - let s = match s.strip_prefix(&Format::Hex.prefix()) { + } else if s.starts_with(&Format::Hex.prefix_str()) { + let s = match s.strip_prefix(&Format::Hex.prefix_str()) { Some(sr) => sr, None => s, }; @@ -348,8 +373,8 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Octal.prefix()) { - let s = match s.strip_prefix(&Format::Octal.prefix()) { + } else if s.starts_with(&Format::Octal.prefix_str()) { + let s = match s.strip_prefix(&Format::Octal.prefix_str()) { Some(sr) => sr, None => s, }; @@ -360,8 +385,8 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Bin.prefix()) { - let s = match s.strip_prefix(&Format::Bin.prefix()) { + } else if s.starts_with(&Format::Bin.prefix_str()) { + let s = match s.strip_prefix(&Format::Bin.prefix_str()) { Some(sr) => sr, None => s, }; @@ -372,8 +397,8 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Base64.prefix()) { - let s = match s.strip_prefix(&Format::Base64.prefix()) { + } else if s.starts_with(&Format::Base64.prefix_str()) { + let s = match s.strip_prefix(&Format::Base64.prefix_str()) { Some(sr) => sr, None => s, }; @@ -384,8 +409,8 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Base32.prefix()) { - let s = match s.strip_prefix(&Format::Base32.prefix()) { + } else if s.starts_with(&Format::Base32.prefix_str()) { + let s = match s.strip_prefix(&Format::Base32.prefix_str()) { Some(sr) => sr, None => s, }; diff --git a/src/main.rs b/src/main.rs index 152543b..4eeca51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::io::{IsTerminal, Read}; +use std::io::{stdout, IsTerminal, Read, Write}; use std::process::exit; use clap::{CommandFactory, Parser}; @@ -61,13 +61,16 @@ fn main() -> anyhow::Result<()> { exit(1); } - let mut out: Vec = Vec::new(); + let mut out: Vec> = Vec::new(); for num in options.numbers() { out.push(options.format().format(*num, &options)); } for o in out { - println!("{o}") + let mut stdout = std::io::stdout(); + stdout.write_all(&o)?; + stdout.write_all(b"\n")?; + stdout.flush()?; } Ok(()) }