generated from PlexSheep/rs-base
feat: padding and FormatOptions #9 #11
156
src/format.rs
156
src/format.rs
|
@ -1,7 +1,11 @@
|
||||||
|
#![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;
|
||||||
|
|
||||||
|
/// formats supported by numf
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
Dec,
|
Dec,
|
||||||
|
@ -12,6 +16,140 @@ pub enum Format {
|
||||||
Base32,
|
Base32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes what the formatter should do
|
||||||
|
///
|
||||||
PlexSheep marked this conversation as resolved
|
|||||||
|
/// Use [Self::default] to get a basic variant or create a object yourself.
|
||||||
|
///
|
||||||
|
/// This struct can be parsed with [clap] derive.
|
||||||
|
#[derive(Parser, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[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 {
|
||||||
|
#[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,
|
||||||
PlexSheep marked this conversation as resolved
Outdated
PlexSheep
commented
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
PlexSheep
commented
can this not be shortened? can this not be shortened?
|
|||||||
|
/// 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![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Format {
|
impl Format {
|
||||||
pub fn prefix(&self) -> String {
|
pub fn prefix(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
|
@ -31,17 +169,27 @@ impl Format {
|
||||||
}
|
}
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
pub fn format(&self, num: Num, prefix: bool) -> String {
|
pub fn format(&self, num: Num, options: &FormatOptions) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if prefix {
|
if options.prefix {
|
||||||
buf += &self.prefix();
|
buf += &self.prefix();
|
||||||
}
|
}
|
||||||
match self {
|
match self {
|
||||||
Format::Hex => {
|
Format::Hex => {
|
||||||
buf += &format!("{num:X}");
|
if options.padding {
|
||||||
|
let tmp = &format!("{num:X}");
|
||||||
|
buf += &("0".repeat((2 - tmp.len() % 2) % 2) + tmp);
|
||||||
|
} else {
|
||||||
|
buf += &format!("{num:X}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Format::Bin => {
|
Format::Bin => {
|
||||||
buf += &format!("{num:b}");
|
if options.padding {
|
||||||
|
let tmp = &format!("{num:b}");
|
||||||
|
buf += &("0".repeat((8 - tmp.len() % 8) % 8) + tmp);
|
||||||
|
} else {
|
||||||
|
buf += &format!("{num:b}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Format::Octal => {
|
Format::Octal => {
|
||||||
buf += &format!("{num:o}");
|
buf += &format!("{num:o}");
|
||||||
|
|
77
src/main.rs
77
src/main.rs
|
@ -3,87 +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 = '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 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, cli.prefix));
|
out.push(options.format().format(*num, &options));
|
||||||
}
|
}
|
||||||
for o in out {
|
for o in out {
|
||||||
println!("{o}")
|
println!("{o}")
|
||||||
|
|
Reference in New Issue
Use the Cli struct instead somehow. It already contains all this information