0

I'm writing a Deserializer for a format that already exists, but the format has one peculiarity which I don't know how to implement in serde:

// pseudo code
fn example(){
   // when decoding an u8 directly, the value 0x00 is invalid
   assert!(<u8>::deserialize(Format::from_bytes(&[0x00u8])).is_err());

   // however, when decoding an u8 through a Vec<u8> 0x00 is valid
   //
   // The problem is that this will first call `deserialize_seq`, which
   // will then use the same function as `<u8>::deserialize`, but I need
   // it to call a different method which actually accepts the value 0x00
   assert_eq!(<Vec<u8>>::deserialize(Format::from_bytes(&[0x00u8])), vec![0x00]);
}

The problem is that the original implementation is not generic, and it has an implementation for u8 which rejects the value 0x00, and a Vec<u8> which accepts it.

It looks like I need some kind of runtime type information to replicate this within a serde deserializer, any way of implementing this?

Augusto Hack
  • 2,032
  • 18
  • 35

1 Answers1

0

Thanks @kmdreko for the pointer, that was very helpful.

So the problem I had was that the default behavior of serde::de::Deserialize for Vec<T> created a visitor parametrized on T, forcing the items of a Vec<u8> to use the same deserialization function as u8. Because serde provides a default implementation for Vec<T>, and rust doesn't support overloading, and specialization hasn't landed, I couldn't simply do impl<'de> Deserialize<'de> for Vec<u8>. The work around was to introduce a unit struct, which I named DirectBytes, and code a impl<'de> Deserialize<'de> for DirectBytes which uses deserialize_byte_buf instead of deserialize_seq.

serde_bytes is a bit more complicated, it not only has these "proxy" structs, but it also has its own trait named Deserialize, which I suppose is necessary for the macro #[serde(with="..")] to work properly. I also don't know how to implement this behavior if deserialize_byte_buf didn't happen to do what I needed, but for my problem at hand the wrapping type seems good enough.

Augusto Hack
  • 2,032
  • 18
  • 35