diff --git a/src/payload/json.rs b/src/payload/json.rs index 225df96..89988c8 100644 --- a/src/payload/json.rs +++ b/src/payload/json.rs @@ -1,12 +1,10 @@ use std::fmt::{Display, Formatter}; -use crate::config::{PayloadJson, PayloadOptionRawFormat}; -use base64::engine::general_purpose; -use base64::Engine; use derive_getters::Getters; use serde_json::{from_slice, Value}; -use crate::payload::{PayloadFormat, PayloadFormatError}; +use crate::config::PayloadJson; +use crate::payload::{convert_raw_type, PayloadFormat, PayloadFormatError}; /// This payload format contains a JSON payload. Its value is encoded as /// `serde_json::Value`. @@ -27,14 +25,6 @@ impl PayloadFormatJson { fn encode_to_json(value: Vec) -> serde_json::Result { from_slice(value.as_slice()) } - - fn convert_raw_type(options: &PayloadJson, value: Vec) -> String { - match options.raw_as_type() { - PayloadOptionRawFormat::Hex => hex::encode(value), - PayloadOptionRawFormat::Base64 => general_purpose::STANDARD.encode(value), - PayloadOptionRawFormat::Utf8 => String::from_utf8_lossy(value.as_slice()).to_string(), - } - } } /// Displays the hex encoded content. @@ -189,7 +179,7 @@ impl TryFrom<(PayloadFormat, &PayloadJson)> for PayloadFormatJson { match value { PayloadFormat::Text(value) => encode_to_json_with_string_content(value.into()), PayloadFormat::Raw(value) => encode_to_json_with_string_content( - PayloadFormatJson::convert_raw_type(options, value.into()), + convert_raw_type(options.raw_as_type(), value.into()), ), PayloadFormat::Protobuf(value) => Ok(Self { content: protobuf::get_message_value( @@ -209,13 +199,12 @@ impl TryFrom<(PayloadFormat, &PayloadJson)> for PayloadFormatJson { } mod protobuf { - use crate::config::PayloadJson; use protofish::context::Context; use protofish::decode::{FieldValue, MessageValue, Value}; use serde_json::json; - use crate::payload::json::PayloadFormatJson; - use crate::payload::PayloadFormatError; + use crate::config::PayloadJson; + use crate::payload::{convert_raw_type, PayloadFormatError}; pub(super) fn get_message_value( context: &Context, @@ -288,7 +277,7 @@ mod protobuf { } Value::Message(value) => get_message_value(context, value, options)?, Value::Bytes(value) => { - json!(PayloadFormatJson::convert_raw_type(options, value.to_vec())) + json!(convert_raw_type(options.raw_as_type(), value.to_vec())) } Value::Enum(value) => { let enum_ref = value.enum_ref; @@ -315,6 +304,7 @@ mod protobuf { #[cfg(test)] mod tests { use serde_json::from_str; + use crate::config::PayloadOptionRawFormat; use crate::payload::base64::PayloadFormatBase64; use crate::payload::hex::PayloadFormatHex; @@ -428,6 +418,16 @@ mod tests { assert_eq!(get_json_value(INPUT_STRING_BASE64), result.content); } + #[test] + fn from_raw_as_utf8() { + let input = PayloadFormatRaw::try_from(Vec::from(INPUT_STRING)).unwrap(); + let options = PayloadJson::new(PayloadOptionRawFormat::Utf8); + let result = PayloadFormatJson::try_from((PayloadFormat::Raw(input), &options)).unwrap(); + + assert_eq!(get_json_value(INPUT_STRING), result.content); + } + + #[test] fn from_hex() { let input = PayloadFormatHex::try_from(INPUT_STRING_HEX.to_owned()).unwrap(); @@ -472,7 +472,7 @@ mod tests { "size: 54.3\nname: \"{}\"", INPUT_STRING ))) - .unwrap(); + .unwrap(); let result = PayloadFormatJson::try_from(PayloadFormat::Yaml(input)).unwrap(); assert_eq!(54.3, result.content.get("size").unwrap().as_f64().unwrap()); diff --git a/src/payload/mod.rs b/src/payload/mod.rs index 340bdaf..92f26c8 100644 --- a/src/payload/mod.rs +++ b/src/payload/mod.rs @@ -4,13 +4,14 @@ use std::io::Read; use std::path::PathBuf; use std::string::FromUtf8Error; -use ::base64::DecodeError; +use ::base64::{DecodeError, Engine}; +use ::base64::engine::general_purpose; use ::hex::FromHexError; use log::error; use protofish::context::ParseError; use thiserror::Error; -use crate::config::{PayloadType, PublishInputType, PublishInputTypeContentPath}; +use crate::config::{PayloadOptionRawFormat, PayloadType, PublishInputType, PublishInputTypeContentPath}; use crate::payload::base64::PayloadFormatBase64; use crate::payload::hex::PayloadFormatHex; use crate::payload::json::PayloadFormatJson; @@ -306,3 +307,11 @@ fn read_from_path(path: &PathBuf) -> Result, PayloadFormatError> { }; Ok(buf) } + +fn convert_raw_type(option: &PayloadOptionRawFormat, value: Vec) -> String { + match option { + PayloadOptionRawFormat::Hex => ::hex::encode(value), + PayloadOptionRawFormat::Base64 => general_purpose::STANDARD.encode(value), + PayloadOptionRawFormat::Utf8 => String::from_utf8_lossy(value.as_slice()).to_string(), + } +} diff --git a/src/payload/text.rs b/src/payload/text.rs index c7576da..224c058 100644 --- a/src/payload/text.rs +++ b/src/payload/text.rs @@ -1,11 +1,8 @@ use std::fmt::{Display, Formatter}; use std::string::FromUtf8Error; -use base64::engine::general_purpose; -use base64::Engine; - -use crate::config::{PayloadOptionRawFormat, PayloadText}; -use crate::payload::{PayloadFormat, PayloadFormatError}; +use crate::config::PayloadText; +use crate::payload::{convert_raw_type, PayloadFormat, PayloadFormatError}; #[derive(Clone, Debug)] pub struct PayloadFormatText { @@ -20,14 +17,6 @@ impl PayloadFormatText { fn encode_to_utf8(value: Vec) -> Result { String::from_utf8(value) } - - fn convert_raw_type(options: &PayloadText, value: Vec) -> String { - match options.raw_as_type() { - PayloadOptionRawFormat::Hex => hex::encode(value), - PayloadOptionRawFormat::Base64 => general_purpose::STANDARD.encode(value), - PayloadOptionRawFormat::Utf8 => String::from_utf8_lossy(value.as_slice()).to_string(), - } - } } /// Displays the UTF-8 encoded content. @@ -93,6 +82,14 @@ impl TryFrom for PayloadFormatText { } } +impl TryFrom<(PayloadFormat, PayloadText)> for PayloadFormatText { + type Error = PayloadFormatError; + + fn try_from((value, options): (PayloadFormat, PayloadText)) -> Result { + Self::try_from((value, &options)) + } +} + impl TryFrom<(PayloadFormat, &PayloadText)> for PayloadFormatText { type Error = PayloadFormatError; @@ -100,7 +97,7 @@ impl TryFrom<(PayloadFormat, &PayloadText)> for PayloadFormatText { match value { PayloadFormat::Text(value) => Ok(value), PayloadFormat::Raw(value) => Ok(Self { - content: Self::convert_raw_type(options, value.into()), + content: convert_raw_type(options.raw_as_type(), value.into()), }), PayloadFormat::Protobuf(value) => Ok(Self { content: protobuf::get_message_value( @@ -114,13 +111,13 @@ impl TryFrom<(PayloadFormat, &PayloadText)> for PayloadFormatText { PayloadFormat::Hex(value) => { let a: Vec = value.try_into()?; Ok(Self { - content: Self::convert_raw_type(options, a), + content: convert_raw_type(options.raw_as_type(), a), }) } PayloadFormat::Base64(value) => { let a: Vec = value.try_into()?; Ok(Self { - content: Self::convert_raw_type(options, a), + content: convert_raw_type(options.raw_as_type(), a), }) } PayloadFormat::Json(value) => { @@ -158,12 +155,11 @@ impl TryFrom<(PayloadFormat, &PayloadText)> for PayloadFormatText { } mod protobuf { - use crate::config::PayloadText; use protofish::context::{Context, EnumField, MessageInfo}; use protofish::decode::{FieldValue, MessageValue, Value}; - use crate::payload::text::PayloadFormatText; - use crate::payload::PayloadFormatError; + use crate::config::PayloadText; + use crate::payload::{convert_raw_type, PayloadFormatError}; pub(super) fn get_message_value( context: &Context, @@ -304,7 +300,7 @@ mod protobuf { format!( "{indent_spaces}[{}] {type_name} = {:?} (Bytes)\n", field.number, - PayloadFormatText::convert_raw_type(options, value.to_vec()) + convert_raw_type(options.raw_as_type(), value.to_vec()) ) } Value::Message(value) => get_message_value( @@ -355,6 +351,7 @@ mod protobuf { #[cfg(test)] mod tests { + use crate::config::PayloadOptionRawFormat; use crate::payload::base64::PayloadFormatBase64; use crate::payload::hex::PayloadFormatHex; use crate::payload::json::PayloadFormatJson; @@ -480,18 +477,59 @@ mod tests { } #[test] - fn from_hex() { + fn from_raw_as_utf8() { + let input = PayloadFormatRaw::try_from(Vec::from(INPUT_STRING)).unwrap(); + let options = PayloadText::new(PayloadOptionRawFormat::Utf8); + let result = PayloadFormatText::try_from((PayloadFormat::Raw(input), &options)).unwrap(); + + assert_eq!(INPUT_STRING.to_string(), result.content); + } + + #[test] + fn from_hex_as_hex() { let input = PayloadFormatHex::try_from(INPUT_STRING_HEX.to_owned()).unwrap(); let result = PayloadFormatText::try_from(PayloadFormat::Hex(input)).unwrap(); - assert_eq!(INPUT_STRING.to_owned(), result.content); + assert_eq!(INPUT_STRING_HEX.to_owned(), result.content); } #[test] - fn from_base64() { + fn from_base64_as_hex() { let input = PayloadFormatBase64::try_from(INPUT_STRING_BASE64.to_owned()).unwrap(); let result = PayloadFormatText::try_from(PayloadFormat::Base64(input)).unwrap(); + assert_eq!(INPUT_STRING_HEX.to_owned(), result.content); + } + + #[test] + fn from_hex_as_base64() { + let input = PayloadFormatHex::try_from(INPUT_STRING_HEX.to_owned()).unwrap(); + let result = PayloadFormatText::try_from((PayloadFormat::Hex(input), PayloadText::new(PayloadOptionRawFormat::Base64))).unwrap(); + + assert_eq!(INPUT_STRING_BASE64.to_owned(), result.content); + } + + #[test] + fn from_base64_as_base64() { + let input = PayloadFormatBase64::try_from(INPUT_STRING_BASE64.to_owned()).unwrap(); + let result = PayloadFormatText::try_from((PayloadFormat::Base64(input), PayloadText::new(PayloadOptionRawFormat::Base64))).unwrap(); + + assert_eq!(INPUT_STRING_BASE64.to_owned(), result.content); + } + + #[test] + fn from_hex_as_text() { + let input = PayloadFormatHex::try_from(INPUT_STRING_HEX.to_owned()).unwrap(); + let result = PayloadFormatText::try_from((PayloadFormat::Hex(input), PayloadText::new(PayloadOptionRawFormat::Utf8))).unwrap(); + + assert_eq!(INPUT_STRING.to_owned(), result.content); + } + + #[test] + fn from_base64_as_text() { + let input = PayloadFormatBase64::try_from(INPUT_STRING_BASE64.to_owned()).unwrap(); + let result = PayloadFormatText::try_from((PayloadFormat::Base64(input), PayloadText::new(PayloadOptionRawFormat::Utf8))).unwrap(); + assert_eq!(INPUT_STRING.to_owned(), result.content); } @@ -501,7 +539,7 @@ mod tests { "{{\"content\": \"{}\"}}", INPUT_STRING ))) - .unwrap(); + .unwrap(); let result = PayloadFormatText::try_from(PayloadFormat::Json(input)).unwrap(); assert_eq!(INPUT_STRING.to_owned(), result.content); diff --git a/src/payload/yaml.rs b/src/payload/yaml.rs index 726dc32..eb95038 100644 --- a/src/payload/yaml.rs +++ b/src/payload/yaml.rs @@ -1,13 +1,11 @@ use std::fmt::{Display, Formatter}; -use crate::config::{PayloadOptionRawFormat, PayloadYaml}; -use base64::engine::general_purpose; -use base64::Engine; use derive_getters::Getters; use log::error; use serde_yaml::{from_slice, from_str, Value}; -use crate::payload::{PayloadFormat, PayloadFormatError}; +use crate::config::PayloadYaml; +use crate::payload::{convert_raw_type, PayloadFormat, PayloadFormatError}; #[derive(Clone, Debug, Getters)] pub struct PayloadFormatYaml { @@ -22,14 +20,6 @@ impl PayloadFormatYaml { fn encode_to_yaml(value: Vec) -> serde_yaml::Result { from_slice(value.as_slice()) } - - fn convert_raw_type(options: &PayloadYaml, value: Vec) -> String { - match options.raw_as_type() { - PayloadOptionRawFormat::Hex => hex::encode(value), - PayloadOptionRawFormat::Base64 => general_purpose::STANDARD.encode(value), - PayloadOptionRawFormat::Utf8 => String::from_utf8_lossy(value.as_slice()).to_string(), - } - } } /// Displays the hex encoded content. @@ -108,7 +98,7 @@ impl TryFrom<(PayloadFormat, &PayloadYaml)> for PayloadFormatYaml { match value { PayloadFormat::Text(value) => convert_from_value(value.into()), PayloadFormat::Raw(value) => { - convert_from_value(PayloadFormatYaml::convert_raw_type(options, value.into())) + convert_from_value(convert_raw_type(options.raw_as_type(), value.into())) } PayloadFormat::Protobuf(value) => Ok(Self { content: protobuf::get_message_value( @@ -128,13 +118,12 @@ impl TryFrom<(PayloadFormat, &PayloadYaml)> for PayloadFormatYaml { } mod protobuf { - use crate::config::PayloadYaml; use protofish::context::Context; use protofish::decode::{FieldValue, MessageValue, Value}; use serde_yaml::value; - use crate::payload::yaml::PayloadFormatYaml; - use crate::payload::PayloadFormatError; + use crate::config::PayloadYaml; + use crate::payload::{convert_raw_type, PayloadFormatError}; pub(super) fn get_message_value( context: &Context, @@ -181,8 +170,8 @@ mod protobuf { Value::Bool(value) => serde_yaml::Value::Bool(*value), Value::String(value) => serde_yaml::Value::String(value.clone()), Value::Message(value) => get_message_value(context, value, options)?, - Value::Bytes(value) => serde_yaml::Value::String(PayloadFormatYaml::convert_raw_type( - options, + Value::Bytes(value) => serde_yaml::Value::String(convert_raw_type( + options.raw_as_type(), value.to_vec(), )), Value::Enum(value) => { @@ -210,6 +199,7 @@ mod protobuf { #[cfg(test)] mod tests { use serde_yaml::from_str; + use crate::config::PayloadOptionRawFormat; use crate::payload::base64::PayloadFormatBase64; use crate::payload::hex::PayloadFormatHex; @@ -323,6 +313,15 @@ mod tests { assert_eq!(get_yaml_value(INPUT_STRING_BASE64), result.content); } + #[test] + fn from_raw_as_utf8() { + let input = PayloadFormatRaw::try_from(Vec::from(INPUT_STRING)).unwrap(); + let options = PayloadYaml::new(PayloadOptionRawFormat::Utf8); + let result = PayloadFormatYaml::try_from((PayloadFormat::Raw(input), &options)).unwrap(); + + assert_eq!(get_yaml_value(INPUT_STRING), result.content); + } + #[test] fn from_hex() { let input = PayloadFormatHex::try_from(INPUT_STRING_HEX.to_owned()).unwrap(); @@ -354,7 +353,7 @@ mod tests { "{{\"content\":\"{}\"}}", INPUT_STRING ))) - .unwrap(); + .unwrap(); let result = PayloadFormatYaml::try_from(PayloadFormat::Json(input)).unwrap(); assert_eq!( @@ -369,7 +368,7 @@ mod tests { "{{\"size\": 54.3, \"name\":\"{}\"}}", INPUT_STRING ))) - .unwrap(); + .unwrap(); let result = PayloadFormatYaml::try_from(PayloadFormat::Json(input)).unwrap(); assert_eq!(54.3, result.content.get("size").unwrap().as_f64().unwrap());