use std::collections::HashMap;
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use flexbuffers::{self, FlexbufferSerializer, Reader};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
struct User(String);
impl User {
fn to_bytes(&self) -> Vec<u8> {
self.0.clone().into_bytes()
}
fn from_bytes(bytes: &[u8]) -> Self {
User(String::from_utf8_lossy(bytes).into_owned())
}
}
impl Serialize for User {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
println!("Serializing as human readable string");
serializer.serialize_str(&hex::encode(self.to_bytes()))
} else {
println!("Serializing as raw bytes");
serializer.serialize_bytes(&self.to_bytes())
}
}
}
impl<'de> Deserialize<'de> for User {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
if deserializer.is_human_readable() && false {
println!("Deserializing as human readable string");
let hex_string = String::deserialize(deserializer)?;
let bytes = hex::decode(&hex_string).map_err(serde::de::Error::custom)?;
Ok(User::from_bytes(&bytes))
} else {
println!("Deserializing as raw bytes");
let bytes = <Vec<u8>>::deserialize(deserializer)?;
Ok(User::from_bytes(&bytes))
}
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct TestStruct {
map: HashMap<User, u32>,
}
fn main() {
// Prepare test data.
let mut map = HashMap::new();
map.insert(User("john".to_string()), 100);
let test_struct = TestStruct { map };
// Serialize using flexbuffers.
let mut serializer = FlexbufferSerializer::new();
test_struct.serialize(&mut serializer).unwrap();
let serialized_data = serializer.take_buffer();
// Deserialize back.
let reader = Reader::get_root(serialized_data.as_slice()).unwrap();
let deserialized_struct = TestStruct::deserialize(reader).expect("Deserialization should not fail");
}
Output
Serializing as human readable string
Deserializing as raw bytes
thread 'main' panicked at src/main.rs:64:61:
Deserialization should not fail: Serde("invalid type: string \"6a6f686e\", expected a sequence")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Reproducible example
Output