diff --git a/CHANGELOG b/CHANGELOG index 7e43c82..3b7a440 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +### v9.1.2 +- Add `ser_bytes_stringify` and `de_bytes_destringify`. + ### v9.1.1 - Integrate `serde_bytes`. diff --git a/Cargo.lock b/Cargo.lock index 8d8ee0b..20721a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "array-bytes" -version = "9.1.1" +version = "9.1.2" dependencies = [ "const-hex", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 4b4596c..debf6b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ license = "Apache-2.0/GPL-3.0" name = "array-bytes" readme = "README.md" repository = "https://github.com/hack-ink/array-bytes" -version = "9.1.1" +version = "9.1.2" [profile.ci-dev] incremental = false diff --git a/src/serde.rs b/src/serde.rs index 960955e..7ca6f85 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -1,11 +1,38 @@ +// core +use core::str; // alloc use alloc::format; // crates.io #[cfg(test)] use serde::Serialize; -use serde::{de::Error as DeError, Deserialize, Deserializer, Serializer}; +use serde::{de::Error as _, ser::Error as _, Deserialize, Deserializer, Serializer}; // self use crate::{prelude::*, Dehexify, Hexify}; +/// Serialize bytes to string. +/// +/// # Examples +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Debug, PartialEq, Serialize)] +/// struct Ljf { +/// #[serde(serialize_with = "array_bytes::ser_bytes_stringify")] +/// _0: Vec, +/// } +/// +/// assert_eq!( +/// serde_json::to_string::(&Ljf { _0: b"Love Jane Forever".to_vec() }).unwrap(), +/// r#"{"_0":"Love Jane Forever"}"# +/// ); +/// ``` +pub fn ser_bytes_stringify(value: &T, serializer: S) -> Result +where + S: Serializer, + T: AsRef<[u8]>, +{ + serializer.serialize_str(str::from_utf8(value.as_ref()).map_err(S::Error::custom)?) +} + /// Serialize `T` to hex. /// /// # Examples @@ -130,6 +157,32 @@ where serializer.serialize_str(&value.hexify_prefixed()) } +/// Deserialize string to bytes. +/// +/// # Examples +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Debug, PartialEq, Deserialize)] +/// struct Ljf { +/// #[serde(deserialize_with = "array_bytes::de_bytes_destringify")] +/// _0: Vec, +/// } +/// +/// assert_eq!( +/// serde_json::from_str::(r#"{"_0":"Love Jane Forever"}"#).unwrap(), +/// Ljf { _0: b"Love Jane Forever".to_vec() } +/// ); +/// ``` +pub fn de_bytes_destringify<'de, D>(str: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let str = <&str>::deserialize(str)?; + + Ok(str.as_bytes().to_vec()) +} + /// Deserialize hex to `T`. /// /// # Examples @@ -168,7 +221,7 @@ where { let hex = <&str>::deserialize(hex)?; - T::dehexify(hex).map_err(|_| D::Error::custom(alloc::format!("invalid hex str `{}`", hex))) + T::dehexify(hex).map_err(|e| D::Error::custom(alloc::format!("{e:?}"))) } /// Deserialize hex to `T` where `T: From>`. @@ -323,6 +376,8 @@ fn serde_should_work() { _6: [u8; 17], #[serde(deserialize_with = "de_dehexify", serialize_with = "ser_hexify_prefixed_upper")] _7: Vec, + #[serde(deserialize_with = "de_bytes_destringify", serialize_with = "ser_bytes_stringify")] + _8: Vec, } impl Default for LjfPredefined { fn default() -> Self { @@ -335,6 +390,7 @@ fn serde_should_work() { _5: 5_201_314, _6: *b"Love Jane Forever", _7: b"Love Jane Forever".to_vec(), + _8: b"Love Jane Forever".to_vec(), } } } @@ -346,7 +402,7 @@ fn serde_should_work() { let json = result.unwrap(); assert_eq!( json, - r#"{"_0":"34","_1":"208","_2":"0x4f5da2","_3":"0x4f5da2","_4":"4f5da2","_5":"4F5DA2","_6":"0x4c6f7665204a616e6520466f7265766572","_7":"0x4c6f7665204a616e6520466f7265766572"}"# + r#"{"_0":"34","_1":"208","_2":"0x4f5da2","_3":"0x4f5da2","_4":"4f5da2","_5":"4F5DA2","_6":"0x4c6f7665204a616e6520466f7265766572","_7":"0x4c6f7665204a616e6520466f7265766572","_8":"Love Jane Forever"}"# ); let result = serde_json::from_str::(&json);