Added more options for input data
+ -b flag allows you to specify the base of the input data, useful if the data does not have a prefix or is a strange base + -i allows you to pass in array or string datamain
parent
d956c111d8
commit
9244cebad3
14
README.md
14
README.md
|
@ -64,18 +64,20 @@ Formaty 0.1.0
|
||||||
Arbitrary Binary Data Formatting
|
Arbitrary Binary Data Formatting
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
formaty [OPTIONS] <format> [data]...
|
formaty [OPTIONS] <format> [data]...
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-V, --version Prints version information
|
-V, --version Prints version information
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-c, --config <config> Path to the format config
|
-b, --base <base> Base of the input values
|
||||||
|
-c, --config <config> Path to the format config
|
||||||
|
-i, --input_type <input-type> Input data type [default: array]
|
||||||
|
|
||||||
ARGS:
|
ARGS:
|
||||||
<format> Format to parse data as
|
<format> Format to parse data as
|
||||||
<data>... Raw data
|
<data>... Raw data
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::FormatyError;
|
use crate::error::FormatyError;
|
||||||
use crate::formatter::format::Format;
|
use crate::formatter::format::Format;
|
||||||
use crate::parser::parse_bytes_from_input_arg;
|
use crate::parser::InputTypes;
|
||||||
use formatter::FormatConfig;
|
use formatter::FormatConfig;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
@ -21,6 +21,17 @@ pub struct Args {
|
||||||
)]
|
)]
|
||||||
config: Option<PathBuf>,
|
config: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[structopt(
|
||||||
|
help = "Input data type",
|
||||||
|
short = "i",
|
||||||
|
long = "input_type",
|
||||||
|
default_value = "array"
|
||||||
|
)]
|
||||||
|
input_type: InputTypes,
|
||||||
|
|
||||||
|
#[structopt(help = "Base of the input values", short = "b", long = "base")]
|
||||||
|
base: Option<u32>,
|
||||||
|
|
||||||
#[structopt(help = "Format to parse data as")]
|
#[structopt(help = "Format to parse data as")]
|
||||||
format: String,
|
format: String,
|
||||||
|
|
||||||
|
@ -35,7 +46,7 @@ fn init() -> Result<(Vec<u8>, Format), FormatyError> {
|
||||||
|
|
||||||
let format = config.get_format(&args.format)?;
|
let format = config.get_format(&args.format)?;
|
||||||
|
|
||||||
let data = parse_bytes_from_input_arg(args.data)?;
|
let data = args.input_type.parse_input(args.data, args.base)?;
|
||||||
Ok((data, format))
|
Ok((data, format))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,89 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum InputTypes {
|
||||||
|
Array,
|
||||||
|
String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for InputTypes {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
|
||||||
|
match s.as_str() {
|
||||||
|
"array" | "a" => Ok(Self::Array),
|
||||||
|
"string" | "s" => Ok(Self::String),
|
||||||
|
_ => Err(format!("Invalid input type '{}'", s)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputTypes {
|
||||||
|
fn parse_byte_default(element: &str) -> Result<u8, ParseIntError> {
|
||||||
|
if element.starts_with("0x") || element.starts_with("0X") {
|
||||||
|
u8::from_str_radix(&element[2..], 16)
|
||||||
|
} else if element.starts_with("0b") || element.starts_with("0B") {
|
||||||
|
u8::from_str_radix(&element[2..], 2)
|
||||||
|
} else if element.starts_with('h') || element.starts_with('H') {
|
||||||
|
u8::from_str_radix(&element[1..], 16)
|
||||||
|
} else if element.len() > 1 && element.starts_with('0') {
|
||||||
|
u8::from_str_radix(&element[1..], 8)
|
||||||
|
} else {
|
||||||
|
element.parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_byte_base(element: &str, base: u32) -> Result<u8, ParseIntError> {
|
||||||
|
u8::from_str_radix(element, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_array(elements: Vec<String>, base: Option<u32>) -> Result<Vec<u8>, ParseIntError> {
|
||||||
|
elements
|
||||||
|
.iter()
|
||||||
|
.map(|element| {
|
||||||
|
if let Some(base) = base {
|
||||||
|
Self::parse_byte_base(element, base)
|
||||||
|
} else {
|
||||||
|
Self::parse_byte_default(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_input(
|
||||||
|
&self,
|
||||||
|
src: Vec<String>,
|
||||||
|
base: Option<u32>,
|
||||||
|
) -> Result<Vec<u8>, ByteArrayParseErr> {
|
||||||
|
if src.is_empty() {
|
||||||
|
return Err(ByteArrayParseErr::EmptySrcArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
let str_arr = if src.len() == 1 {
|
||||||
|
src[0]
|
||||||
|
.replace(',', " ")
|
||||||
|
.replace('[', "")
|
||||||
|
.replace(']', "")
|
||||||
|
.split_whitespace()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
src
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = match self {
|
||||||
|
InputTypes::Array => Self::parse_array(str_arr, base)?,
|
||||||
|
InputTypes::String => str_arr.join(" ").as_bytes().to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ByteArrayParseErr {
|
pub enum ByteArrayParseErr {
|
||||||
|
@ -24,54 +108,15 @@ impl Display for ByteArrayParseErr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bytes_from_str_array(src: Vec<String>) -> Result<Vec<u8>, ByteArrayParseErr> {
|
|
||||||
src.iter()
|
|
||||||
.map(|element| {
|
|
||||||
if element.starts_with("0x") || element.starts_with("0X") {
|
|
||||||
u8::from_str_radix(&element[2..], 16)
|
|
||||||
} else if element.starts_with("0b") || element.starts_with("0B") {
|
|
||||||
u8::from_str_radix(&element[2..], 2)
|
|
||||||
} else if element.starts_with('h') || element.starts_with('H') {
|
|
||||||
u8::from_str_radix(&element[1..], 16)
|
|
||||||
} else if element.len() > 1 && element.starts_with('0') {
|
|
||||||
u8::from_str_radix(&element[1..], 8)
|
|
||||||
} else {
|
|
||||||
element.parse()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|e| e.map_err(ByteArrayParseErr::from))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_bytes_from_input_arg(src: Vec<String>) -> Result<Vec<u8>, ByteArrayParseErr> {
|
|
||||||
if src.is_empty() {
|
|
||||||
return Err(ByteArrayParseErr::EmptySrcArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
let str_arr = if src.len() == 1 {
|
|
||||||
src[0]
|
|
||||||
.replace(',', " ")
|
|
||||||
.replace('[', "")
|
|
||||||
.replace(']', "")
|
|
||||||
.split_whitespace()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
src
|
|
||||||
};
|
|
||||||
|
|
||||||
bytes_from_str_array(str_arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::parser::parse_bytes_from_input_arg;
|
use crate::parser::InputTypes;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_base_10_array() {
|
fn parse_base_10_array() {
|
||||||
let array = vec!["[0, 1, 2, 3, 4]".to_string()];
|
let array = vec!["[0, 1, 2, 3, 4]".to_string()];
|
||||||
|
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -80,7 +125,7 @@ mod tests {
|
||||||
fn parse_base_2_array() {
|
fn parse_base_2_array() {
|
||||||
let array = vec!["[0b0, 0b1, 0b10, 0b11, 0b100]".to_string()];
|
let array = vec!["[0b0, 0b1, 0b10, 0b11, 0b100]".to_string()];
|
||||||
|
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -89,7 +134,7 @@ mod tests {
|
||||||
fn parse_base_8_array() {
|
fn parse_base_8_array() {
|
||||||
let array = vec!["[00, 01, 02, 03, 04]".to_string()];
|
let array = vec!["[00, 01, 02, 03, 04]".to_string()];
|
||||||
|
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -98,7 +143,7 @@ mod tests {
|
||||||
fn parse_base_16_array() {
|
fn parse_base_16_array() {
|
||||||
let array = vec!["[0x0, 0x1, 0x2, h3, H4]".to_string()];
|
let array = vec!["[0x0, 0x1, 0x2, h3, H4]".to_string()];
|
||||||
|
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -107,7 +152,7 @@ mod tests {
|
||||||
fn parse_base_mixed() {
|
fn parse_base_mixed() {
|
||||||
let array = vec!["[00 0x1, 2, h3, H4]".to_string()];
|
let array = vec!["[00 0x1, 2, h3, H4]".to_string()];
|
||||||
|
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -121,7 +166,7 @@ mod tests {
|
||||||
"3".to_string(),
|
"3".to_string(),
|
||||||
"4".to_string(),
|
"4".to_string(),
|
||||||
];
|
];
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
@ -129,8 +174,19 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_no_braces_one_arg() {
|
fn parse_no_braces_one_arg() {
|
||||||
let array = vec!["0 1 2 3 4".to_string()];
|
let array = vec!["0 1 2 3 4".to_string()];
|
||||||
let out = parse_bytes_from_input_arg(array).unwrap();
|
let out = InputTypes::Array.parse_input(array, None).unwrap();
|
||||||
|
|
||||||
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
assert_eq!(out, vec![0, 1, 2, 3, 4])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_string() {
|
||||||
|
let string = "Hello World!";
|
||||||
|
|
||||||
|
let out = InputTypes::String
|
||||||
|
.parse_input(vec![string.to_string()], None)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(string.as_bytes(), out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue