google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.35k stars 3.25k forks source link

[Rust] Map key encode as human-readable, but decoded as raw #8438

Open koxu1996 opened 1 week ago

koxu1996 commented 1 week ago

Reproducible example

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
koxu1996 commented 1 week ago

Key always must be string, so deserializer should use human readble format too (instead of relying on false that is set globally).