dtolnay / erased-serde

Type-erased Serialize, Serializer and Deserializer traits
Apache License 2.0
709 stars 36 forks source link

Expose ser::erase::Serializer #66

Closed stepancheg closed 1 year ago

stepancheg commented 1 year ago

Long story.

Currently we store function pointers in custom vtable.

https://github.com/facebookexperimental/starlark-rust/blob/9645eaf81f35a6f254e3c526ce00d3b16b4df971/starlark/src/values/layout/vtable.rs#L143

We want to remove dependency on ptr_metadata feature to make starlark-rust work in stable.

One possibility is to store functions instead of dyn metadata in vtable. I. e. for Display, store

fn(*const (), &mut Formatter<'_>) -> fmt::Result

instead of

DynMetadata<dyn Display>

(D41063479).

However, similar transformation seems to be impossible for erased_serde::Serialize.

We could store function:

fn(*const (), v: &mut dyn erased_serde::Serializer) -> Result<(), erased_serde::Error>

instead of

DynMetadata<dyn erased_serde::Serialize>

however, it is not possible to call this function. There are two options, neither work:

First, erased_serde::Serialize cannot be implemented directly using stored function because the trait is sealed (Ok type is private).

Second, this function cannot be called directly, because there's no public API to construct erased_serde::Serializer from serde::Serializer.

The latter approach seems to be more appropriate.

Hence feature request: create a public function like:

pub fn into_erased_serializer<S: serde::Serializer>(serializer: S) -> impl erased_serde::Serializer { ... }
dtolnay commented 1 year ago

I am not interested in exposing that.

The canonical stable way to "store a DynMetadata\<dyn Trait>" is fn(*const ()) -> *const dyn Trait.

stepancheg commented 1 year ago

Thanks! I didn't know of this way to solve it.