From 9f1f1a80fe1d21eecd63c0c0aca7150011625ecd Mon Sep 17 00:00:00 2001 From: Volker Mische Date: Mon, 12 Aug 2024 23:22:54 +0200 Subject: [PATCH 1/4] chore: fix Clippy warnings on Rust 1.80.1 Fix all Clippy warnings on the most recent Rust stable release. --- src/lib.rs | 1 + src/serde/ser.rs | 52 ++++++++++++++++++++---------------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0190253..fdc8eab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_doctest_main)] #![doc = include_str!("../README.md")] #![deny(missing_docs)] #![deny(warnings)] diff --git a/src/serde/ser.rs b/src/serde/ser.rs index 19998f2..f31a2ea 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -207,13 +207,13 @@ impl serde::Serializer for Serializer { } #[inline] - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { let ipld = value.serialize(self); if name == CID_SERDE_PRIVATE_IDENTIFIER { @@ -226,7 +226,7 @@ impl serde::Serializer for Serializer { ipld } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, @@ -234,7 +234,7 @@ impl serde::Serializer for Serializer { value: &T, ) -> Result where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { let values = BTreeMap::from([(variant.to_owned(), value.serialize(self)?)]); Ok(Self::Ok::Map(values)) @@ -246,9 +246,9 @@ impl serde::Serializer for Serializer { } #[inline] - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { value.serialize(self) } @@ -341,9 +341,9 @@ impl ser::SerializeSeq for SerializeVec { type Ok = Ipld; type Error = SerdeError; - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { self.vec.push(value.serialize(Serializer)?); Ok(()) @@ -358,9 +358,9 @@ impl ser::SerializeTuple for SerializeVec { type Ok = Ipld; type Error = SerdeError; - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { ser::SerializeSeq::serialize_element(self, value) } @@ -374,9 +374,9 @@ impl ser::SerializeTupleStruct for SerializeVec { type Ok = Ipld; type Error = SerdeError; - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { ser::SerializeSeq::serialize_element(self, value) } @@ -390,9 +390,9 @@ impl ser::SerializeTupleVariant for SerializeTupleVariant { type Ok = Ipld; type Error = SerdeError; - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { self.vec.push(value.serialize(Serializer)?); Ok(()) @@ -408,9 +408,9 @@ impl ser::SerializeMap for SerializeMap { type Ok = Ipld; type Error = SerdeError; - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { match key.serialize(Serializer)? { Ipld::String(string_key) => { @@ -421,9 +421,9 @@ impl ser::SerializeMap for SerializeMap { } } - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { let key = self.next_key.take(); // Panic because this indicates a bug in the program rather than an @@ -442,13 +442,9 @@ impl ser::SerializeStruct for SerializeMap { type Ok = Ipld; type Error = SerdeError; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { serde::ser::SerializeMap::serialize_key(self, key)?; serde::ser::SerializeMap::serialize_value(self, value) @@ -463,13 +459,9 @@ impl ser::SerializeStructVariant for SerializeStructVariant { type Ok = Ipld; type Error = SerdeError; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: ser::Serialize, + T: ser::Serialize + ?Sized, { self.map .insert(key.to_string(), value.serialize(Serializer)?); From 4ef5d7344881d0c6c0824f40922bd3f5163320b6 Mon Sep 17 00:00:00 2001 From: Volker Mische Date: Mon, 12 Aug 2024 23:05:13 +0200 Subject: [PATCH 2/4] feat: make it possible to define your own primitive types As issue #19 outlines, it might make sense to use a different internal type for integer values. This commit makes all primitive types generic, so that you can choose your own. Though you're discouraged from doing so. Usually using the IPLD type should be enough and leads to the best interoperability. Thanks @stebalien for the idea of this implementation. Fixes #19. --- src/ipld.rs | 57 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/ipld.rs b/src/ipld.rs index ff0b9f7..ef6694b 100644 --- a/src/ipld.rs +++ b/src/ipld.rs @@ -33,29 +33,64 @@ impl fmt::Display for IndexError { #[cfg(feature = "std")] impl std::error::Error for IndexError {} -/// Ipld +/// Define the primitive types used for the internal IPLD Data Model representation within Rust. +/// +/// `Null` is missing as this is always represented as a unit variant. The container types are +/// derived from the primitives defined here. +pub trait Primitives { + /// Type for a boolean. + type Bool; + /// Type for an integer. + type Integer; + /// Type for a float. + type Float; + /// Type for a String. + type String; + /// Type for bytes. + type Bytes; + /// Type for a link. + type Link; +} + +/// The default values for the primitive types. #[derive(Clone)] -pub enum Ipld { +pub struct DefaultPrimitives; + +impl Primitives for DefaultPrimitives { + type Bool = bool; + type Integer = i128; + type Float = f64; + type String = String; + type Bytes = Vec; + type Link = Cid; +} + +/// The generic version of the core IPLD type that allows using custom primitive types. +#[derive(Clone)] +pub enum IpldGeneric { /// Represents the absence of a value or the value undefined. Null, /// Represents a boolean value. - Bool(bool), + Bool(P::Bool), /// Represents an integer. - Integer(i128), + Integer(P::Integer), /// Represents a floating point value. - Float(f64), + Float(P::Float), /// Represents an UTF-8 string. - String(String), + String(P::String), /// Represents a sequence of bytes. - Bytes(Vec), + Bytes(P::Bytes), /// Represents a list. - List(Vec), + List(Vec), /// Represents a map of strings. - Map(BTreeMap), - /// Represents a map of integers. - Link(Cid), + Map(BTreeMap), + /// Represents a link, usually a CID. + Link(P::Link), } +/// The core IPLD type. +pub type Ipld = IpldGeneric; + impl fmt::Debug for Ipld { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if f.alternate() { From edc70ed762ee2a44dad9fb42d2b58daaeaeb636d Mon Sep 17 00:00:00 2001 From: Volker Mische Date: Fri, 30 Aug 2024 01:46:03 +0200 Subject: [PATCH 3/4] WIP: deserializer seems to compile The serializer doesn't compile though. --- src/ipld.rs | 49 +++++++++--- src/lib.rs | 4 +- src/serde/de.rs | 201 ++++++++++++++++++++++++++++++----------------- src/serde/ser.rs | 164 ++++++++++++++++++++++++-------------- 4 files changed, 276 insertions(+), 142 deletions(-) diff --git a/src/ipld.rs b/src/ipld.rs index ef6694b..eab39fa 100644 --- a/src/ipld.rs +++ b/src/ipld.rs @@ -39,21 +39,27 @@ impl std::error::Error for IndexError {} /// derived from the primitives defined here. pub trait Primitives { /// Type for a boolean. - type Bool; + type Bool: fmt::Debug + From + Into; /// Type for an integer. - type Integer; + type Integer: fmt::Debug + From + From + From + Into; /// Type for a float. - type Float; + type Float: fmt::Debug + From + Into; /// Type for a String. - type String; + #[cfg(not(feature = "serde"))] + type String: fmt::Debug + From + Into + Ord; + // TODO vmx 2024-08-14: Check if the `for <'de>` is the right thing to do here. + #[cfg(feature = "serde")] + type String: fmt::Debug + From + Into + Ord + for<'de> serde::Deserialize<'de>; /// Type for bytes. - type Bytes; + type Bytes: fmt::Debug + From> + Into>; /// Type for a link. - type Link; + // TODO vmx 2024-08-14: This should be `CidGeneric` and not just `Cid`. + type Link: fmt::Debug + fmt::Display + From + Into; } /// The default values for the primitive types. -#[derive(Clone)] +#[derive(Clone, Debug)] +//pub struct DefaultPrimitives<'de>(&'de PhantomData<_>); pub struct DefaultPrimitives; impl Primitives for DefaultPrimitives { @@ -65,9 +71,30 @@ impl Primitives for DefaultPrimitives { type Link = Cid; } +#[cfg(feature = "serde")] +pub trait PrimitivesSerde<'de>: Primitives { + fn visit_integer, E: serde::de::Error>( + visitor: V, + value: ::Integer, + ) -> Result; +} + +#[cfg(feature = "serde")] +impl<'de> PrimitivesSerde<'de> for DefaultPrimitives { + //fn visit_integer(visitor: V) -> Result + fn visit_integer(visitor: V, value: Self::Integer) -> Result + where + V: serde::de::Visitor<'de>, + E: serde::de::Error, + { + visitor.visit_i128(value) + //println!("vmx: visit_integer") + } +} + /// The generic version of the core IPLD type that allows using custom primitive types. #[derive(Clone)] -pub enum IpldGeneric { +pub enum IpldGeneric { /// Represents the absence of a value or the value undefined. Null, /// Represents a boolean value. @@ -89,9 +116,13 @@ pub enum IpldGeneric { } /// The core IPLD type. +//pub type Ipld<'de> = IpldGeneric>; pub type Ipld = IpldGeneric; -impl fmt::Debug for Ipld { +impl

