diff --git a/Cargo.lock b/Cargo.lock index a5ade72..868f82f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -381,10 +381,13 @@ checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" [[package]] name = "erased-serde" -version = "0.4.1" -source = "git+https://github.com/gurafi/erased-serde?rev=29c475a1e1e425d1a850579d4a34eab0a27ea3b5#29c475a1e1e425d1a850579d4a34eab0a27ea3b5" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e59b668157f32d3459d4bd634861a06ffa2503a461ca5f0916b9f0252605e66" dependencies = [ "serde", + "serde_core", + "typeid", ] [[package]] @@ -522,7 +525,7 @@ version = "0.2.0" dependencies = [ "erased-serde", "serde", - "serde-value", + "serde_json", ] [[package]] @@ -828,15 +831,6 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -1049,15 +1043,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.7.0" -source = "git+https://github.com/gurafi/serde-value?rev=a3c7d1e70bd3feb5c2eb62527748524dcbb358ec#a3c7d1e70bd3feb5c2eb62527748524dcbb358ec" -dependencies = [ - "ordered-float", - "serde", -] - [[package]] name = "serde_core" version = "1.0.229" @@ -1139,7 +1124,6 @@ name = "shiri" version = "0.0.0" dependencies = [ "serde", - "serde-value", "serde_json", ] @@ -1504,6 +1488,12 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.20.1" diff --git a/crates/gql/Cargo.toml b/crates/gql/Cargo.toml index 0a12a04..31abd8d 100644 --- a/crates/gql/Cargo.toml +++ b/crates/gql/Cargo.toml @@ -21,11 +21,9 @@ rustdoc-args = ["--cfg", "docsrs"] serde = { version = "1.0.193", default-features = false } # Private dependencies - MUST NEVER be in public API!!!! -# TODO: Migrate back to the releases once the required changes land upstream. -# https://github.com/dtolnay/erased-serde/pull/102 -erased-serde = { git = "https://github.com/gurafi/erased-serde", rev = "29c475a1e1e425d1a850579d4a34eab0a27ea3b5" } -# TODO: I hate that this is required. -# It's due to the Serde's low-level API not being able to express 2D types. -serde-value = { git = "https://github.com/gurafi/serde-value", rev = "a3c7d1e70bd3feb5c2eb62527748524dcbb358ec" } +erased-serde = "0.4.11" # graphql-parser = "0.4.0" + +[dev-dependencies] +serde_json.workspace = true diff --git a/crates/gql/src/serializer/adapter.rs b/crates/gql/src/serializer/adapter.rs new file mode 100644 index 0000000..4b7c0f7 --- /dev/null +++ b/crates/gql/src/serializer/adapter.rs @@ -0,0 +1,169 @@ +//! An adapter from a `serde` serializer to the object-safe traits in this module. + +use serde::ser::{SerializeMap as _, SerializeSeq as _}; + +use super::traits::{ErasedValue, MapImpl, SeqImpl, SerializerImpl}; + +/// Owns a `serde` serializer and drives it through the object-safe traits. +/// +/// The state machine exists because `serde`'s serializers are consumed when a map or sequence is +/// started. The serializer is moved into the map/sequence, which is moved back here. +pub(crate) struct SerdeAdapter { + serializer: Option, + map: Option, + seq: Option, +} + +impl SerdeAdapter { + pub(crate) fn new(serializer: S) -> Self { + Self { + serializer: Some(serializer), + map: None, + seq: None, + } + } + + fn take_serializer(&mut self) -> S { + self.serializer + .take() + .expect("SerdeAdapter: serializer already consumed") + } +} + +macro_rules! impl_scalar { + ($($method:ident($ty:ty)),* $(,)?) => { + $( + fn $method(&mut self, value: $ty) { + self.take_serializer().$method(value).unwrap(); + } + )* + }; +} + +impl SerializerImpl for SerdeAdapter { + impl_scalar!( + serialize_bool(bool), + serialize_i8(i8), + serialize_i16(i16), + serialize_i32(i32), + serialize_i64(i64), + serialize_u8(u8), + serialize_u16(u16), + serialize_u32(u32), + serialize_u64(u64), + serialize_f32(f32), + serialize_f64(f64), + serialize_i128(i128), + serialize_u128(u128), + serialize_char(char), + serialize_str(&str), + serialize_bytes(&[u8]), + ); + + fn serialize_none(&mut self) { + self.take_serializer().serialize_none().unwrap(); + } + + fn serialize_some(&mut self, value: &dyn erased_serde::Serialize) { + self.take_serializer() + .serialize_some(&ErasedValue(value)) + .unwrap(); + } + + fn serialize_unit(&mut self) { + self.take_serializer().serialize_unit().unwrap(); + } + + fn serialize_unit_struct(&mut self, name: &'static str) { + self.take_serializer().serialize_unit_struct(name).unwrap(); + } + + fn serialize_unit_variant( + &mut self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) { + self.take_serializer() + .serialize_unit_variant(name, variant_index, variant) + .unwrap(); + } + + fn serialize_newtype_struct( + &mut self, + name: &'static str, + value: &dyn erased_serde::Serialize, + ) { + self.take_serializer() + .serialize_newtype_struct(name, &ErasedValue(value)) + .unwrap(); + } + + fn serialize_newtype_variant( + &mut self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &dyn erased_serde::Serialize, + ) { + self.take_serializer() + .serialize_newtype_variant(name, variant_index, variant, &ErasedValue(value)) + .unwrap(); + } + + fn serialize_seq(&mut self, len: Option) -> Result<&mut dyn SeqImpl, ()> { + let serializer = self.take_serializer(); + self.seq = Some(serializer.serialize_seq(len).map_err(|_| ())?); + Ok(self) + } + + fn serialize_map(&mut self, len: Option) -> Result<&mut dyn MapImpl, ()> { + let serializer = self.take_serializer(); + self.map = Some(serializer.serialize_map(len).map_err(|_| ())?); + Ok(self) + } + + fn serialize_serde(&mut self, value: &dyn erased_serde::Serialize) { + SerializerImpl::serialize_some(self, value); + } +} + +impl MapImpl for SerdeAdapter { + fn serialize_key(&mut self, key: &dyn erased_serde::Serialize) -> Result<(), ()> { + self.map + .as_mut() + .ok_or(())? + .serialize_key(&ErasedValue(key)) + .map_err(|_| ()) + } + + fn serialize_value(&mut self, value: &dyn erased_serde::Serialize) -> Result<(), ()> { + self.map + .as_mut() + .ok_or(())? + .serialize_value(&ErasedValue(value)) + .map_err(|_| ()) + } + + fn end(&mut self) { + if let Some(map) = self.map.take() { + let _ = map.end(); + } + } +} + +impl SeqImpl for SerdeAdapter { + fn serialize_element(&mut self, value: &dyn erased_serde::Serialize) -> Result<(), ()> { + self.seq + .as_mut() + .ok_or(())? + .serialize_element(&ErasedValue(value)) + .map_err(|_| ()) + } + + fn end(&mut self) { + if let Some(seq) = self.seq.take() { + let _ = seq.end(); + } + } +} diff --git a/crates/gql/src/serializer/mod.rs b/crates/gql/src/serializer/mod.rs index dd3c3b5..492be55 100644 --- a/crates/gql/src/serializer/mod.rs +++ b/crates/gql/src/serializer/mod.rs @@ -8,6 +8,7 @@ //! - `erased_serde` has not reached 1.0 yet so we don't want it in our public API. //! +mod adapter; mod owned_serializer; mod serialize_map; mod serialize_seq; @@ -17,11 +18,11 @@ mod serialize_tuple; mod serialize_tuple_struct; mod serialize_tuple_variant; mod serializer; - -// This is hidden as an end-user shouldn't ever need it but it's public in-case they need to refer to it. -#[doc(hidden)] -pub use owned_serializer::AnyOwnedSerializer; +mod traits; pub use owned_serializer::OwnedSerializer; pub use serialize_map::SerializeMap; pub use serializer::Serializer; + +pub(crate) use adapter::SerdeAdapter; +pub(crate) use traits::{MapImpl, SeqImpl, SerializerImpl}; diff --git a/crates/gql/src/serializer/owned_serializer.rs b/crates/gql/src/serializer/owned_serializer.rs index 055f78c..c011ccb 100644 --- a/crates/gql/src/serializer/owned_serializer.rs +++ b/crates/gql/src/serializer/owned_serializer.rs @@ -1,50 +1,24 @@ -//! This stuff exists because converting `serde` to `erased_serde` requires ownership of the `Serializer`. -//! -//! TODO: Try and fix upstream +//! This stuff exists because converting `serde` to the object-safe traits in this module requires +//! ownership of the `Serializer`. use std::fmt; -use super::{serializer::SerializeImpl, Serializer}; +use super::{SerdeAdapter, Serializer, serializer::SerializeImpl}; -pub trait AnyOwnedSerializer: sealed::Sealed {} +pub struct OwnedSerializer(SerdeAdapter); -mod sealed { - // This prevents downstream user's from implementing the trait due to the private supertrait. - pub trait Sealed { - // This method is hidden from the public API as it has `erased_serde` in it. - fn get(&mut self) -> &mut dyn erased_serde::Serializer; - } - - impl Sealed for T { - fn get(&mut self) -> &mut dyn erased_serde::Serializer { - self - } - } - - impl super::AnyOwnedSerializer for T {} -} - -/// TODO: Replace this with `Serialize::new`. Will likely need upstream work in `erased_serde` or to fork it. -pub struct OwnedSerializer(S); - -impl fmt::Debug for OwnedSerializer { +impl fmt::Debug for OwnedSerializer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OwnedSerializer").finish() } } -impl OwnedSerializer { - pub fn new(serializer: S) -> OwnedSerializer - where - S: serde::Serializer, - { - OwnedSerializer(::erase(serializer)) +impl OwnedSerializer { + pub fn new(serializer: S) -> Self { + OwnedSerializer(SerdeAdapter::new(serializer)) } - pub fn serialize(&mut self) -> Serializer<'_> - where - S: AnyOwnedSerializer, - { - Serializer(SerializeImpl::Regular(self.0.get())) + pub fn serialize(&mut self) -> Serializer<'_> { + Serializer(SerializeImpl::Regular(&mut self.0)) } } diff --git a/crates/gql/src/serializer/serialize_map.rs b/crates/gql/src/serializer/serialize_map.rs index 936e7b3..ab07b01 100644 --- a/crates/gql/src/serializer/serialize_map.rs +++ b/crates/gql/src/serializer/serialize_map.rs @@ -1,19 +1,8 @@ use std::fmt; -use super::{serializer::SerializeImpl, Serializer}; +use super::{MapImpl, Serializer, serializer::SerializeImpl}; -pub struct SerializeMap<'a>(pub(crate) SerializeMapImpl<'a>); - -pub enum SerializeMapImpl<'a> { - Map(&'a mut dyn erased_serde::SerializeMap), - // TODO: This variant is inherently inefficient because we collect up in memory, then serialize instead of doing both at once. - // However Serde doesn't provide a better way to do this. - SerdeValue { - value: serde_value::Serializer, - // `value` will be written to `parent` when done - parent: &'a mut dyn erased_serde::SerializeMap, - }, -} +pub struct SerializeMap<'a>(pub(crate) &'a mut dyn MapImpl); impl<'a> fmt::Debug for SerializeMap<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -24,30 +13,11 @@ impl<'a> fmt::Debug for SerializeMap<'a> { // TODO: Error type impl<'a> SerializeMap<'a> { pub fn serialize_key(&mut self, key: &T) -> Result<(), ()> { - match &mut self.0 { - SerializeMapImpl::Map(serializer) => { - serializer.erased_serialize_key(key).map_err(|_| ()) - } - SerializeMapImpl::SerdeValue { value, parent } => { - // value.serialize(key).map_err(|_| ())?; - // parent.erased_serialize_value(&value).map_err(|_| ()) - todo!(); - } - } + self.0.serialize_key(key) } pub fn serialize_value(&mut self, value: &T) -> Result<(), ()> { - // self.0.erased_serialize_value(value).map_err(|_| ()) - match &mut self.0 { - SerializeMapImpl::Map(serializer) => { - serializer.erased_serialize_value(value).map_err(|_| ()) - } - SerializeMapImpl::SerdeValue { value, parent } => { - // value.serialize(value).map_err(|_| ())?; - // parent.erased_serialize_value(&value).map_err(|_| ()) - todo!(); - } - } + self.0.serialize_value(value) } pub fn serialize_entry( @@ -65,31 +35,12 @@ impl<'a> SerializeMap<'a> { pub fn serialize_entry_serializer( &mut self, key: &K, - ) -> Result { - match &mut self.0 { - SerializeMapImpl::Map(serializer) => { - serializer.erased_serialize_key(key).map_err(|_| ())?; - Ok(Serializer(SerializeImpl::MapValue(&mut **serializer))) - } - SerializeMapImpl::SerdeValue { value, parent } => { - // Ok(Serializer(SerializeImpl::M { - // value: serde_value::Serializer, - // parent: &mut **serializer, - // })) - todo!(); - - // serializer.erased_serialize_key(key).map_err(|_| ())?; - // Ok(Serializer(SerializeImpl::MapValue(&mut **serializer))) - } - } + ) -> Result, ()> { + self.0.serialize_key(key)?; + Ok(Serializer(SerializeImpl::MapValue(&mut *self.0))) } pub fn end(self) { - match self.0 { - SerializeMapImpl::Map(serializer) => serializer.erased_end(), - SerializeMapImpl::SerdeValue { value, parent } => { - todo!(); - } - } + self.0.end(); } } diff --git a/crates/gql/src/serializer/serialize_seq.rs b/crates/gql/src/serializer/serialize_seq.rs index 3078999..fd036a6 100644 --- a/crates/gql/src/serializer/serialize_seq.rs +++ b/crates/gql/src/serializer/serialize_seq.rs @@ -1,6 +1,8 @@ use std::fmt; -pub struct SerializeSeq<'a>(pub(crate) &'a mut dyn erased_serde::SerializeSeq); +use super::SeqImpl; + +pub struct SerializeSeq<'a>(pub(crate) &'a mut dyn SeqImpl); impl<'a> fmt::Debug for SerializeSeq<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -11,10 +13,10 @@ impl<'a> fmt::Debug for SerializeSeq<'a> { // TODO: Error type impl<'a> SerializeSeq<'a> { pub fn serialize_element(&mut self, element: &T) -> Result<(), ()> { - self.0.erased_serialize_element(element).map_err(|_| ()) + self.0.serialize_element(element) } pub fn end(self) { - self.0.erased_end(); + self.0.end(); } } diff --git a/crates/gql/src/serializer/serializer.rs b/crates/gql/src/serializer/serializer.rs index 1d9c06c..76b7751 100644 --- a/crates/gql/src/serializer/serializer.rs +++ b/crates/gql/src/serializer/serializer.rs @@ -1,15 +1,15 @@ use std::fmt; -use super::{serialize_map::SerializeMapImpl, serialize_seq::SerializeSeq, SerializeMap}; +use super::{MapImpl, SerializerImpl, serialize_map::SerializeMap, serialize_seq::SerializeSeq}; /// TODO // A wrapper around the object-safe [`Serializer`](super::Serializer) trait. pub struct Serializer<'a>(pub(crate) SerializeImpl<'a>); pub(crate) enum SerializeImpl<'a> { - Regular(&'a mut dyn erased_serde::Serializer), + Regular(&'a mut dyn SerializerImpl), // In this state we assume `.serialize_key` was called first. - MapValue(&'a mut dyn erased_serde::SerializeMap), + MapValue(&'a mut dyn MapImpl), } impl<'a> fmt::Debug for Serializer<'a> { @@ -20,7 +20,6 @@ impl<'a> fmt::Debug for Serializer<'a> { impl<'a> Serializer<'a> { pub fn new(serializer: S) -> Self { - // TODO: Can we modify `erased-serde` to support this and drop `super::owned_serializer` completely? todo!(); } } @@ -29,103 +28,98 @@ macro_rules! dispatch { ($self:ident; $value: ident; $method:ident) => { match $self.0 { SerializeImpl::Regular(serializer) => serializer.$method($value), - SerializeImpl::MapValue(serializer) => { - // TODO: Error handling - serializer.erased_serialize_value(&$value).unwrap() - } + SerializeImpl::MapValue(serializer) => serializer.$method($value), } }; } impl<'a> Serializer<'a> { pub fn serialize_bool(self, value: bool) { - dispatch!(self; value; erased_serialize_bool); + dispatch!(self; value; serialize_bool); } pub fn serialize_i8(self, value: i8) { - dispatch!(self; value; erased_serialize_i8); + dispatch!(self; value; serialize_i8); } pub fn serialize_i16(self, value: i16) { - dispatch!(self; value; erased_serialize_i16); + dispatch!(self; value; serialize_i16); } pub fn serialize_i32(self, value: i32) { - dispatch!(self; value; erased_serialize_i32); + dispatch!(self; value; serialize_i32); } pub fn serialize_i64(self, value: i64) { - dispatch!(self; value; erased_serialize_i64); + dispatch!(self; value; serialize_i64); } pub fn serialize_u8(self, value: u8) { - dispatch!(self; value; erased_serialize_u8); + dispatch!(self; value; serialize_u8); } pub fn serialize_u16(self, value: u16) { - dispatch!(self; value; erased_serialize_u16); + dispatch!(self; value; serialize_u16); } pub fn serialize_u32(self, value: u32) { - dispatch!(self; value; erased_serialize_u32); + dispatch!(self; value; serialize_u32); } pub fn serialize_u64(self, value: u64) { - dispatch!(self; value; erased_serialize_u64); + dispatch!(self; value; serialize_u64); } pub fn serialize_f32(self, value: f32) { - dispatch!(self; value; erased_serialize_f32); + dispatch!(self; value; serialize_f32); } pub fn serialize_f64(self, value: f64) { - dispatch!(self; value; erased_serialize_f64); + dispatch!(self; value; serialize_f64); } pub fn serialize_i128(self, value: i128) { - dispatch!(self; value; erased_serialize_i128); + dispatch!(self; value; serialize_i128); } pub fn serialize_u128(self, value: u128) { - dispatch!(self; value; erased_serialize_u128); + dispatch!(self; value; serialize_u128); } pub fn serialize_char(self, value: char) { - dispatch!(self; value; erased_serialize_char); + dispatch!(self; value; serialize_char); } pub fn serialize_str(self, value: &str) { - dispatch!(self; value; erased_serialize_str); + dispatch!(self; value; serialize_str); } pub fn serialize_bytes(self, value: &[u8]) { - dispatch!(self; value; erased_serialize_bytes); + dispatch!(self; value; serialize_bytes); } pub fn serialize_none(self) { match self.0 { - SerializeImpl::Regular(serializer) => serializer.erased_serialize_none(), - SerializeImpl::MapValue(serializer) => serializer - .erased_serialize_value(&(None as Option<()>)) - .unwrap(), + SerializeImpl::Regular(serializer) => serializer.serialize_none(), + SerializeImpl::MapValue(serializer) => serializer.serialize_none(), } } pub fn serialize_some(self, value: &T) { - dispatch!(self; value; erased_serialize_some); + dispatch!(self; value; serialize_some); } pub fn serialize_unit(self) { match self.0 { - SerializeImpl::Regular(serializer) => serializer.erased_serialize_unit(), - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::Regular(serializer) => serializer.serialize_unit(), + SerializeImpl::MapValue(_) => todo!(), } } pub fn serialize_unit_struct(self, name: &'static str) { match self.0 { - SerializeImpl::Regular(serializer) => serializer.erased_serialize_unit_struct(name), - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::Regular(serializer) => serializer.serialize_unit_struct(name), + SerializeImpl::MapValue(_) => todo!(), } } @@ -137,18 +131,16 @@ impl<'a> Serializer<'a> { ) { match self.0 { SerializeImpl::Regular(serializer) => { - serializer.erased_serialize_unit_variant(name, variant_index, variant) + serializer.serialize_unit_variant(name, variant_index, variant) } - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::MapValue(_) => todo!(), } } pub fn serialize_newtype_struct(self, name: &'static str, value: &T) { match self.0 { - SerializeImpl::Regular(serializer) => { - serializer.erased_serialize_newtype_struct(name, value) - } - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::Regular(serializer) => serializer.serialize_newtype_struct(name, value), + SerializeImpl::MapValue(_) => todo!(), } } @@ -161,19 +153,19 @@ impl<'a> Serializer<'a> { ) { match self.0 { SerializeImpl::Regular(serializer) => { - serializer.erased_serialize_newtype_variant(name, variant_index, variant, value) + serializer.serialize_newtype_variant(name, variant_index, variant, value) } - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::MapValue(_) => todo!(), } } pub fn serialize_seq(self, len: Option) -> Result, ()> { match self.0 { SerializeImpl::Regular(serializer) => serializer - .erased_serialize_seq(len) + .serialize_seq(len) .map(SerializeSeq) .map_err(|_| ()), - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::MapValue(_) => todo!(), } } @@ -200,13 +192,10 @@ impl<'a> Serializer<'a> { pub fn serialize_map(self, len: Option) -> Result, ()> { match self.0 { SerializeImpl::Regular(serializer) => serializer - .erased_serialize_map(len) - .map(|v| SerializeMap(SerializeMapImpl::Map(v))) + .serialize_map(len) + .map(SerializeMap) .map_err(|_| ()), - SerializeImpl::MapValue(serializer) => Ok(SerializeMap(SerializeMapImpl::SerdeValue { - value: serde_value::Serializer, - parent: serializer, - })), + SerializeImpl::MapValue(_) => todo!(), } } @@ -226,8 +215,8 @@ impl<'a> Serializer<'a> { pub fn serialize_serde(self, value: &T) { match self.0 { - SerializeImpl::Regular(serializer) => serializer.erased_serialize_some(value), - SerializeImpl::MapValue(serializer) => todo!(), + SerializeImpl::Regular(serializer) => serializer.serialize_serde(value), + SerializeImpl::MapValue(_) => todo!(), } } } diff --git a/crates/gql/src/serializer/traits.rs b/crates/gql/src/serializer/traits.rs new file mode 100644 index 0000000..c954520 --- /dev/null +++ b/crates/gql/src/serializer/traits.rs @@ -0,0 +1,143 @@ +//! Object-safe traits used by [`Serializer`](super::Serializer). +//! +//! These traits wrap the format-specific `serde` serializer types so the rest of the crate can stay +//! format agnostic. + +/// The object-safe equivalent of [`serde::Serializer`]. +pub(crate) trait SerializerImpl { + fn serialize_bool(&mut self, value: bool); + fn serialize_i8(&mut self, value: i8); + fn serialize_i16(&mut self, value: i16); + fn serialize_i32(&mut self, value: i32); + fn serialize_i64(&mut self, value: i64); + fn serialize_u8(&mut self, value: u8); + fn serialize_u16(&mut self, value: u16); + fn serialize_u32(&mut self, value: u32); + fn serialize_u64(&mut self, value: u64); + fn serialize_f32(&mut self, value: f32); + fn serialize_f64(&mut self, value: f64); + fn serialize_i128(&mut self, value: i128); + fn serialize_u128(&mut self, value: u128); + fn serialize_char(&mut self, value: char); + fn serialize_str(&mut self, value: &str); + fn serialize_bytes(&mut self, value: &[u8]); + fn serialize_none(&mut self); + fn serialize_some(&mut self, value: &dyn erased_serde::Serialize); + fn serialize_unit(&mut self); + fn serialize_unit_struct(&mut self, name: &'static str); + fn serialize_unit_variant( + &mut self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ); + fn serialize_newtype_struct(&mut self, name: &'static str, value: &dyn erased_serde::Serialize); + fn serialize_newtype_variant( + &mut self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &dyn erased_serde::Serialize, + ); + fn serialize_seq(&mut self, len: Option) -> Result<&mut dyn SeqImpl, ()>; + fn serialize_map(&mut self, len: Option) -> Result<&mut dyn MapImpl, ()>; + fn serialize_serde(&mut self, value: &dyn erased_serde::Serialize); +} + +/// The object-safe equivalent of [`serde::ser::SerializeMap`]. +pub(crate) trait MapImpl { + fn serialize_key(&mut self, key: &dyn erased_serde::Serialize) -> Result<(), ()>; + fn serialize_value(&mut self, value: &dyn erased_serde::Serialize) -> Result<(), ()>; + fn end(&mut self); + + // The remaining methods write a scalar into the map's current value slot. + // They exist so `SerializeImpl::MapValue` can reuse the `dispatch!` macro. + + fn serialize_bool(&mut self, value: bool) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_i8(&mut self, value: i8) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_i16(&mut self, value: i16) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_i32(&mut self, value: i32) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_i64(&mut self, value: i64) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_u8(&mut self, value: u8) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_u16(&mut self, value: u16) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_u32(&mut self, value: u32) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_u64(&mut self, value: u64) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_f32(&mut self, value: f32) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_f64(&mut self, value: f64) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_i128(&mut self, value: i128) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_u128(&mut self, value: u128) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_char(&mut self, value: char) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_str(&mut self, value: &str) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_bytes(&mut self, value: &[u8]) { + self.serialize_value(&value).unwrap(); + } + + fn serialize_none(&mut self) { + let none: Option<()> = None; + self.serialize_value(&none).unwrap(); + } + + fn serialize_some(&mut self, value: &dyn erased_serde::Serialize) { + self.serialize_value(value).unwrap(); + } +} + +/// The object-safe equivalent of [`serde::ser::SerializeSeq`]. +pub(crate) trait SeqImpl { + fn serialize_element(&mut self, value: &dyn erased_serde::Serialize) -> Result<(), ()>; + fn end(&mut self); +} + +/// Bridges an erased value back into `serde`'s generic API. +pub(crate) struct ErasedValue<'a>(pub(crate) &'a dyn erased_serde::Serialize); + +impl serde::Serialize for ErasedValue<'_> { + fn serialize(&self, serializer: S) -> Result { + erased_serde::serialize(self.0, serializer) + } +} diff --git a/crates/gql/tests/owned_serializer.rs b/crates/gql/tests/owned_serializer.rs new file mode 100644 index 0000000..e658ee2 --- /dev/null +++ b/crates/gql/tests/owned_serializer.rs @@ -0,0 +1,57 @@ +use gql::serializer::OwnedSerializer; + +#[test] +fn serializes_map_through_owned_serializer() { + let mut buf = Vec::new(); + + { + let mut serde = serde_json::Serializer::new(&mut buf); + let mut serializer = OwnedSerializer::new(&mut serde); + + let mut map = serializer.serialize().serialize_map(Some(3)).unwrap(); + map.serialize_entry(&"hello", &"world").unwrap(); + map.serialize_entry(&"answer", &42).unwrap(); + map.serialize_entry(&"list", &vec![1, 2, 3]).unwrap(); + map.end(); + } + + assert_eq!( + std::str::from_utf8(&buf).unwrap(), + r#"{"hello":"world","answer":42,"list":[1,2,3]}"# + ); +} + +#[test] +fn serializes_seq_through_owned_serializer() { + let mut buf = Vec::new(); + + { + let mut serde = serde_json::Serializer::new(&mut buf); + let mut serializer = OwnedSerializer::new(&mut serde); + + let mut seq = serializer.serialize().serialize_seq(Some(3)).unwrap(); + seq.serialize_element(&1).unwrap(); + seq.serialize_element(&"two").unwrap(); + seq.serialize_element(&true).unwrap(); + seq.end(); + } + + assert_eq!(std::str::from_utf8(&buf).unwrap(), r#"[1,"two",true]"#); +} + +#[test] +fn serializes_scalar_into_map_value_slot() { + let mut buf = Vec::new(); + + { + let mut serde = serde_json::Serializer::new(&mut buf); + let mut serializer = OwnedSerializer::new(&mut serde); + + let mut map = serializer.serialize().serialize_map(Some(1)).unwrap(); + let value = map.serialize_entry_serializer(&"hello").unwrap(); + value.serialize_str("world"); + map.end(); + } + + assert_eq!(std::str::from_utf8(&buf).unwrap(), r#"{"hello":"world"}"#); +} diff --git a/crates/shiri/Cargo.toml b/crates/shiri/Cargo.toml index 8865c82..2eb98b3 100644 --- a/crates/shiri/Cargo.toml +++ b/crates/shiri/Cargo.toml @@ -12,9 +12,5 @@ repository.workspace = true # TODO: Make serde optional serde = { version = "1.0.193", default-features = false } -# TODO: Remove this -# TODO: Migrate back to the release once the required changes land upstream. -serde-value = { git = "https://github.com/gurafi/serde-value", rev = "a3c7d1e70bd3feb5c2eb62527748524dcbb358ec" } - # TODO: Dev depedency serde_json.workspace = true diff --git a/crates/shiri/src/serde.rs b/crates/shiri/src/serde.rs index d08eed9..1245c47 100644 --- a/crates/shiri/src/serde.rs +++ b/crates/shiri/src/serde.rs @@ -58,8 +58,7 @@ where Repr::Map(_) => unreachable!(), Repr::MapValue(mut s) => { use serde::ser::SerializeMap; - s.serialize_value(&serde_value::Value::String(value.to_owned())) - .unwrap(); + s.serialize_value(value).unwrap(); *self = Self(Repr::Map(s)); } Repr::Taken => todo!(), @@ -131,16 +130,16 @@ impl serde::Serializer for SerdeInterop where S: serde::Serializer, { - type Ok = serde_value::Value; - // TODO: Stop using `serde_value` and use internal stuff - type Error = serde_value::SerializerError; - type SerializeSeq = serde_value::SerializeSeq; - type SerializeTuple = serde_value::SerializeTuple; - type SerializeTupleStruct = serde_value::SerializeTupleStruct; - type SerializeTupleVariant = serde_value::SerializeTupleVariant; - type SerializeMap = serde_value::SerializeMap; - type SerializeStruct = serde_value::SerializeStruct; - type SerializeStructVariant = serde_value::SerializeStructVariant; + type Ok = (); + // TODO: Proper error type + type Error = Error; + type SerializeSeq = serde::ser::Impossible<(), Error>; + type SerializeTuple = serde::ser::Impossible<(), Error>; + type SerializeTupleStruct = serde::ser::Impossible<(), Error>; + type SerializeTupleVariant = serde::ser::Impossible<(), Error>; + type SerializeMap = serde::ser::Impossible<(), Error>; + type SerializeStruct = serde::ser::Impossible<(), Error>; + type SerializeStructVariant = serde::ser::Impossible<(), Error>; fn serialize_bool(self, v: bool) -> Result { todo!() @@ -309,16 +308,16 @@ where pub(crate) struct SerdeInterop2<'a>(pub Serializer2<'a>); impl<'a> serde::Serializer for SerdeInterop2<'a> { - type Ok = serde_value::Value; - // TODO: Stop using `serde_value` and use internal stuff - type Error = serde_value::SerializerError; - type SerializeSeq = serde_value::SerializeSeq; - type SerializeTuple = serde_value::SerializeTuple; - type SerializeTupleStruct = serde_value::SerializeTupleStruct; - type SerializeTupleVariant = serde_value::SerializeTupleVariant; - type SerializeMap = serde_value::SerializeMap; - type SerializeStruct = serde_value::SerializeStruct; - type SerializeStructVariant = serde_value::SerializeStructVariant; + type Ok = (); + // TODO: Proper error type + type Error = Error; + type SerializeSeq = serde::ser::Impossible<(), Error>; + type SerializeTuple = serde::ser::Impossible<(), Error>; + type SerializeTupleStruct = serde::ser::Impossible<(), Error>; + type SerializeTupleVariant = serde::ser::Impossible<(), Error>; + type SerializeMap = serde::ser::Impossible<(), Error>; + type SerializeStruct = serde::ser::Impossible<(), Error>; + type SerializeStructVariant = serde::ser::Impossible<(), Error>; fn serialize_bool(self, v: bool) -> Result { todo!() @@ -370,7 +369,7 @@ impl<'a> serde::Serializer for SerdeInterop2<'a> { fn serialize_str(self, v: &str) -> Result { self.0.serialize_str(v).unwrap(); - Ok(serde_value::Value::Unit) + Ok(()) } fn serialize_bytes(self, v: &[u8]) -> Result { diff --git a/crates/suku/src/server.rs b/crates/suku/src/server.rs index ce8be2e..9f10b6f 100644 --- a/crates/suku/src/server.rs +++ b/crates/suku/src/server.rs @@ -1,8 +1,8 @@ use core::fmt; use gql::{ - serializer::{OwnedSerializer, Serializer}, GraphQLResolveInfo, NamedOutputType, ObjectType, OutputType, ResolveFnArgs, Schema, Thunk, + serializer::{OwnedSerializer, Serializer}, }; use graphql_parser::query::{Definition, Document, OperationDefinition, Selection, SelectionSet}; @@ -36,7 +36,7 @@ impl Server { // TODO: Proper error handling + serializable error #[cfg_attr(feature = "tracing", tracing::instrument)] - pub async fn execute( + pub async fn execute( &self, mut serializer: OwnedSerializer, document: String,