Compare commits

...

15 commits

Author SHA1 Message Date
PlexSheep
acdec5836e automatic cargo CI changes
Some checks failed
cargo devel CI / cargo CI (push) Has been cancelled
2024-05-12 18:31:15 +00:00
9700ae5b35 test: check set_format #12
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m22s
2024-05-12 20:29:40 +02:00
290b959b7e refactor: more derives
Some checks failed
cargo devel CI / cargo CI (push) Has been cancelled
2024-05-12 20:29:12 +02:00
a88a03eab7 test: padded prefixed formatting #12
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m12s
2024-05-12 20:25:48 +02:00
1f91710bda chore: format tests
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m14s
2024-05-12 20:23:47 +02:00
b681a6b04d Merge branch 'test/basics' of https://git.cscherr.de/PlexSheep/numf into test/basics 2024-05-12 20:23:05 +02:00
fe01412467 test: add prefix test #12 2024-05-12 20:23:04 +02:00
PlexSheep
cd7f7cc376 automatic cargo CI changes 2024-05-12 18:21:54 +00:00
9bfc8504a4 test: add padding test #12
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m21s
2024-05-12 20:20:36 +02:00
47ae8e135b feat: add setters for FormatOptions
Some checks failed
cargo devel CI / cargo CI (push) Has been cancelled
2024-05-12 20:19:57 +02:00
8b419048ef test: testing the format #12
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m22s
2024-05-12 20:11:05 +02:00
6251546a31 Merge pull request 'feat: padding and FormatOptions #9' (#11) from feat/padding into master
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m14s
Reviewed-on: #11
2024-05-12 19:59:19 +02:00
4f269fb509 refactor: add more derives
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m11s
2024-05-12 19:54:45 +02:00
cae701815e refactor: use the cli struct as format options #11 #9
Some checks failed
cargo devel CI / cargo CI (push) Has been cancelled
2024-05-12 19:53:38 +02:00
82c1bf8d8a feat: padding and FormatOptions #9
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m14s
2024-05-12 19:34:01 +02:00
3 changed files with 367 additions and 78 deletions

View file

@ -1,8 +1,12 @@
#![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;
#[derive(Copy, Clone, Debug)]
/// formats supported by numf
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Format {
Dec,
Hex,
@ -12,6 +16,150 @@ pub enum Format {
Base32,
}
/// Describes what the formatter should do
///
/// 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,
#[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 {
/// 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;
}
/// set padding manually
pub fn set_padding(&mut self, value: bool) {
self.padding = value
}
/// get padding
pub fn padding(&self) -> bool {
self.padding
}
/// get prefix
pub fn prefix(&self) -> bool {
self.prefix
}
/// set prefix manually
pub fn set_prefix(&mut self, value: bool) {
self.prefix = value;
}
}
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 {
pub fn prefix(&self) -> String {
match self {
@ -31,18 +179,28 @@ impl Format {
}
.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();
if prefix {
if options.prefix {
buf += &self.prefix();
}
match self {
Format::Hex => {
if options.padding {
let tmp = &format!("{num:X}");
buf += &("0".repeat((2 - tmp.len() % 2) % 2) + tmp);
} else {
buf += &format!("{num:X}");
}
}
Format::Bin => {
if options.padding {
let tmp = &format!("{num:b}");
buf += &("0".repeat((8 - tmp.len() % 8) % 8) + tmp);
} else {
buf += &format!("{num:b}");
}
}
Format::Octal => {
buf += &format!("{num:o}");
}

View file

@ -3,87 +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 = '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::parse();
let mut out: Vec<String> = Vec::new();
for num in &cli.numbers {
out.push(cli.format().format(*num, cli.prefix));
for num in options.numbers() {
out.push(options.format().format(*num, &options));
}
for o in out {
println!("{o}")

200
tests/format.rs Normal file
View file

@ -0,0 +1,200 @@
use numf::format::*;
#[test]
fn format() {
let options = FormatOptions::default();
assert_eq!(Format::Dec.format(1337, &options), "1337");
assert_eq!(
Format::Dec.format(u128::MAX, &options),
format!("{}", u128::MAX)
);
assert_eq!(Format::Hex.format(0x1337, &options), "1337");
assert_eq!(
Format::Hex.format(u128::MAX, &options),
format!("{:X}", u128::MAX)
);
assert_eq!(
Format::Bin.format(0b1010001001010010010100111, &options),
"1010001001010010010100111"
);
assert_eq!(
Format::Bin.format(u128::MAX, &options),
format!("{:b}", u128::MAX)
);
assert_eq!(Format::Octal.format(0o13377331, &options), "13377331");
assert_eq!(
Format::Octal.format(u128::MAX, &options),
format!("{:o}", u128::MAX)
);
assert_eq!(Format::Base32.format(0x41414242, &options), "IFAUEQQ=");
assert_eq!(
Format::Base32.format(0x4141414141414141, &options),
"IFAUCQKBIFAUC==="
);
assert_eq!(Format::Base64.format(0x41414242, &options), "QUFCQg==");
assert_eq!(
Format::Base64.format(0x4141414141414141, &options),
"QUFBQUFBQUE="
);
}
#[test]
fn format_padding() {
let mut options = FormatOptions::default();
options.set_padding(true);
assert_eq!(Format::Dec.format(1337, &options), "1337");
assert_eq!(
Format::Dec.format(u128::MAX, &options),
format!("{}", u128::MAX)
);
assert_eq!(Format::Hex.format(0xFFF, &options), "0FFF");
assert_eq!(Format::Hex.format(0xFFFF, &options), "FFFF");
assert_eq!(
Format::Hex.format(u128::MAX, &options),
format!("{:X}", u128::MAX)
);
assert_eq!(
Format::Bin.format(0b11110000_00001111, &options),
"1111000000001111"
);
assert_eq!(
Format::Bin.format(0b110000_00001111, &options),
"0011000000001111"
);
assert_eq!(
Format::Bin.format(u128::MAX, &options),
format!("{:b}", u128::MAX)
);
assert_eq!(Format::Octal.format(0o13377331, &options), "13377331");
assert_eq!(
Format::Octal.format(u128::MAX, &options),
format!("{:o}", u128::MAX)
);
assert_eq!(Format::Base32.format(0x41414242, &options), "IFAUEQQ=");
assert_eq!(
Format::Base32.format(0x4141414141414141, &options),
"IFAUCQKBIFAUC==="
);
assert_eq!(Format::Base64.format(0x41414242, &options), "QUFCQg==");
assert_eq!(
Format::Base64.format(0x4141414141414141, &options),
"QUFBQUFBQUE="
);
}
#[test]
fn format_prefix() {
let mut options = FormatOptions::default();
options.set_prefix(true);
assert_eq!(Format::Dec.format(1337, &options), "0d1337");
assert_eq!(
Format::Dec.format(u128::MAX, &options),
format!("0d{}", u128::MAX)
);
assert_eq!(Format::Hex.format(0x1337, &options), "0x1337");
assert_eq!(
Format::Hex.format(u128::MAX, &options),
format!("0x{:X}", u128::MAX)
);
assert_eq!(
Format::Bin.format(0b1010001001010010010100111, &options),
"0b1010001001010010010100111"
);
assert_eq!(
Format::Bin.format(u128::MAX, &options),
format!("0b{:b}", u128::MAX)
);
assert_eq!(Format::Octal.format(0o13377331, &options), "0o13377331");
assert_eq!(
Format::Octal.format(u128::MAX, &options),
format!("0o{:o}", u128::MAX)
);
assert_eq!(Format::Base32.format(0x41414242, &options), "032sIFAUEQQ=");
assert_eq!(
Format::Base32.format(0x4141414141414141, &options),
"032sIFAUCQKBIFAUC==="
);
assert_eq!(Format::Base64.format(0x41414242, &options), "0sQUFCQg==");
assert_eq!(
Format::Base64.format(0x4141414141414141, &options),
"0sQUFBQUFBQUE="
);
}
#[test]
fn format_padded_prefix() {
let mut options = FormatOptions::default();
options.set_prefix(true);
options.set_padding(true);
assert_eq!(Format::Dec.format(1337, &options), "0d1337");
assert_eq!(
Format::Dec.format(u128::MAX, &options),
format!("0d{}", u128::MAX)
);
assert_eq!(Format::Hex.format(0xFFF, &options), "0x0FFF");
assert_eq!(Format::Hex.format(0xFFFF, &options), "0xFFFF");
assert_eq!(
Format::Hex.format(u128::MAX, &options),
format!("0x{:X}", u128::MAX)
);
assert_eq!(
Format::Bin.format(0b11110000_00001111, &options),
"0b1111000000001111"
);
assert_eq!(
Format::Bin.format(0b110000_00001111, &options),
"0b0011000000001111"
);
assert_eq!(
Format::Bin.format(u128::MAX, &options),
format!("0b{:b}", u128::MAX)
);
assert_eq!(Format::Octal.format(0o13377331, &options), "0o13377331");
assert_eq!(
Format::Octal.format(u128::MAX, &options),
format!("0o{:o}", u128::MAX)
);
assert_eq!(Format::Base32.format(0x41414242, &options), "032sIFAUEQQ=");
assert_eq!(
Format::Base32.format(0x4141414141414141, &options),
"032sIFAUCQKBIFAUC==="
);
assert_eq!(Format::Base64.format(0x41414242, &options), "0sQUFCQg==");
assert_eq!(
Format::Base64.format(0x4141414141414141, &options),
"0sQUFBQUFBQUE="
);
}
#[test]
fn set_format_checker() {
let mut options = FormatOptions::default();
assert_eq!(options.format(), Format::Hex);
options.set_format(Format::Base32);
assert_eq!(options.format(), Format::Base32);
options.set_format(Format::Base64);
assert_eq!(options.format(), Format::Base64);
}