fmt::Debug for IpldGeneric

+where + P: Primitives, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if f.alternate() { match self { diff --git a/src/lib.rs b/src/lib.rs index fdc8eab..3fd2f09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![allow(clippy::needless_doctest_main)] #![doc = include_str!("../README.md")] -#![deny(missing_docs)] -#![deny(warnings)] +//#![deny(missing_docs)] +//#![deny(warnings)] #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; diff --git a/src/serde/de.rs b/src/serde/de.rs index cd890a6..310e200 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -1,5 +1,5 @@ use alloc::{borrow::ToOwned, collections::BTreeMap, format, string::String, vec::Vec}; -use core::{convert::TryFrom, fmt}; +use core::{convert::TryFrom, fmt, marker::PhantomData}; use cid::serde::{BytesToCidVisitor, CID_SERDE_PRIVATE_IDENTIFIER}; use cid::Cid; @@ -8,9 +8,12 @@ use serde::{ forward_to_deserialize_any, Deserialize, }; -use crate::{ipld::Ipld, serde::SerdeError}; +use crate::{ + ipld::{IpldGeneric, Primitives, PrimitivesSerde}, + serde::SerdeError, +}; -/// Deserialize instances of [`crate::ipld::Ipld`]. +/// Deserialize instances of [`crate::ipld::IpldGeneric`]. /// /// # Example /// @@ -48,22 +51,35 @@ use crate::{ipld::Ipld, serde::SerdeError}; /// assert!(matches!(person, Ok(Person { .. }))); /// ``` // NOTE vmx 2021-12-22: Taking by value is also what `serde_json` does. -pub fn from_ipld(value: Ipld) -> Result +pub fn from_ipld(value: IpldGeneric

) -> Result where + P: for<'de> PrimitivesSerde<'de>, T: serde::de::DeserializeOwned, { T::deserialize(value) } -impl<'de> de::Deserialize<'de> for Ipld { +//impl<'de, P> de::Deserializer<'de> for IpldGeneric

{ +// where +// P: Primitives, +// P::Integer: SomeTrait<'de>, + +impl<'de, P> de::Deserialize<'de> for IpldGeneric

+where + P: PrimitivesSerde<'de>, + //P::Integer: TraitWithDeLifetime<'de>, +{ fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct IpldVisitor; + struct IpldVisitor(PhantomData); - impl<'de> de::Visitor<'de> for IpldVisitor { - type Value = Ipld; + impl<'de, PInner> de::Visitor<'de> for IpldVisitor + where + PInner: PrimitivesSerde<'de>, + { + type Value = IpldGeneric; fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str("any valid IPLD kind") @@ -74,7 +90,9 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::String(String::from(value))) + //Ok(IpldGeneric::String(PInner::String::from(value))) + //Ok(IpldGeneric::String(PInner::String::from(value.to_string()))) + Ok(IpldGeneric::String(value.to_string().into())) } #[inline] @@ -90,7 +108,8 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Bytes(v)) + //Ok(IpldGeneric::Bytes(PInner::Bytes ::from(v))) + Ok(IpldGeneric::Bytes(v.into())) } #[inline] @@ -98,7 +117,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Integer(v.into())) + Ok(IpldGeneric::Integer(v.into())) } #[inline] @@ -106,7 +125,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Integer(v.into())) + Ok(IpldGeneric::Integer(v.into())) } #[inline] @@ -114,7 +133,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Integer(v)) + Ok(IpldGeneric::Integer(v.into())) } #[inline] @@ -122,7 +141,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Float(v)) + Ok(IpldGeneric::Float(v.into())) } #[inline] @@ -130,7 +149,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Bool(v)) + Ok(IpldGeneric::Bool(v.into())) } #[inline] @@ -138,7 +157,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Null) + Ok(IpldGeneric::Null) } #[inline] @@ -154,7 +173,7 @@ impl<'de> de::Deserialize<'de> for Ipld { where E: de::Error, { - Ok(Ipld::Null) + Ok(IpldGeneric::Null) } #[inline] @@ -168,7 +187,7 @@ impl<'de> de::Deserialize<'de> for Ipld { vec.push(elem); } - Ok(Ipld::List(vec)) + Ok(IpldGeneric::List(vec)) } #[inline] @@ -185,7 +204,7 @@ impl<'de> de::Deserialize<'de> for Ipld { } } - Ok(Ipld::Map(values)) + Ok(IpldGeneric::Map(values)) } /// Newtype structs are only used to deserialize CIDs. @@ -196,11 +215,11 @@ impl<'de> de::Deserialize<'de> for Ipld { { deserializer .deserialize_bytes(BytesToCidVisitor) - .map(Ipld::Link) + .map(|link| IpldGeneric::Link(link.into())) } } - deserializer.deserialize_any(IpldVisitor) + deserializer.deserialize_any(IpldVisitor(PhantomData)) } } @@ -208,15 +227,15 @@ macro_rules! impl_deserialize_integer { ($ty:ident, $deserialize:ident, $visit:ident) => { fn $deserialize>(self, visitor: V) -> Result { match self { - Self::Integer(integer) => match $ty::try_from(integer) { + Self::Integer(integer) => match $ty::try_from(integer.into()) { Ok(int) => visitor.$visit(int), Err(_) => error(format!( - "`Ipld::Integer` value was bigger than `{}`", + "`IpldGeneric::Integer` value was bigger than `{}`", stringify!($ty) )), }, _ => error(format!( - "Only `Ipld::Integer` can be deserialized to `{}`, input was `{:#?}`", + "Only `IpldGeneric::Integer` can be deserialized to `{}`, input was `{:#?}`", stringify!($ty), self )), @@ -227,8 +246,8 @@ macro_rules! impl_deserialize_integer { /// A Deserializer for CIDs. /// -/// A separate deserializer is needed to make sure we always deserialize only CIDs as `Ipld::Link` -/// and don't deserialize arbitrary bytes. +/// A separate deserializer is needed to make sure we always deserialize only CIDs as +/// `IpldGeneric::Link` and don't deserialize arbitrary bytes. struct CidDeserializer(Cid); impl<'de> de::Deserializer<'de> for CidDeserializer { @@ -249,13 +268,16 @@ impl<'de> de::Deserializer<'de> for CidDeserializer { } } -/// Deserialize from an [`Ipld`] enum into a Rust type. +/// Deserialize from an [`IpldGeneric`] enum into a Rust type. /// /// The deserialization will return an error if you try to deserialize into an integer type that -/// would be too small to hold the value stored in [`Ipld::Integer`]. +/// would be too small to hold the value stored in [`IpldGeneric::Integer`]. /// -/// [`Ipld::Floats`] can be converted to `f32` if there is no of precision, else it will error. -impl<'de> de::Deserializer<'de> for Ipld { +/// [`IpldGeneric::Floats`] can be converted to `f32` if there is no of precision, else it will error. +impl<'de, P> de::Deserializer<'de> for IpldGeneric

+where + P: PrimitivesSerde<'de>, +{ type Error = SerdeError; #[inline] @@ -265,14 +287,16 @@ impl<'de> de::Deserializer<'de> for Ipld { { match self { Self::Null => visitor.visit_none(), - Self::Bool(bool) => visitor.visit_bool(bool), - Self::Integer(i128) => visitor.visit_i128(i128), - Self::Float(f64) => visitor.visit_f64(f64), - Self::String(string) => visitor.visit_str(&string), - Self::Bytes(bytes) => visitor.visit_bytes(&bytes), + Self::Bool(bool) => visitor.visit_bool(bool.into()), + //GO ON HERE and think about what to visit here + //Self::Integer(i128) => visitor.visit_i128(i128), + Self::Integer(i128) => P::visit_integer(visitor, i128), + Self::Float(f64) => visitor.visit_f64(f64.into()), + Self::String(string) => visitor.visit_str(&string.into()), + Self::Bytes(bytes) => visitor.visit_bytes(&bytes.into()), Self::List(list) => visit_seq(list, visitor), Self::Map(map) => visit_map(map, visitor), - Self::Link(cid) => visitor.visit_newtype_struct(CidDeserializer(cid)), + Self::Link(cid) => visitor.visit_newtype_struct(CidDeserializer(cid.into())), } } @@ -288,7 +312,7 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_bool>(self, visitor: V) -> Result { match self { - Self::Bool(bool) => visitor.visit_bool(bool), + Self::Bool(bool) => visitor.visit_bool(bool.into()), _ => error(format!( "Only `Ipld::Bool` can be deserialized to bool, input was `{:#?}`", self @@ -308,7 +332,8 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_f32>(self, visitor: V) -> Result { match self { - Self::Float(float) => { + Self::Float(associate_float) => { + let float = associate_float.into(); if !float.is_finite() { error(format!("`Ipld::Float` must be a finite number, not infinity or NaN, input was `{}`", float)) } else if (float as f32) as f64 != float { @@ -328,7 +353,8 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_f64>(self, visitor: V) -> Result { match self { - Self::Float(float) => { + Self::Float(associate_float) => { + let float = associate_float.into(); if float.is_finite() { visitor.visit_f64(float) } else { @@ -344,7 +370,8 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_char>(self, visitor: V) -> Result { match self { - Self::String(string) => { + Self::String(associate_string) => { + let string: String = associate_string.into(); if string.chars().count() == 1 { visitor.visit_char(string.chars().next().unwrap()) } else { @@ -360,7 +387,7 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_str>(self, visitor: V) -> Result { match self { - Self::String(string) => visitor.visit_str(&string), + Self::String(string) => visitor.visit_str(&string.into()), _ => error(format!( "Only `Ipld::String` can be deserialized to string, input was `{:#?}`", self @@ -370,7 +397,7 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_string>(self, visitor: V) -> Result { match self { - Self::String(string) => visitor.visit_string(string), + Self::String(string) => visitor.visit_string(string.into()), _ => error(format!( "Only `Ipld::String` can be deserialized to string, input was `{:#?}`", self @@ -380,7 +407,7 @@ impl<'de> de::Deserializer<'de> for Ipld { fn deserialize_bytes>(self, visitor: V) -> Result { match self { - Self::Bytes(bytes) => visitor.visit_bytes(&bytes), + Self::Bytes(bytes) => visitor.visit_bytes(&bytes.into()), _ => error(format!( "Only `Ipld::Bytes` can be deserialized to bytes, input was `{:#?}`", self @@ -393,7 +420,7 @@ impl<'de> de::Deserializer<'de> for Ipld { visitor: V, ) -> Result { match self { - Self::Bytes(bytes) => visitor.visit_byte_buf(bytes), + Self::Bytes(bytes) => visitor.visit_byte_buf(bytes.into()), _ => error(format!( "Only `Ipld::Bytes` can be deserialized to bytes, input was `{:#?}`", self @@ -455,7 +482,7 @@ impl<'de> de::Deserializer<'de> for Ipld { visitor: V, ) -> Result { match self { - Self::String(string) => visitor.visit_str(&string), + Self::String(string) => visitor.visit_str(&string.into()), _ => error(format!( "Only `Ipld::String` can be deserialized to identifier, input was `{:#?}`", self @@ -493,7 +520,7 @@ impl<'de> de::Deserializer<'de> for Ipld { ) -> Result { if name == CID_SERDE_PRIVATE_IDENTIFIER { match self { - Ipld::Link(cid) => visitor.visit_newtype_struct(CidDeserializer(cid)), + IpldGeneric::Link(cid) => visitor.visit_newtype_struct(CidDeserializer(cid.into())), _ => error(format!( "Only `Ipld::Link`s can be deserialized to CIDs, input was `{:#?}`", self @@ -513,7 +540,7 @@ impl<'de> de::Deserializer<'de> for Ipld { visitor: V, ) -> Result { let (variant, value) = match self { - Ipld::Map(map) => { + IpldGeneric::Map(map) => { let mut iter = map.into_iter(); let (variant, value) = match iter.next() { Some(v) => v, @@ -529,9 +556,9 @@ impl<'de> de::Deserializer<'de> for Ipld { "Only `Ipld::Map`s with a single key can be deserialized to `enum`, input had more keys" ); } - (variant, Some(value)) + (variant.into(), Some(value)) } - Ipld::String(variant) => (variant, None), + IpldGeneric::String(variant) => (variant.into(), None), _ => return error(format!( "Only `Ipld::Map` and `Ipld::String` can be deserialized to `enum`, input was `{:#?}`", self @@ -563,16 +590,21 @@ impl<'de> de::Deserializer<'de> for Ipld { } } -fn visit_map<'de, V>(map: BTreeMap, visitor: V) -> Result +fn visit_map<'de, P, V>( + map: BTreeMap>, + visitor: V, +) -> Result where + P: PrimitivesSerde<'de>, V: de::Visitor<'de>, { let mut deserializer = MapDeserializer::new(map); visitor.visit_map(&mut deserializer) } -fn visit_seq<'de, V>(list: Vec, visitor: V) -> Result +fn visit_seq<'de, P, V>(list: Vec>, visitor: V) -> Result where + P: PrimitivesSerde<'de>, V: de::Visitor<'de>, { let mut deserializer = SeqDeserializer::new(list); @@ -581,13 +613,19 @@ where // Heavily based on // https://github.com/serde-rs/json/blob/95f67a09399d546d9ecadeb747a845a77ff309b2/src/value/de.rs#L601 -struct MapDeserializer { - iter: as IntoIterator>::IntoIter, - value: Option, +struct MapDeserializer

+where + P: Primitives, +{ + iter: > as IntoIterator>::IntoIter, + value: Option>, } -impl MapDeserializer { - fn new(map: BTreeMap) -> Self { +impl

MapDeserializer

+where + P: Primitives, +{ + fn new(map: BTreeMap>) -> Self { Self { iter: map.into_iter(), value: None, @@ -595,7 +633,10 @@ impl MapDeserializer { } } -impl<'de> de::MapAccess<'de> for MapDeserializer { +impl<'de, P> de::MapAccess<'de> for MapDeserializer

+where + P: PrimitivesSerde<'de>, +{ type Error = SerdeError; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> @@ -605,7 +646,7 @@ impl<'de> de::MapAccess<'de> for MapDeserializer { match self.iter.next() { Some((key, value)) => { self.value = Some(value); - seed.deserialize(Ipld::String(key)).map(Some) + seed.deserialize(IpldGeneric::

::String(key)).map(Some) } None => Ok(None), } @@ -631,19 +672,28 @@ impl<'de> de::MapAccess<'de> for MapDeserializer { // Heavily based on // https://github.com/serde-rs/json/blob/95f67a09399d546d9ecadeb747a845a77ff309b2/src/value/de.rs#L554 -struct SeqDeserializer { - iter: as IntoIterator>::IntoIter, +struct SeqDeserializer

+where + P: Primitives, +{ + iter: > as IntoIterator>::IntoIter, } -impl SeqDeserializer { - fn new(vec: Vec) -> Self { +impl

SeqDeserializer

+where + P: Primitives, +{ + fn new(vec: Vec>) -> Self { Self { iter: vec.into_iter(), } } } -impl<'de> de::SeqAccess<'de> for SeqDeserializer { +impl<'de, P> de::SeqAccess<'de> for SeqDeserializer

+where + P: PrimitivesSerde<'de>, +{ type Error = SerdeError; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> @@ -666,14 +716,20 @@ impl<'de> de::SeqAccess<'de> for SeqDeserializer { // Heavily based on // https://github.com/serde-rs/json/blob/95f67a09399d546d9ecadeb747a845a77ff309b2/src/value/de.rs#L455 -struct EnumDeserializer { +struct EnumDeserializer

+where + P: Primitives, +{ variant: String, - value: Option, + value: Option>, } -impl<'de> de::EnumAccess<'de> for EnumDeserializer { +impl<'de, P> de::EnumAccess<'de> for EnumDeserializer

+where + P: PrimitivesSerde<'de>, +{ type Error = SerdeError; - type Variant = VariantDeserializer; + type Variant = VariantDeserializer

; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where @@ -687,9 +743,12 @@ impl<'de> de::EnumAccess<'de> for EnumDeserializer { // Heavily based on // https://github.com/serde-rs/json/blob/95f67a09399d546d9ecadeb747a845a77ff309b2/src/value/de.rs#L482 -struct VariantDeserializer(Option); +struct VariantDeserializer(Option>); -impl<'de> de::VariantAccess<'de> for VariantDeserializer { +impl<'de, P> de::VariantAccess<'de> for VariantDeserializer

+where + P: PrimitivesSerde<'de>, +{ type Error = SerdeError; fn unit_variant(self) -> Result<(), Self::Error> { @@ -717,7 +776,7 @@ impl<'de> de::VariantAccess<'de> for VariantDeserializer { V: de::Visitor<'de>, { match self.0 { - Some(Ipld::List(list)) => { + Some(IpldGeneric::List(list)) => { if len == list.len() { visit_seq(list, visitor) } else { @@ -744,7 +803,7 @@ impl<'de> de::VariantAccess<'de> for VariantDeserializer { V: de::Visitor<'de>, { match self.0 { - Some(Ipld::Map(v)) => visit_map(v, visitor), + Some(IpldGeneric::Map(v)) => visit_map(v, visitor), Some(_) => error(format!( "Only `Ipld::Map` can be deserialized to struct variant, input was `{:#?}`", self.0 diff --git a/src/serde/ser.rs b/src/serde/ser.rs index f31a2ea..43d3d80 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -7,13 +7,16 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::convert::TryFrom; +use core::{convert::TryFrom, fmt::Debug, marker::PhantomData}; use cid::serde::CID_SERDE_PRIVATE_IDENTIFIER; use cid::Cid; use serde::ser; -use crate::{ipld::Ipld, serde::SerdeError}; +use crate::{ + ipld::{IpldGeneric, Primitives}, + serde::SerdeError, +}; /// Serialize into instances of [`crate::ipld::Ipld`]. /// @@ -72,50 +75,58 @@ use crate::{ipld::Ipld, serde::SerdeError}; /// let ipld = to_ipld(person); /// assert!(matches!(ipld, Ok(Ipld::Map(_)))); /// ``` -pub fn to_ipld(value: T) -> Result +pub fn to_ipld(value: T) -> Result, SerdeError> where T: ser::Serialize, + P: Primitives, { value.serialize(Serializer) } -impl ser::Serialize for Ipld { +impl

ser::Serialize for IpldGeneric

+where + P: Primitives, +{ fn serialize(&self, serializer: S) -> Result where S: ser::Serializer, { match &self { - Self::Null => serializer.serialize_none(), - Self::Bool(value) => serializer.serialize_bool(*value), - Self::Integer(value) => serializer.serialize_i128(*value), - Self::Float(value) => serializer.serialize_f64(*value), - Self::String(value) => serializer.serialize_str(value), - Self::Bytes(value) => serializer.serialize_bytes(value), - Self::List(value) => serializer.collect_seq(value), - Self::Map(value) => serializer.collect_map(value), - Self::Link(value) => value.serialize(serializer), + //Self::Null => serializer.serialize_none(), + //Self::Bool(value) => serializer.serialize_bool((*value).into()), + //Self::Integer(value) => serializer.serialize_i128((*value).into()), + //Self::Float(value) => serializer.serialize_f64((*value).into()), + //Self::String(value) => serializer.serialize_str(&(*value).into()), + //Self::Bytes(value) => serializer.serialize_bytes(&(*value).into()), + //Self::List(value) => serializer.collect_seq(value), + //Self::Map(value) => serializer.collect_map(value.into()), + //Self::Link(value) => (*value).into().serialize(serializer), + _ => todo!(), } } } /// The IPLD serializer. -pub struct Serializer; +pub struct Serializer

(PhantomData

); -impl serde::Serializer for Serializer { - type Ok = Ipld; +impl

serde::Serializer for Serializer

+where + P: Primitives + Debug, +{ + type Ok = IpldGeneric

; type Error = SerdeError; - type SerializeSeq = SerializeVec; - type SerializeTuple = SerializeVec; - type SerializeTupleStruct = SerializeVec; - type SerializeTupleVariant = SerializeTupleVariant; - type SerializeMap = SerializeMap; - type SerializeStruct = SerializeMap; - type SerializeStructVariant = SerializeStructVariant; + type SerializeSeq = SerializeVec

; + type SerializeTuple = SerializeVec

; + type SerializeTupleStruct = SerializeVec

; + type SerializeTupleVariant = SerializeTupleVariant

; + type SerializeMap = SerializeMap

; + type SerializeStruct = SerializeMap

; + type SerializeStructVariant = SerializeStructVariant

; #[inline] fn serialize_bool(self, value: bool) -> Result { - Ok(Self::Ok::Bool(value)) + Ok(Self::Ok::Bool(value.into())) } #[inline] @@ -139,7 +150,7 @@ impl serde::Serializer for Serializer { } fn serialize_i128(self, value: i128) -> Result { - Ok(Self::Ok::Integer(value)) + Ok(Self::Ok::Integer(value.into())) } #[inline] @@ -169,7 +180,7 @@ impl serde::Serializer for Serializer { #[inline] fn serialize_f64(self, value: f64) -> Result { - Ok(Self::Ok::Float(value)) + Ok(Self::Ok::Float(value.into())) } #[inline] @@ -179,11 +190,11 @@ impl serde::Serializer for Serializer { #[inline] fn serialize_str(self, value: &str) -> Result { - Ok(Self::Ok::String(value.to_owned())) + Ok(Self::Ok::String(value.to_owned().into())) } fn serialize_bytes(self, value: &[u8]) -> Result { - Ok(Self::Ok::Bytes(value.to_vec())) + Ok(Self::Ok::Bytes(value.to_vec().into())) } #[inline] @@ -217,10 +228,10 @@ impl serde::Serializer for Serializer { { let ipld = value.serialize(self); if name == CID_SERDE_PRIVATE_IDENTIFIER { - if let Ok(Ipld::Bytes(bytes)) = ipld { - let cid = Cid::try_from(bytes) + if let Ok(IpldGeneric::Bytes(bytes)) = ipld { + let cid = Cid::try_from(bytes.into()) .map_err(|err| ser::Error::custom(format!("Invalid CID: {}", err)))?; - return Ok(Self::Ok::Link(cid)); + return Ok(Self::Ok::Link(cid.into())); } } ipld @@ -236,7 +247,7 @@ impl serde::Serializer for Serializer { where T: ser::Serialize + ?Sized, { - let values = BTreeMap::from([(variant.to_owned(), value.serialize(self)?)]); + let values = BTreeMap::from([(variant.to_owned().into(), value.serialize(self)?)]); Ok(Self::Ok::Map(values)) } @@ -307,7 +318,7 @@ impl serde::Serializer for Serializer { _len: usize, ) -> Result { Ok(SerializeStructVariant { - name: String::from(variant), + name: P::String::from(variant.into()), map: BTreeMap::new(), }) } @@ -318,27 +329,42 @@ impl serde::Serializer for Serializer { } } -pub struct SerializeVec { - vec: Vec, +pub struct SerializeVec

+where + P: Primitives, +{ + vec: Vec>, } -pub struct SerializeTupleVariant { +pub struct SerializeTupleVariant

+where + P: Primitives, +{ name: String, - vec: Vec, + vec: Vec>, } -pub struct SerializeMap { - map: BTreeMap, - next_key: Option, +pub struct SerializeMap

+where + P: Primitives, +{ + map: BTreeMap>, + next_key: Option, } -pub struct SerializeStructVariant { - name: String, - map: BTreeMap, +pub struct SerializeStructVariant

+where + P: Primitives, +{ + name: P::String, + map: BTreeMap>, } -impl ser::SerializeSeq for SerializeVec { - type Ok = Ipld; +impl

ser::SerializeSeq for SerializeVec

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> @@ -354,8 +380,11 @@ impl ser::SerializeSeq for SerializeVec { } } -impl ser::SerializeTuple for SerializeVec { - type Ok = Ipld; +impl

ser::SerializeTuple for SerializeVec

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> @@ -370,8 +399,11 @@ impl ser::SerializeTuple for SerializeVec { } } -impl ser::SerializeTupleStruct for SerializeVec { - type Ok = Ipld; +impl

ser::SerializeTupleStruct for SerializeVec

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> @@ -386,8 +418,11 @@ impl ser::SerializeTupleStruct for SerializeVec { } } -impl ser::SerializeTupleVariant for SerializeTupleVariant { - type Ok = Ipld; +impl

ser::SerializeTupleVariant for SerializeTupleVariant

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> @@ -399,13 +434,16 @@ impl ser::SerializeTupleVariant for SerializeTupleVariant { } fn end(self) -> Result { - let map = BTreeMap::from([(self.name, Self::Ok::List(self.vec))]); + let map = BTreeMap::from([(self.name.into(), Self::Ok::List(self.vec))]); Ok(Self::Ok::Map(map)) } } -impl ser::SerializeMap for SerializeMap { - type Ok = Ipld; +impl

ser::SerializeMap for SerializeMap

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> @@ -413,7 +451,7 @@ impl ser::SerializeMap for SerializeMap { T: ser::Serialize + ?Sized, { match key.serialize(Serializer)? { - Ipld::String(string_key) => { + IpldGeneric::String(string_key) => { self.next_key = Some(string_key); Ok(()) } @@ -438,8 +476,11 @@ impl ser::SerializeMap for SerializeMap { } } -impl ser::SerializeStruct for SerializeMap { - type Ok = Ipld; +impl

ser::SerializeStruct for SerializeMap

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> @@ -455,8 +496,11 @@ impl ser::SerializeStruct for SerializeMap { } } -impl ser::SerializeStructVariant for SerializeStructVariant { - type Ok = Ipld; +impl

ser::SerializeStructVariant for SerializeStructVariant

+where + P: Primitives, +{ + type Ok = IpldGeneric

; type Error = SerdeError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> @@ -464,7 +508,7 @@ impl ser::SerializeStructVariant for SerializeStructVariant { T: ser::Serialize + ?Sized, { self.map - .insert(key.to_string(), value.serialize(Serializer)?); + .insert(key.to_string().into(), value.serialize(Serializer)?); Ok(()) } From 15a55ea1254cf897c74a77c78be9809eb4544c54 Mon Sep 17 00:00:00 2001 From: Volker Mische Date: Fri, 30 Aug 2024 13:11:36 +0200 Subject: [PATCH 4/4] fix: add Serializer constructor Things are getting closer to working. But getting from `&P::String` to `&str` seems to be hard to do. --- src/ipld.rs | 19 ++++++++++++------ src/serde/ser.rs | 42 ++++++++++++++++++++++++--------------- tests/serde_serializer.rs | 4 ++-- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/ipld.rs b/src/ipld.rs index eab39fa..a9b54fa 100644 --- a/src/ipld.rs +++ b/src/ipld.rs @@ -37,24 +37,32 @@ impl std::error::Error for IndexError {} /// /// `Null` is missing as this is always represented as a unit variant. The container types are /// derived from the primitives defined here. -pub trait Primitives { +pub trait Primitives: fmt::Debug { /// Type for a boolean. - type Bool: fmt::Debug + From + Into; + type Bool: fmt::Debug + From + Into + Copy; /// Type for an integer. - type Integer: fmt::Debug + From + From + From + Into; + type Integer: fmt::Debug + From + From + From + Into + Copy; /// Type for a float. - type Float: fmt::Debug + From + Into; + type Float: fmt::Debug + From + Into + Copy; /// Type for a String. #[cfg(not(feature = "serde"))] type String: fmt::Debug + From + Into + Ord; // TODO vmx 2024-08-14: Check if the `for <'de>` is the right thing to do here. #[cfg(feature = "serde")] - type String: fmt::Debug + From + Into + Ord + for<'de> serde::Deserialize<'de>; + type String: fmt::Debug + + From + + Into + + Ord + + for<'de> serde::Deserialize<'de> + + serde::Serialize; /// Type for bytes. type Bytes: fmt::Debug + From> + Into>; /// Type for a link. // TODO vmx 2024-08-14: This should be `CidGeneric` and not just `Cid`. + #[cfg(not(feature = "serde"))] type Link: fmt::Debug + fmt::Display + From + Into; + #[cfg(feature = "serde")] + type Link: fmt::Debug + fmt::Display + From + Into + serde::Serialize; } /// The default values for the primitive types. @@ -116,7 +124,6 @@ pub enum IpldGeneric { } /// The core IPLD type. -//pub type Ipld<'de> = IpldGeneric>; pub type Ipld = IpldGeneric; impl

fmt::Debug for IpldGeneric

diff --git a/src/serde/ser.rs b/src/serde/ser.rs index 43d3d80..d039dd5 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -80,28 +80,32 @@ where T: ser::Serialize, P: Primitives, { - value.serialize(Serializer) + value.serialize(Serializer::new()) } impl

ser::Serialize for IpldGeneric

where P: Primitives, + //for<'a> &'a [u8]: From<&'a P::Bytes>, + //for<'a> &'a str: From<&'a P::String>, { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer, { match &self { - //Self::Null => serializer.serialize_none(), - //Self::Bool(value) => serializer.serialize_bool((*value).into()), - //Self::Integer(value) => serializer.serialize_i128((*value).into()), - //Self::Float(value) => serializer.serialize_f64((*value).into()), - //Self::String(value) => serializer.serialize_str(&(*value).into()), - //Self::Bytes(value) => serializer.serialize_bytes(&(*value).into()), - //Self::List(value) => serializer.collect_seq(value), - //Self::Map(value) => serializer.collect_map(value.into()), - //Self::Link(value) => (*value).into().serialize(serializer), - _ => todo!(), + Self::Null => serializer.serialize_none(), + Self::Bool(value) => serializer.serialize_bool((*value).into()), + Self::Integer(value) => serializer.serialize_i128((*value).into()), + Self::Float(value) => serializer.serialize_f64((*value).into()), + Self::String(value) => serializer.serialize_str(value.into()), + Self::Bytes(value) => serializer.serialize_bytes(value.into()), + Self::List(value) => serializer.collect_seq(value), + Self::Map(value) => { + serializer.collect_map::<_, _, &BTreeMap>>(value) + } + Self::Link(value) => value.serialize(serializer), + //_ => todo!(), } } } @@ -109,6 +113,12 @@ where /// The IPLD serializer. pub struct Serializer

(PhantomData

); +impl

Serializer

{ + pub fn new() -> Self { + Self(PhantomData) + } +} + impl

serde::Serializer for Serializer

where P: Primitives + Debug, @@ -371,7 +381,7 @@ where where T: ser::Serialize + ?Sized, { - self.vec.push(value.serialize(Serializer)?); + self.vec.push(value.serialize(Serializer::new())?); Ok(()) } @@ -429,7 +439,7 @@ where where T: ser::Serialize + ?Sized, { - self.vec.push(value.serialize(Serializer)?); + self.vec.push(value.serialize(Serializer::new())?); Ok(()) } @@ -450,7 +460,7 @@ where where T: ser::Serialize + ?Sized, { - match key.serialize(Serializer)? { + match key.serialize(Serializer::

::new())? { IpldGeneric::String(string_key) => { self.next_key = Some(string_key); Ok(()) @@ -467,7 +477,7 @@ where // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect("serialize_value called before serialize_key"); - self.map.insert(key, value.serialize(Serializer)?); + self.map.insert(key, value.serialize(Serializer::new())?); Ok(()) } @@ -508,7 +518,7 @@ where T: ser::Serialize + ?Sized, { self.map - .insert(key.to_string().into(), value.serialize(Serializer)?); + .insert(key.to_string().into(), value.serialize(Serializer::new())?); Ok(()) } diff --git a/tests/serde_serializer.rs b/tests/serde_serializer.rs index 56952c4..6967dc5 100644 --- a/tests/serde_serializer.rs +++ b/tests/serde_serializer.rs @@ -25,7 +25,7 @@ where #[allow(clippy::let_unit_value)] fn ipld_serializer_unit() { let unit = (); - let serialized = to_ipld(unit); + let serialized: Result = to_ipld(unit); assert!(serialized.is_err()); } @@ -35,7 +35,7 @@ fn ipld_serializer_unit_struct() { struct UnitStruct; let unit_struct = UnitStruct; - let serialized = to_ipld(unit_struct); + let serialized: Result = to_ipld(unit_struct); assert!(serialized.is_err()); }