diff --git a/README.md b/README.md index 4bab36e..a8ed35d 100644 --- a/README.md +++ b/README.md @@ -64,18 +64,20 @@ Formaty 0.1.0 Arbitrary Binary Data Formatting USAGE: - formaty [OPTIONS] [data]... +formaty [OPTIONS] [data]... FLAGS: - -h, --help Prints help information - -V, --version Prints version information +-h, --help Prints help information +-V, --version Prints version information OPTIONS: - -c, --config Path to the format config +-b, --base Base of the input values +-c, --config Path to the format config +-i, --input_type Input data type [default: array] ARGS: - Format to parse data as - ... Raw data + Format to parse data as +... Raw data ``` ## License diff --git a/src/main.rs b/src/main.rs index 0fe106b..1c272ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use crate::error::FormatyError; use crate::formatter::format::Format; -use crate::parser::parse_bytes_from_input_arg; +use crate::parser::InputTypes; use formatter::FormatConfig; use std::path::PathBuf; use structopt::StructOpt; @@ -21,6 +21,17 @@ pub struct Args { )] config: Option, + #[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, + #[structopt(help = "Format to parse data as")] format: String, @@ -35,7 +46,7 @@ fn init() -> Result<(Vec, Format), FormatyError> { 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)) } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 626fae4..accd6b8 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,5 +1,89 @@ +use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; 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 { + 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 { + 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::from_str_radix(element, base) + } + + fn parse_array(elements: Vec, base: Option) -> Result, 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, + base: Option, + ) -> Result, 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)] pub enum ByteArrayParseErr { @@ -24,54 +108,15 @@ impl Display for ByteArrayParseErr { } } -fn bytes_from_str_array(src: Vec) -> Result, 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) -> Result, 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)] mod tests { - use crate::parser::parse_bytes_from_input_arg; + use crate::parser::InputTypes; #[test] fn parse_base_10_array() { 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]) } @@ -80,7 +125,7 @@ mod tests { fn parse_base_2_array() { 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]) } @@ -89,7 +134,7 @@ mod tests { fn parse_base_8_array() { 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]) } @@ -98,7 +143,7 @@ mod tests { fn parse_base_16_array() { 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]) } @@ -107,7 +152,7 @@ mod tests { fn parse_base_mixed() { 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]) } @@ -121,7 +166,7 @@ mod tests { "3".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]) } @@ -129,8 +174,19 @@ mod tests { #[test] fn parse_no_braces_one_arg() { 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]) } + + #[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) + } }