diff --git a/lib/src/sql/value/serde/ser/kind/mod.rs b/lib/src/sql/value/serde/ser/kind/mod.rs new file mode 100644 index 00000000..60940d50 --- /dev/null +++ b/lib/src/sql/value/serde/ser/kind/mod.rs @@ -0,0 +1,180 @@ +use crate::err::Error; +use crate::sql::value::serde::ser; +use crate::sql::Kind; +use serde::ser::Error as _; +use serde::ser::Impossible; +use serde::ser::Serialize; + +pub(super) struct Serializer; + +impl ser::Serializer for Serializer { + type Ok = Kind; + type Error = Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + const EXPECTED: &'static str = "an enum `Kind`"; + + #[inline] + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + match variant { + "Any" => Ok(Kind::Any), + "Array" => Ok(Kind::Array), + "Bool" => Ok(Kind::Bool), + "Bytes" => Ok(Kind::Bytes), + "Datetime" => Ok(Kind::Datetime), + "Decimal" => Ok(Kind::Decimal), + "Duration" => Ok(Kind::Duration), + "Float" => Ok(Kind::Float), + "Int" => Ok(Kind::Int), + "Number" => Ok(Kind::Number), + "Object" => Ok(Kind::Object), + "String" => Ok(Kind::String), + variant => Err(Error::custom(format!("unexpected unit variant `{name}::{variant}`"))), + } + } + + #[inline] + fn serialize_newtype_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + match variant { + "Record" => Ok(Kind::Record(value.serialize(ser::table::vec::Serializer.wrap())?)), + "Geometry" => Ok(Kind::Geometry(value.serialize(ser::string::vec::Serializer.wrap())?)), + variant => { + Err(Error::custom(format!("unexpected newtype variant `{name}::{variant}`"))) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sql::serde::serialize_internal; + use ser::Serializer as _; + + #[test] + fn any() { + let kind = Kind::Any; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn array() { + let kind = Kind::Array; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn bool() { + let kind = Kind::Bool; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn bytes() { + let kind = Kind::Bytes; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn datetime() { + let kind = Kind::Datetime; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn decimal() { + let kind = Kind::Decimal; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn duration() { + let kind = Kind::Duration; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn float() { + let kind = Kind::Float; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn int() { + let kind = Kind::Int; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn number() { + let kind = Kind::Number; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn object() { + let kind = Kind::Object; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn string() { + let kind = Kind::String; + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn record() { + let kind = Kind::Record(Default::default()); + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + + let kind = Kind::Record(vec![Default::default()]); + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } + + #[test] + fn geometry() { + let kind = Kind::Geometry(Default::default()); + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + + let kind = Kind::Geometry(vec![Default::default()]); + let serialized = serialize_internal(|| kind.serialize(Serializer.wrap())).unwrap(); + assert_eq!(kind, serialized); + } +} diff --git a/lib/src/sql/value/serde/ser/mod.rs b/lib/src/sql/value/serde/ser/mod.rs index f4d13e11..f52e9eb3 100644 --- a/lib/src/sql/value/serde/ser/mod.rs +++ b/lib/src/sql/value/serde/ser/mod.rs @@ -16,6 +16,7 @@ mod geometry; mod graph; mod group; mod id; +mod kind; mod limit; mod model; mod number; diff --git a/lib/src/sql/value/serde/ser/string/mod.rs b/lib/src/sql/value/serde/ser/string/mod.rs index 1fd5b0e3..802bd9d4 100644 --- a/lib/src/sql/value/serde/ser/string/mod.rs +++ b/lib/src/sql/value/serde/ser/string/mod.rs @@ -1,3 +1,5 @@ +pub(super) mod vec; + use crate::err::Error; use crate::sql::value::serde::ser; use serde::ser::Impossible; diff --git a/lib/src/sql/value/serde/ser/string/vec.rs b/lib/src/sql/value/serde/ser/string/vec.rs new file mode 100644 index 00000000..85235382 --- /dev/null +++ b/lib/src/sql/value/serde/ser/string/vec.rs @@ -0,0 +1,77 @@ +use crate::err::Error; +use crate::sql::value::serde::ser; +use ser::Serializer as _; +use serde::ser::Impossible; +use serde::ser::Serialize; + +pub struct Serializer; + +impl ser::Serializer for Serializer { + type Ok = Vec; + type Error = Error; + + type SerializeSeq = SerializeStringVec; + type SerializeTuple = Impossible, Error>; + type SerializeTupleStruct = Impossible, Error>; + type SerializeTupleVariant = Impossible, Error>; + type SerializeMap = Impossible, Error>; + type SerializeStruct = Impossible, Error>; + type SerializeStructVariant = Impossible, Error>; + + const EXPECTED: &'static str = "a `Vec`"; + + fn serialize_seq(self, len: Option) -> Result { + Ok(SerializeStringVec(Vec::with_capacity(len.unwrap_or_default()))) + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self.wrap()) + } +} + +pub struct SerializeStringVec(Vec); + +impl serde::ser::SerializeSeq for SerializeStringVec { + type Ok = Vec; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + self.0.push(value.serialize(ser::string::Serializer.wrap())?); + Ok(()) + } + + fn end(self) -> Result { + Ok(self.0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sql::serde::serialize_internal; + + #[test] + fn empty() { + let vec: Vec = Vec::new(); + let serialized = serialize_internal(|| vec.serialize(Serializer.wrap())).unwrap(); + assert_eq!(vec, serialized); + } + + #[test] + fn vec() { + let vec = vec![String::new()]; + let serialized = serialize_internal(|| vec.serialize(Serializer.wrap())).unwrap(); + assert_eq!(vec, serialized); + } +}