Custom trait objects serialization with Serde?

#1

I’m writing an encoder for PostgreSQL binary protocol (which is used in a COPY WITH BINARY command for example). Among a few types that can be mapped to the Serde types (ex. smallint is the same as i16 and so on), PostgreSQL has some types that can be mapped only to external crate structs, let’s say, timestamp with time zone can be mapped to chrono::DateTime<Tz>.

While chrono provides an implementation for serde::Serialize for DateTime<Tz> type, it can’t be used in my format, because instead of writing a string I’m required to write the microseconds amount starting from the 2000-00-00T00:00:00+00:00; therefore default serde::Serialize implementation is not suitable for me.
Another example is a MAC address, which in Rust can be a [u8; 6], eui48::MacAddress or smth else.

The first option that I saw is to provide a bunch of functions for #[serde(with)] attribute and force end user to use them where needed, but I’ll get access only to S: Serializer trait object, not to my Serializer type or an inner Encoder and will not be able to write bytes directly (Serializer::serialize_* methods will not help here).

The second option is to use Serde “remote derive” feature and serialize object directly to bytes array, but it will require for user to add #[serde(with)] attribute whenever it is needed and will lead to a huge code amount to support. Also, it might just not work, I had not investigated this feature closely :slight_smile:

Right now I have a bunch of traits which are utilized by the low-level encoder, but I don’t think I’ll be able to re-use them in any way with Serializer.

So, is there anything that I’m missing or serde just not suitable right now for my requirements?

#2

Maybe you want this?

#3

Yeah, @dtolnay already recommended this crate, but it supports only tagged enum representations, which are not useful in my case, basically each field is just a i32 of data length immediately followed by this data, there is no place to stick “tag”.