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;
pub type Num = u128;
@ -13,29 +16,137 @@ pub enum Format {
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].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
/// Use [Self::default] to get a basic variant or create a object yourself.
///
/// 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 {
/// add a prefix to the formatted number, such as `0x` for hex
#[arg(short, long)]
/// add a prefix (like "0x" for hex)
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,
#[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,
PlexSheep marked this conversation as resolved Outdated

also maybe shorten this

also maybe shorten this
#[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 {
PlexSheep marked this conversation as resolved
Review

can this not be shortened?

can this not be shortened?
/// set prefix
pub fn prefix(mut self, value: bool) -> Self {
self.prefix = value;
self
/// get the format that the user has configured
pub 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!()
}
}
/// 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()
}
pub fn format(&self, num: Num, options: FormatOptions) -> String {
pub fn format(&self, num: Num, options: &FormatOptions) -> String {
let mut buf = String::new();
if options.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
//! system.
use clap::{ArgGroup, Parser};
use clap_num::maybe_hex;
use clap::Parser;
mod 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() {
let cli = Cli::parse();
let options: FormatOptions = FormatOptions::default()
.padding(cli.padding)
.prefix(cli.prefix);
let options = FormatOptions::parse();
let mut out: Vec<String> = Vec::new();
for num in &cli.numbers {
out.push(cli.format().format(*num, options));
for num in options.numbers() {
out.push(options.format().format(*num, &options));
}
for o in out {
println!("{o}")