feat: padding and FormatOptions #9 #11

Merged
PlexSheep merged 3 commits from feat/padding into master 2024-05-12 19:59:19 +02:00
2 changed files with 131 additions and 98 deletions
Showing only changes of commit cae701815e - Show all commits

View File

@ -1,3 +1,6 @@
#![allow(dead_code)] // this is exported to lib.rs
use clap::{ArgGroup, Parser};
use clap_num::maybe_hex;
use libpt::bintols::split; use libpt::bintols::split;
pub type Num = u128; pub type Num = u128;
@ -13,29 +16,137 @@ pub enum Format {
Base32, Base32,
} }
/// Options to use when formatting a number /// Describes what the formatter should do
/// ///
PlexSheep marked this conversation as resolved
Review

Use the Cli struct instead somehow. It already contains all this information

Use the Cli struct instead somehow. It already contains all this information
/// Used by [Format::format]. /// Use [Self::default] to get a basic variant or create a object yourself.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] ///
/// This struct can be parsed with [clap] derive.
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
#[command(
author,
version,
about,
long_about,
help_template = r#"{about-section}
{usage-heading} {usage}
{all-args}{tab}
{name}: {version}
Author: {author-with-newline}
"#
)]
#[clap(group(
ArgGroup::new("format")
.args(&["hex", "bin", "oct", "dec", "base64", "base32"]),
))]
pub struct FormatOptions { pub struct FormatOptions {
/// add a prefix to the formatted number, such as `0x` for hex #[arg(short, long)]
/// add a prefix (like "0x" for hex)
prefix: bool, prefix: bool,
/// fill the formatted number with zeros (or the equivalent) to make a whole byte #[arg(short = 'P', long)]
/// add a padding to make the number at least one byte long
///
/// For example, `0b1100` will be `0b00001100` with this.
/// This does not apply to all formats, only hexadecimal and binary.
padding: bool, padding: bool,
#[arg(short = 'x', long, default_value_t = true)]
/// format to hexadecimal
hex: bool,
#[arg(short, long)]
/// format to binary
bin: bool,
#[arg(short, long)]
/// format to decimal
dec: bool,
#[arg(short, long)]
/// format to octal
oct: bool,
#[arg(short = 's', long)]
/// format to base64
base64: bool,
#[arg(short = 'z', long)]
/// format to base32
base32: bool,
#[clap(value_parser=maybe_hex::<Num>, required=true)]
/// at least one number that should be formatted
///
/// supports either base 10 or base 16 inputs (with 0xaaaa)
numbers: Vec<Num>,
} }
impl FormatOptions { impl FormatOptions {
PlexSheep marked this conversation as resolved
Review

can this not be shortened?

can this not be shortened?
/// set prefix /// get the format that the user has configured
pub fn prefix(mut self, value: bool) -> Self { pub fn format(&self) -> Format {
self.prefix = value; if self.oct {
self Format::Octal
} else if self.bin {
Format::Bin
} else if self.dec {
Format::Dec
} else if self.base64 {
Format::Base64
} else if self.base32 {
Format::Base32
} else if self.hex {
Format::Hex
} else {
unreachable!()
}
}
/// set the format manually
pub fn set_format(&mut self, format: Format) {
self.bin = false;
self.oct = false;
self.dec = false;
self.hex = false;
self.base64 = false;
self.base32 = false;
match format {
Format::Bin => self.bin = true,
Format::Hex => self.hex = true,
Format::Octal => self.oct = true,
Format::Base64 => self.base64 = true,
Format::Base32 => self.base32 = true,
Format::Dec => self.dec = true,
}
}
/// get numbers
pub fn numbers(&self) -> &[u128] {
self.numbers.as_ref()
}
/// set numbers manually
pub fn set_numbers(&mut self, numbers: Vec<Num>) {
self.numbers = numbers;
}
/// get padding
pub fn padding(&self) -> bool {
self.padding
}
/// get prefix
pub fn prefix(&self) -> bool {
self.prefix
}
}
impl Default for FormatOptions {
fn default() -> Self {
Self {
padding: false,
prefix: false,
oct: false,
hex: true,
bin: false,
base32: false,
base64: false,
dec: false,
numbers: vec![],
} }
/// set padding
///
/// Does not apply to all formats
pub fn padding(mut self, value: bool) -> Self {
self.padding = value;
self
} }
} }
@ -58,7 +169,7 @@ impl Format {
} }
.to_string() .to_string()
} }
pub fn format(&self, num: Num, options: FormatOptions) -> String { pub fn format(&self, num: Num, options: &FormatOptions) -> String {
let mut buf = String::new(); let mut buf = String::new();
if options.prefix { if options.prefix {
buf += &self.prefix(); buf += &self.prefix();

View File

@ -3,96 +3,18 @@
//! This binary should just take any amount of numbers and print them out formatted to some other //! This binary should just take any amount of numbers and print them out formatted to some other
//! system. //! system.
use clap::{ArgGroup, Parser}; use clap::Parser;
use clap_num::maybe_hex;
mod format; mod format;
use format::*; use format::*;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
#[command(
author,
version,
about,
long_about,
help_template = r#"{about-section}
{usage-heading} {usage}
{all-args}{tab}
{name}: {version}
Author: {author-with-newline}
"#
)]
#[clap(group(
ArgGroup::new("format")
.args(&["hex", "bin", "oct", "dec", "base64", "base32"]),
))]
struct Cli {
#[arg(short, long)]
/// add a prefix (like "0x" for hex)
prefix: bool,
#[arg(short = 'P', long)]
/// add a padding to make the number at least one byte long
///
/// For example, `0b1100` will be `0b00001100` with this.
/// This does not apply to all formats, only hexadecimal and binary.
padding: bool,
#[arg(short = 'x', long, default_value_t = true)]
/// format to hexadecimal
hex: bool,
#[arg(short, long)]
/// format to binary
bin: bool,
#[arg(short, long)]
/// format to decimal
dec: bool,
#[arg(short, long)]
/// format to octal
oct: bool,
#[arg(short = 's', long)]
/// format to base64
base64: bool,
#[arg(short = 'z', long)]
/// format to base32
base32: bool,
#[clap(value_parser=maybe_hex::<Num>, required=true)]
/// at least one number that should be formatted
///
/// supports either base 10 or base 16 inputs (with 0xaaaa)
numbers: Vec<Num>,
}
impl Cli {
fn format(&self) -> Format {
if self.oct {
Format::Octal
} else if self.bin {
Format::Bin
} else if self.dec {
Format::Dec
} else if self.base64 {
Format::Base64
} else if self.base32 {
Format::Base32
} else if self.hex {
Format::Hex
} else {
unreachable!()
}
}
}
fn main() { fn main() {
let cli = Cli::parse(); let options = FormatOptions::parse();
let options: FormatOptions = FormatOptions::default()
.padding(cli.padding)
.prefix(cli.prefix);
let mut out: Vec<String> = Vec::new(); let mut out: Vec<String> = Vec::new();
for num in &cli.numbers { for num in options.numbers() {
out.push(cli.format().format(*num, options)); out.push(options.format().format(*num, &options));
} }
for o in out { for o in out {
println!("{o}") println!("{o}")