From e5bb8c3cf522b21d337f6c44f8538266627b6572 Mon Sep 17 00:00:00 2001 From: sunny-g Date: Tue, 27 Sep 2022 12:31:52 -0500 Subject: [PATCH 1/9] simplify impls for select, misc --- Cargo.toml | 8 +- macros-internals/Cargo.toml | 1 + .../src/schema/compound/expand_list.rs | 2 +- .../src/schema/compound/expand_map.rs | 2 +- macros-internals/src/schema/expand.rs | 278 ++++---- macros-internals/src/schema/mod.rs | 109 ++- macros-internals/src/schema/parse.rs | 13 +- .../src/schema/primitive/expand.rs | 12 +- .../src/schema/primitive/expand_bytes.rs | 2 +- .../src/schema/primitive/expand_link.rs | 2 +- macros-internals/src/schema/struct/expand.rs | 41 +- macros-internals/src/schema/union/expand.rs | 130 ++-- .../src/schema/union/expand_kinded.rs | 86 ++- macros-internals/src/schema/union/mod.rs | 9 +- macros-internals/src/schema/union/parse.rs | 62 +- src/cid.rs | 68 +- src/codecs/dag_cbor.rs | 250 ++++++- src/codecs/dag_cose.rs | 0 src/codecs/dag_jose.rs | 0 src/codecs/dag_json.rs | 73 +- src/codecs/dag_pb.rs | 124 ---- src/codecs/mod.rs | 24 +- src/codecs/raw.rs | 0 src/data_model/compat.rs | 174 +++++ src/data_model/link.rs | 77 ++- src/data_model/list.rs | 105 ++- src/data_model/map.rs | 76 ++- src/data_model/mod.rs | 20 +- src/data_model/primitive.rs | 295 +++++---- src/lib.rs | 5 +- src/multicodec.rs | 81 ++- src/multihash.rs | 2 +- src/representation.rs | 153 ++--- src/selectors/mod.rs | 76 ++- src/selectors/seed.rs | 623 +++++++++++++----- src/selectors/state.rs | 44 +- tests/codec-fixtures.rs | 18 +- 37 files changed, 1914 insertions(+), 1131 deletions(-) delete mode 100644 src/codecs/dag_cose.rs delete mode 100644 src/codecs/dag_jose.rs delete mode 100644 src/codecs/dag_pb.rs delete mode 100644 src/codecs/raw.rs create mode 100644 src/data_model/compat.rs diff --git a/Cargo.toml b/Cargo.toml index 34a1d92..ccd0551 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,9 @@ thiserror = "1.0" unicode-normalization = "0.1" # codecs -serde_cbor = { version = "0.11", optional = true } # TODO: use ciborium or cbor4ii instead +serde_cbor = { version = "0.11", optional = true, features = ["tags"] } +# cbor4ii = { version = "0.2", optional = true, features = ["serde1", "use_std"] } +# serde_ipld_dagcbor = { version = "0.2", optional = true, features = ["std"] } serde_json = { version = "1.0", optional = true, features = ["float_roundtrip"] } # simd-json = { version = "0.6", optional = true, features = ["serde_impl", "128bit"] } @@ -45,7 +47,9 @@ proptest = "1.0" [features] default = ["multicodec"] -dag-cbor = ["serde_cbor/tags"] +dag-cbor = ["serde_cbor"] +# dag-cbor = ["cbor4ii", "delegate"] +# dag-cbor = ["serde_ipld_dagcbor", "delegate"] dag-json = ["serde_json", "delegate"] dag-pb = [] # enables all available multicodecs diff --git a/macros-internals/Cargo.toml b/macros-internals/Cargo.toml index 2e9a584..a9b6c05 100644 --- a/macros-internals/Cargo.toml +++ b/macros-internals/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitflags = "1.3" derive_more = "0.99" # impls = "1" # juniper = { version = "0.14", optional = true } diff --git a/macros-internals/src/schema/compound/expand_list.rs b/macros-internals/src/schema/compound/expand_list.rs index b76e759..97a3458 100644 --- a/macros-internals/src/schema/compound/expand_list.rs +++ b/macros-internals/src/schema/compound/expand_list.rs @@ -10,7 +10,7 @@ use syn::{ impl ExpandBasicRepresentation for ListReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let child_ty = self.child_ty(); diff --git a/macros-internals/src/schema/compound/expand_map.rs b/macros-internals/src/schema/compound/expand_map.rs index 1aeaaca..25d27cc 100644 --- a/macros-internals/src/schema/compound/expand_map.rs +++ b/macros-internals/src/schema/compound/expand_map.rs @@ -12,7 +12,7 @@ impl ExpandBasicRepresentation for MapReprDefinition { let inner_ty = self.inner_ty(); match self { - Self::Basic { .. } => derive_newtype!(@typedef_transparent self, meta => inner_ty), + Self::Basic { .. } => derive_newtype!(@typedef self, meta => inner_ty), Self::Stringpairs { .. } => unimplemented!(), Self::Listpairs { .. } => unimplemented!(), Self::Advanced(..) => unimplemented!(), diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index da12ae9..d6ff1d9 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -42,22 +42,15 @@ impl ToTokens for SchemaDefinition { fn to_tokens(&self, tokens: &mut TokenStream) { macro_rules! expand_basic { ($meta:ident, $def:ident) => {{ - let name = &$meta.name; - let typedef = $def.define_type($meta); - let lib = &$meta.lib; - - let use_ipld = if $meta.internal { - quote! { + let import_ipld = if $meta.internal { + quote!( use crate as _ipld; - #[allow(unused_imports)] - use _ipld::dev::*; - } + ) } else { + let lib = &$meta.lib; quote! { // #[allow(clippy::useless_attribute)] - extern crate #lib as _ipld - #[allow(unused_imports)] - use _ipld::dev::*; + extern crate #lib as _ipld; } }; @@ -69,9 +62,12 @@ impl ToTokens for SchemaDefinition { ]; let scoped_impls = defs .iter() - .map(|(kind, def)| { + .map(|(def_kind, def)| { ( - Ident::new(&format!("_IPLD_{}_FOR_{}", kind, name), Span::call_site()), + Ident::new( + &format!("_IPLD_{}_FOR_{}", def_kind, &$meta.name), + Span::call_site(), + ), def, ) }) @@ -79,13 +75,16 @@ impl ToTokens for SchemaDefinition { quote! { #[doc(hidden)] const #ident: () = { - #use_ipld + #import_ipld + #[allow(unused_imports)] + use _ipld::dev::*; #def }; } }); + let typedef = $def.define_type($meta); quote! { #typedef #(#scoped_impls)* @@ -103,7 +102,7 @@ impl ToTokens for SchemaDefinition { ReprDefinition::String(def) => expand_basic!(meta, def), ReprDefinition::Bytes(def) => expand_basic!(meta, def), ReprDefinition::List(def) => expand_basic!(meta, def), - // ReprDefinition::Map(def) => expand_basic_def!(meta, def), + ReprDefinition::Map(def) => expand_basic!(meta, def), ReprDefinition::Link(def) => expand_basic!(meta, def), // schema kinds @@ -190,7 +189,7 @@ pub trait ExpandAdvancedRepresentation { impl SchemaKind { pub(crate) fn data_model_kind(&self) -> Ident { Ident::new( - match self { + match *self { Self::Null => "Null", Self::Bool => "Bool", Self::Int @@ -214,6 +213,7 @@ impl SchemaKind { Self::Union => "Union", Self::Enum => "Enum", Self::Copy => "Copy", + _ => unreachable!(), }, Span::call_site(), ) @@ -221,7 +221,7 @@ impl SchemaKind { pub(crate) fn selected_node_ident(&self) -> Ident { Ident::new( - match self { + match *self { Self::Null => "Null", Self::Bool => "Bool", Self::Int => "Int64", @@ -243,10 +243,11 @@ impl SchemaKind { Self::List => "List", Self::Map => "Map", Self::Link => "Link", - Self::Struct => "Struct", - Self::Union => "Union", - Self::Enum => "Enum", - Self::Copy => "Copy", + Self::Struct => todo!(), + Self::Union => todo!(), + Self::Enum => todo!(), + Self::Copy => todo!(), + _ => unreachable!(), }, Span::call_site(), ) @@ -293,13 +294,13 @@ macro_rules! derive_newtype { #vis struct #name #generics (#$inner_ty); } }}; - (@typedef_transparent $def:ident, $meta:ident => $inner_ty:ident) => {{ - $crate::derive_newtype! { @typedef - $def, $meta => $inner_ty - #[derive(Deserialize, Serialize)] - #[serde(transparent)] - } - }}; + // (@typedef_transparent $def:ident, $meta:ident => $inner_ty:ident) => {{ + // $crate::derive_newtype! { @typedef + // $def, $meta => $inner_ty + // #[derive(serde::Deserialize, serde::Serialize)] + // #[serde(transparent)] + // } + // }}; (@repr { $tokens:tt } $meta:ident => $inner_ty:ident) => {{ $crate::dev::impl_repr( $meta, @@ -372,117 +373,114 @@ macro_rules! derive_newtype { }}; } -/// -pub(crate) fn impl_serialize(meta: &SchemaMeta, body: TokenStream) -> TokenStream { - let name = &meta.name; - quote! { - #[automatically_derived] - impl Serialize for #name { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - #body - } - } - } -} - -// TODO: for each visitor method, incorporate try_from... -// - define TryFromType -// - `impl Visitor for ReprVisitor` -// - method bodies expanded (should only refer to Self::Value, not #name) -// - in `impl Visitor for ReprVisitor`, replacing method bodies -// - call each equiv method on > -// - handle result with try_from().map_err() call -pub(crate) fn impl_visitor( - meta: &SchemaMeta, - expecting: &'static str, - body: TokenStream, -) -> (Ident, TokenStream) { - let name = &meta.name; - let visitor = meta.visitor_name(); - - // TODO? if try_from, add: - // - def ReprVisitor - // - def TryFromType - // - `impl Visitor for ReprVisitor` - // - body - // - `impl Visitor for ReprVisitor` - // - body replaced w/ try_from call - // TODO? else: - // - def ReprVisitor - // - `impl Visitor for ReprVisitor` - // - // body = if let Some(try_from_name) = &meta.try_from { - // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); - // let methods = expand_try_from_visitor_methods(body, try_from_ident); - // quote! { - // use ::std::convert::TryFrom; - // // let t = #try_from_ident::deserialize(deserializer)?; - // // Ok(#name::try_from(t).map_err(D::Error::custom)?) - // } - // } else { - // quote! { - // type Value = #name; - // #body - // } - // }; - - let visitor_def = quote! { - struct #visitor; - - #[automatically_derived] - impl<'de> Visitor<'de> for #visitor { - type Value = #name; - fn expecting(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str(#expecting) - } - #body - } - }; - - (visitor, visitor_def) -} - -pub(crate) fn impl_visitor_ext(meta: &SchemaMeta, body: Option) -> TokenStream { - let visitor = meta.visitor_name(); - quote! { - #[automatically_derived] - impl<'de> IpldVisitorExt<'de> for #visitor { - #body - } - } -} - -pub(crate) fn impl_deserialize(meta: &SchemaMeta, mut body: TokenStream) -> TokenStream { - let name = &meta.name; - // let lib = &meta.ipld_schema_lib; - - // body = if let Some(try_from_name) = &meta.try_from { - // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); - // // let methods = expand_try_from_visitor_methods(body, try_from_ident); - // quote! { - // use ::std::convert::TryFrom; - // let t = #try_from_ident::deserialize(deserializer)?; - // Ok(#name::try_from(t).map_err(D::Error::custom)?) - // } - // } else { - // body - // }; - - quote! { - #[automatically_derived] - impl<'de> Deserialize<'de> for #name { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - #body - } - } - } -} +// /// +// pub(crate) fn impl_serialize(meta: &SchemaMeta, body: TokenStream) -> TokenStream { +// let name = &meta.name; +// quote! { +// #[automatically_derived] +// impl Serialize for #name { +// fn serialize(&self, serializer: S) -> Result +// where +// S: Serializer, +// { +// #body +// } +// } +// } +// } +// +// // TODO: for each visitor method, incorporate try_from... +// // - define TryFromType +// // - `impl Visitor for ReprVisitor` +// // - method bodies expanded (should only refer to Self::Value, not #name) +// // - in `impl Visitor for ReprVisitor`, replacing method bodies +// // - call each equiv method on > +// // - handle result with try_from().map_err() call +// pub(crate) fn impl_visitor( +// meta: &SchemaMeta, +// expecting: &'static str, +// body: TokenStream, +// ) -> (Ident, TokenStream) { +// let name = &meta.name; +// let visitor = meta.visitor_name(); +// +// // TODO? if try_from, add: +// // - def ReprVisitor +// // - def TryFromType +// // - `impl Visitor for ReprVisitor` +// // - body +// // - `impl Visitor for ReprVisitor` +// // - body replaced w/ try_from call +// // TODO? else: +// // - def ReprVisitor +// // - `impl Visitor for ReprVisitor` +// // +// // body = if let Some(try_from_name) = &meta.try_from { +// // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); +// // let methods = expand_try_from_visitor_methods(body, try_from_ident); +// // quote! { +// // use ::std::convert::TryFrom; +// // // let t = #try_from_ident::deserialize(deserializer)?; +// // // Ok(#name::try_from(t).map_err(D::Error::custom)?) +// // } +// // } else { +// // quote! { +// // type Value = #name; +// // #body +// // } +// // }; +// +// let visitor_def = quote! { +// struct #visitor; +// #[automatically_derived] +// impl<'de> Visitor<'de> for #visitor { +// type Value = #name; +// fn expecting(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +// fmt.write_str(#expecting) +// } +// #body +// } +// }; +// (visitor, visitor_def) +// } +// +// pub(crate) fn impl_visitor_ext(meta: &SchemaMeta, body: Option) -> TokenStream { +// let visitor = meta.visitor_name(); +// quote! { +// #[automatically_derived] +// impl<'de> IpldVisitorExt<'de> for #visitor { +// #body +// } +// } +// } +// +// pub(crate) fn impl_deserialize(meta: &SchemaMeta, mut body: TokenStream) -> TokenStream { +// let name = &meta.name; +// // let lib = &meta.ipld_schema_lib; +// // body = if let Some(try_from_name) = &meta.try_from { +// // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); +// // // let methods = expand_try_from_visitor_methods(body, try_from_ident); +// // quote! { +// // use ::std::convert::TryFrom; +// // let t = #try_from_ident::deserialize(deserializer)?; +// // Ok(#name::try_from(t).map_err(D::Error::custom)?) +// // } +// // } else { +// // body +// // }; +// +// quote! { +// #[automatically_derived] +// impl<'de> Deserialize<'de> for #name { +// fn deserialize(deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// #body +// } +// } +// } +// } pub(crate) fn impl_repr(meta: &SchemaMeta, consts_and_simple_methods: TokenStream) -> TokenStream { let lib = &meta.lib; diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index be4f5a4..b695116 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -22,7 +22,7 @@ use crate::{common::*, dev::*}; use proc_macro2::{Span, TokenStream}; use proc_macro_crate::{crate_name, FoundCrate}; use quote::quote; -use std::ops::Deref; +use std::ops::{BitOr, Deref}; use syn::{parse_str, Attribute, Generics, Ident, LitStr, Path, Type, Visibility}; /// @@ -135,34 +135,85 @@ impl ReprDefinition { } } -/// -#[derive(Debug, PartialEq, Eq, Hash)] -pub enum SchemaKind { - Null, - Bool, - Int, // same as Int128 - Int8, - Int16, - Int32, - Int64, - Int128, - Uint8, - Uint16, - Uint32, - Uint64, - Uint128, - Float, // same as Float64 - Float32, - Float64, - Bytes, - String, - List, - Map, - Link, - Struct, - Enum, - Union, - Copy, +// /// +// #[derive(Debug, PartialEq, Eq, Hash)] +// pub enum SchemaKind { +// Null, +// Bool, +// Int, // same as Int128 +// Int8, +// Int16, +// Int32, +// Int64, +// Int128, +// Uint8, +// Uint16, +// Uint32, +// Uint64, +// Uint128, +// Float, // same as Float64 +// Float32, +// Float64, +// Bytes, +// String, +// List, +// Map, +// Link, +// Struct, +// Enum, +// Union, +// Copy, +// } +bitflags::bitflags! { + /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. + /// + pub struct SchemaKind: u32 { + // data model kinds + + const Null = 0b0000_0000_0000_0001; + const Bool = 0b0000_0000_0000_0010; + const Int = 0b0000_0000_0000_0100; + + const Float = 0b0000_0000_0000_1000; + const String = 0b0000_0000_0001_0000; + const Bytes = 0b0000_0000_0010_0000; + const List = 0b0000_0000_0100_0000; + const Map = 0b0000_0000_1000_0000; + const Link = 0b0000_0001_0000_0000; + + // schema kinds + + const Struct = 0b0000_0010_0000_0000; + const Enum = 0b0000_0100_0000_0000; + const Union = 0b0000_1000_0000_0000; + const Copy = 0b0001_0000_0000_0000; + + // any + + const Any = Self::Null.bits + | Self::Bool.bits + | Self::Int.bits + | Self::Float.bits + | Self::String.bits + | Self::Bytes.bits + | Self::List.bits + | Self::Map.bits + | Self::Link.bits; + + const Typed = 0b0010_0000_0000_0000; + const Int8 = 0b0100_0000_0000_0000; + const Int16 = 0b1000_0000_0000_0000; + const Int32 = 0b0000_0001_0000_0000_0000_0000; + const Int64 = 0b0000_0010_0000_0000_0000_0000; + const Int128 = 0b0000_0100_0000_0000_0000_0000; + const Uint8 = 0b0000_1000_0000_0000_0000_0000; + const Uint16 = 0b0001_0000_0000_0000_0000_0000; + const Uint32 = 0b0010_0000_0000_0000_0000_0000; + const Uint64 = 0b0100_0000_0000_0000_0000_0000; + const Uint128 = 0b1000_0000_0000_0000_0000_0000; + const Float32 = 0b0000_0001_0000_0000_0000_0000_0000_0000; + const Float64 = 0b0000_0010_0000_0000_0000_0000_0000_0000; + } } // #[derive(Debug)] diff --git a/macros-internals/src/schema/parse.rs b/macros-internals/src/schema/parse.rs index 2f61e7c..62b89d2 100644 --- a/macros-internals/src/schema/parse.rs +++ b/macros-internals/src/schema/parse.rs @@ -118,7 +118,7 @@ impl Parse for ReprDefinition { _ if input.peek(kw::string) => { parse_kw!(input, kw::string => String StringReprDefinition) } - // bytes + // bytes TODO: _ if input.peek(kw::bytes) => { input.parse::()?; Self::Bytes(input.parse::()?) @@ -219,9 +219,7 @@ impl Parse for SchemaKind { _ if input.peek(kw::list) => parse_kw!(input, kw::list => List), _ if input.peek(kw::map) => parse_kw!(input, kw::map => Map), _ if input.peek(kw::link) => parse_kw!(input, kw::link => Link), - _ => Err(input.error( - "invalid IPLD union kinded representation definition: invalid data model kind", - )), + _ => Err(input.error("invalid data model kind")), } } } @@ -258,6 +256,7 @@ pub(crate) fn parse_rest(input: ParseStream) -> ParseResult { Ok(args.parse::()?) } +// TODO: move somewhere else pub(crate) fn parse_stringpair_args(input: ParseStream) -> ParseResult<(LitStr, LitStr)> { let args; braced!(args in input); @@ -289,7 +288,6 @@ fn try_parse_stringpair_args( )); } inner_delim.replace(parse_kwarg!(input, innerDelim => LitStr)); - Ok(()) } else if input.peek(kw::entryDelim) { if entry_delim.is_some() { return Err(input.error( @@ -297,10 +295,9 @@ fn try_parse_stringpair_args( )); } entry_delim.replace(parse_kwarg!(input, entryDelim => LitStr)); - Ok(()) - } else { - Ok(()) } + + Ok(()) } // impl Parse for super::Methods { diff --git a/macros-internals/src/schema/primitive/expand.rs b/macros-internals/src/schema/primitive/expand.rs index 7f74f1b..ee7fe1f 100644 --- a/macros-internals/src/schema/primitive/expand.rs +++ b/macros-internals/src/schema/primitive/expand.rs @@ -86,7 +86,7 @@ impl NullReprDefinition { impl expand::ExpandBasicRepresentation for NullReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); @@ -128,7 +128,7 @@ impl BoolReprDefinition { impl expand::ExpandBasicRepresentation for BoolReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); @@ -152,7 +152,7 @@ impl expand::ExpandBasicRepresentation for BoolReprDefinition { impl expand::ExpandBasicRepresentation for IntReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; @@ -177,7 +177,7 @@ impl expand::ExpandBasicRepresentation for IntReprDefinition { impl expand::ExpandBasicRepresentation for FloatReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; @@ -208,7 +208,7 @@ impl StringReprDefinition { impl expand::ExpandBasicRepresentation for StringReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); @@ -232,7 +232,7 @@ impl expand::ExpandBasicRepresentation for StringReprDefinition { impl expand::ExpandBasicRepresentation for CopyReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@typedef_transparent self, meta => inner_ty) + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; diff --git a/macros-internals/src/schema/primitive/expand_bytes.rs b/macros-internals/src/schema/primitive/expand_bytes.rs index 068390b..38b2cae 100644 --- a/macros-internals/src/schema/primitive/expand_bytes.rs +++ b/macros-internals/src/schema/primitive/expand_bytes.rs @@ -22,7 +22,7 @@ impl BytesReprDefinition { impl expand::ExpandBasicRepresentation for BytesReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_type = self.inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_type) + derive_newtype!(@typedef self, meta => inner_type) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { expand::impl_repr( diff --git a/macros-internals/src/schema/primitive/expand_link.rs b/macros-internals/src/schema/primitive/expand_link.rs index d9f9809..0c2710f 100644 --- a/macros-internals/src/schema/primitive/expand_link.rs +++ b/macros-internals/src/schema/primitive/expand_link.rs @@ -20,7 +20,7 @@ impl LinkReprDefinition { impl expand::ExpandBasicRepresentation for LinkReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_type = self.inner_ty(); - derive_newtype!(@typedef_transparent self, meta => inner_type) + derive_newtype!(@typedef self, meta => inner_type) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { expand::impl_repr( diff --git a/macros-internals/src/schema/struct/expand.rs b/macros-internals/src/schema/struct/expand.rs index e2b2048..eca8011 100644 --- a/macros-internals/src/schema/struct/expand.rs +++ b/macros-internals/src/schema/struct/expand.rs @@ -86,7 +86,7 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { quote! { #(#attrs)* - #[derive(Deserialize, Serialize)] + // #[derive(Deserialize, Serialize)] #vis struct #ident #generics { #(#fields,)* } @@ -110,22 +110,18 @@ pub(super) fn impl_repr<'a>( ) -> TokenStream { let lib = &meta.lib; let name = &meta.name; - let fields: Vec = iter - .map( - |StructField { - key, value, rename, .. - }| { - let key = key.to_string(); - let rename = rename - .as_ref() - .map(|s| s.value()) - .unwrap_or_else(|| key.clone()); - quote! { - (#key, Field::new::<#value>(#rename)) - } - }, - ) - .collect(); + // let fields = iter.map(|f| { + // let key = f.key.to_string(); + // let val = &f.value; + // let rename = f + // .rename + // .as_ref() + // .map(|s| s.value()) + // .unwrap_or_else(|| key.clone()); + // quote! { + // (#key, Field::new::<#val>(#rename)) + // } + // }); let repr_body = expand::impl_repr( meta, @@ -144,11 +140,12 @@ pub(crate) fn default_field_def(field: &StructField) -> TokenStream { let attrs = &field.attrs; let vis = &field.vis; let key = &field.key; - let value = super::expand::field_value(field); + let value = field_value(field); + let generics = &field.generics; quote! { #(#attrs)* - #vis #key: #value + #vis #key: #value #generics } } @@ -157,7 +154,7 @@ fn field_def(field: &StructField) -> TokenStream { let vis = &field.vis; let key = &field.key; let value = field_value(field); - let generics = field.generics.as_ref().map(|g| quote!(#g)); + let generics = &field.generics; let implicit_attr = field.implicit.as_ref().map(|_| quote!(#[serde(default)])); let rename_attr = field @@ -167,8 +164,8 @@ fn field_def(field: &StructField) -> TokenStream { quote! { #(#attrs)* - #implicit_attr - #rename_attr + // #implicit_attr + // #rename_attr #vis #key: #value #generics } } diff --git a/macros-internals/src/schema/union/expand.rs b/macros-internals/src/schema/union/expand.rs index 5f1a619..2552720 100644 --- a/macros-internals/src/schema/union/expand.rs +++ b/macros-internals/src/schema/union/expand.rs @@ -8,17 +8,59 @@ use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{Ident, Type}; +impl ExpandBasicRepresentation for UnionReprDefinition { + fn define_type(&self, meta: &SchemaMeta) -> TokenStream { + match self { + Self::Keyed(def) => def.define_type(meta), + // Self::Envelope(def) => def.define_type(meta), + // Self::Inline(def) => def.define_type(meta), + // Self::BytePrefix(def) => def.define_type(meta), + Self::Kinded(def) => def.define_type(meta), + _ => unimplemented!(), + } + } + fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + match self { + Self::Keyed(def) => def.derive_repr(meta), + // Self::Envelope(def) => def.derive_repr(meta), + // Self::Inline(def) => def.derive_repr(meta), + // Self::BytePrefix(def) => def.derive_repr(meta), + Self::Kinded(def) => def.derive_repr(meta), + _ => unimplemented!(), + } + } + fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { + match self { + Self::Keyed(def) => def.derive_select(meta), + // Self::Envelope(def) => def.derive_select(meta), + // Self::Inline(def) => def.derive_select(meta), + // Self::BytePrefix(def) => def.derive_select(meta), + Self::Kinded(def) => def.derive_select(meta), + _ => unimplemented!(), + } + } + fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { + match self { + Self::Keyed(def) => def.derive_conv(meta), + // Self::Envelope(def) => def.derive_conv(meta), + // Self::Inline(def) => def.derive_conv(meta), + // Self::BytePrefix(def) => def.derive_conv(meta), + Self::Kinded(def) => def.derive_conv(meta), + _ => unimplemented!(), + } + } +} + impl ExpandBasicRepresentation for KeyedUnionReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { - let lib = &meta.lib; let attrs = &meta.attrs; let vis = &meta.vis; let ident = &meta.name; - let fields = self.iter().map(UnionField::::field_typedef); + let fields = self.iter().map(UnionStrField::field_typedef); quote! { #(#attrs)* - #[derive(Deserialize, Serialize)] + // #[derive(Deserialize, Serialize)] #vis enum #ident { #(#fields,)* } @@ -26,9 +68,11 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let lib = &meta.lib; - let name_branches = self.iter().map(UnionField::::name_branch); - let kind_branches = self.iter().map(UnionField::::kind_branch); - let link_branches = self.iter().map(UnionField::::link_branch); + let name_branches = self.iter().map(UnionStrField::name_branch); + let kind_branches = self.iter().map(UnionStrField::kind_branch); + let link_branches = self.iter().map(UnionStrField::link_branch); + let serialize_branches = self.iter().map(UnionStrField::serialize_branch); + // let deserialize_branches = self.iter().map(UnionStrField::deserialize_branch); expand::impl_repr( meta, quote! { @@ -57,6 +101,25 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { #(#link_branches,)* } } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // match self { + // #(#serialize_branches,)* + // } + unimplemented!() + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + unimplemented!() + } }, ) } @@ -88,7 +151,6 @@ impl UnionField { let key = &self.key; let generics = &self.generics; - let rename_attr = quote!(#[serde(rename = #key)]); let field_name: Ident = self.field_name(); let ty: TokenStream = if let Some(wrapper_type) = &self.wrapper { @@ -99,7 +161,7 @@ impl UnionField { quote! { #(#attrs)* - #rename_attr + // #[serde(rename = #key)] #field_name(#ty) } } @@ -118,47 +180,17 @@ impl UnionField { let field_name = self.field_name(); quote!(Self::#field_name(inner) => Representation::has_links(inner)) } -} -impl ExpandBasicRepresentation for UnionReprDefinition { - fn define_type(&self, meta: &SchemaMeta) -> TokenStream { - match self { - Self::Keyed(def) => def.define_type(meta), - // Self::Envelope(def) => def.define_type(meta), - // Self::Inline(def) => def.define_type(meta), - // Self::BytePrefix(def) => def.define_type(meta), - Self::Kinded(def) => def.define_type(meta), - _ => unimplemented!(), - } - } - fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - match self { - Self::Keyed(def) => def.derive_repr(meta), - // Self::Envelope(def) => def.derive_repr(meta), - // Self::Inline(def) => def.derive_repr(meta), - // Self::BytePrefix(def) => def.derive_repr(meta), - Self::Kinded(def) => def.derive_repr(meta), - _ => unimplemented!(), - } - } - fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { - match self { - Self::Keyed(def) => def.derive_select(meta), - // Self::Envelope(def) => def.derive_select(meta), - // Self::Inline(def) => def.derive_select(meta), - // Self::BytePrefix(def) => def.derive_select(meta), - Self::Kinded(def) => def.derive_select(meta), - _ => unimplemented!(), - } - } - fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - match self { - Self::Keyed(def) => def.derive_conv(meta), - // Self::Envelope(def) => def.derive_conv(meta), - // Self::Inline(def) => def.derive_conv(meta), - // Self::BytePrefix(def) => def.derive_conv(meta), - Self::Kinded(def) => def.derive_conv(meta), - _ => unimplemented!(), - } + fn serialize_branch(&self) -> TokenStream { + let field_name = self.field_name(); + let repr_field_name = &self.key; + // let ty = &self.value; + quote!(Self::#field_name(ty) => { + use serde::ser::SerializeTupleVariant; + + let mut tv = serializer.serialize_tuple_variant("", 0, #repr_field_name, 1)?; + tv.serialize_field(&SerializeWrapper(&ty))?; + tv.end() + }) } } diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index ab4ad9f..0537755 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -14,14 +14,14 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { let attrs = &meta.attrs; let vis = &meta.vis; let name = &meta.name; - let fields = self.iter().map(UnionField::::typedef); + let fields = self.iter().map(UnionKindedField::typedef); // TODO: assert that all nested REPR_KINDs are unique and are DM kinds quote! { #(#attrs)* - #[derive(Deserialize, Serialize)] - #[serde(untagged)] + // #[derive(Deserialize, Serialize)] + // #[serde(untagged)] #vis enum #name { #(#fields,)* } @@ -31,8 +31,10 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let dm_kind = self.dm_kind(); let repr_kind = self.repr_kind(); - let name_branches = self.iter().map(UnionField::::name_branch); + let name_branches = self.iter().map(UnionKindedField::name_branch); // let kind_branches: Vec = self.iter().map(|f| f.kind_branch(&lib)).collect(); + let serialize_branches = self.iter().map(UnionKindedField::serialize_branch); + // let deserialize_branches = self.iter().map(UnionKindedField::deserialize_branch); expand::impl_repr( meta, @@ -55,6 +57,24 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { // #(#kind_branches,)* // } // } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + #(#serialize_branches,)* + } + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + unimplemented!() + } }, ) } @@ -145,46 +165,11 @@ impl KindedUnionReprDefinition { } } -impl UnionField { - const NULL: &'static str = "Null"; - const BOOL: &'static str = "Bool"; - const INT: &'static str = "Int"; - // const INT8: &'static str = "Int8"; - // const INT16: &'static str = "Int16"; - // const INT32: &'static str = "In32t"; - // const INT64: &'static str = "Int64"; - // const INT128: &'static str = "Int128"; - // const UINT8: &'static str = "Uint8"; - // const UINT16: &'static str = "Uint16"; - // const UINT32: &'static str = "Uint32"; - // const UINT64: &'static str = "Uint64"; - // const UINT128: &'static str = "Uint128"; - const FLOAT: &'static str = "Float"; - // const FLOAT32: &'static str = "Float32"; - // const FLOAT64: &'static str = "Float64"; - const BYTES: &'static str = "Bytes"; - const STRING: &'static str = "String"; - const LIST: &'static str = "List"; - const MAP: &'static str = "Map"; - const LINK: &'static str = "Link"; - +impl UnionKindedField { /// Outputs the kinded enum variant name. /// TODO: this is wrong, let users define the name and just check the repr_kind - fn name(&self) -> Ident { - let name = match self.key { - SchemaKind::Null => Self::NULL, - SchemaKind::Bool => Self::BOOL, - SchemaKind::Int => Self::INT, - SchemaKind::Float => Self::FLOAT, - SchemaKind::Bytes => Self::BYTES, - SchemaKind::String => Self::STRING, - SchemaKind::List => Self::LIST, - SchemaKind::Map => Self::MAP, - SchemaKind::Link => Self::LINK, - _ => unreachable!(), - }; - - Ident::new(name, Span::call_site()) + fn name(&self) -> &Ident { + &self.value } fn dm_kind(&self) -> TokenStream { @@ -262,11 +247,17 @@ impl UnionField { let name = self.name(); quote!(Self::#name(ty) => Representation::repr_kind(ty)) } + + fn serialize_branch(&self) -> TokenStream { + let name = self.name(); + // let ty = &self.value; + quote!(Self::#name(ty) => Representation::serialize::(ty, serializer)) + } } -impl UnionField { +impl UnionKindedField { fn visit_params(&self) -> Vec<(TokenStream, TokenStream)> { - match &self.key { + match self.key { SchemaKind::Null => vec![ (quote!(visit_unit), quote!()), (quote!(visit_none), quote!()), @@ -299,8 +290,9 @@ impl UnionField { SchemaKind::List => vec![(quote!(visit_seq), quote!(v: A))], SchemaKind::Map => vec![(quote!(visit_map), quote!(v: A))], SchemaKind::Link => vec![ - (quote!(visit_link_bytes), quote!(v: &[u8])), - (quote!(visit_link_str), quote!(v: &str)), + // (quote!(visit_link_bytes), quote!(v: &[u8])), + // (quote!(visit_link_str), quote!(v: &str)), + (quote!(visit_cid), quote!(v: Cid)), ], _ => unreachable!(), } @@ -312,7 +304,7 @@ impl UnionField { let field_name = self.name(); let ty = self.ty(false); let visit_impl = { - let deserializer = match &self.key { + let deserializer = match self.key { SchemaKind::Null => quote!(().into_deserializer()), SchemaKind::Bytes => quote!(serde::de::value::BytesDeserializer::new(&v)), SchemaKind::List => quote!(serde::de::value::SeqAccessDeserializer::::new(v)), diff --git a/macros-internals/src/schema/union/mod.rs b/macros-internals/src/schema/union/mod.rs index bb7f625..926f4e9 100644 --- a/macros-internals/src/schema/union/mod.rs +++ b/macros-internals/src/schema/union/mod.rs @@ -64,9 +64,12 @@ deref! { Kinded, SchemaKind => KindedUnionReprDefinition, } -pub type UnionStrFields = Fields>; -pub type UnionIntFields = Fields>; -pub type UnionKindedFields = Fields>; +pub type UnionStrField = UnionField; +pub type UnionIntField = UnionField; +pub type UnionKindedField = UnionField; +pub type UnionStrFields = Fields; +pub type UnionIntFields = Fields; +pub type UnionKindedFields = Fields; #[derive(Debug)] pub struct UnionField { diff --git a/macros-internals/src/schema/union/parse.rs b/macros-internals/src/schema/union/parse.rs index 644ba84..c8b09a2 100644 --- a/macros-internals/src/schema/union/parse.rs +++ b/macros-internals/src/schema/union/parse.rs @@ -6,7 +6,6 @@ use crate::dev::{ schema::{kw, SchemaKind}, OuterAttributes, }; -use std::collections::HashSet; use syn::{ braced, parse::{Parse, ParseStream, Result as ParseResult}, @@ -23,13 +22,13 @@ impl Parse for UnionReprDefinition { // keyed _ if input.peek(kw::keyed) => { input.parse::()?; - let fields = field_input.parse::()?; + let fields = field_input.parse()?; Self::Keyed(KeyedUnionReprDefinition { fields }) } // envelope _ if input.peek(kw::envelope) => { input.parse::()?; - let fields = field_input.parse::()?; + let fields = field_input.parse()?; let args; braced!(args in input); @@ -37,10 +36,12 @@ impl Parse for UnionReprDefinition { let mut content_key = None; try_parse_envelope_args(&args, &mut discriminant_key, &mut content_key)?; try_parse_envelope_args(&args, &mut discriminant_key, &mut content_key)?; - let discriminant_key = discriminant_key.ok_or(args.error("invalid IPLD union envelope representation definition: missing `discriminantKey`"))?; - let content_key = content_key.ok_or(args.error( - "invalid IPLD union envelope representation definition: missing `contentKey`", + let discriminant_key = discriminant_key.ok_or(args.error( + "invalid IPLD union envelope representation: missing `discriminantKey`", ))?; + let content_key = content_key.ok_or( + args.error("invalid IPLD union envelope representation: missing `contentKey`"), + )?; Self::Envelope(EnvelopeUnionReprDefinition { fields, discriminant_key, @@ -50,7 +51,7 @@ impl Parse for UnionReprDefinition { // inline _ if input.peek(kw::inline) => { input.parse::()?; - let fields = field_input.parse::()?; + let fields = field_input.parse()?; let args; braced!(args in input); let discriminant_key = parse_kwarg!(args, discriminantKey => LitStr); @@ -62,28 +63,32 @@ impl Parse for UnionReprDefinition { // byteprefix _ if input.peek(kw::byteprefix) => { input.parse::()?; - let fields = field_input.parse::()?; + let fields = field_input.parse()?; Self::BytePrefix(BytePrefixUnionReprDefinition { fields }) } // kinded _ if input.peek(kw::kinded) => { input.parse::()?; let fields = field_input.parse::()?; - let all_unique_kinds = { - let set = &fields - .iter() - .map(|field| &field.key) - .collect::>(); - fields.len() == set.len() - }; - if !all_unique_kinds { + + // validate that all the kinds are of the data model and unique + let all = &fields + .iter() + .map(|fs| fs.key) + .fold(SchemaKind::empty(), SchemaKind::union); + if !SchemaKind::Any.contains(*all) { return Err(input.error( - "invalid IPLD union kinded representation defintion: duplicate kinds", + "invalid IPLD union kinded representation: schema contains non-data model types", )); } + if fields.len() != all.bits.count_ones() as usize { + return Err(input + .error("invalid IPLD union kinded representation: schema contains duplicate type fields")); + } + Self::Kinded(KindedUnionReprDefinition { fields }) } - _ => return Err(input.error("invalid IPLD union representation definition")), + _ => return Err(input.error("invalid IPLD union representation")), }; Ok(union_repr) @@ -126,23 +131,20 @@ pub(crate) fn try_parse_envelope_args( ) -> ParseResult<()> { if input.peek(kw::discriminantKey) { if discriminant_key.is_some() { - return Err(input.error( - "invalid IPLD union envelope representation defintion: duplicate `discriminantKey`", - )); + return Err(input + .error("invalid IPLD union envelope representation: duplicate `discriminantKey`")); } - *discriminant_key = Some(parse_kwarg!(input, discriminantKey => LitStr)); - Ok(()) + discriminant_key.replace(parse_kwarg!(input, discriminantKey => LitStr)); } else if input.peek(kw::contentKey) { if content_key.is_some() { - return Err(input.error( - "invalid IPLD union envelope representation defintion: duplicate `contentKey`", - )); + return Err( + input.error("invalid IPLD union envelope representation: duplicate `contentKey`") + ); } - *content_key = Some(parse_kwarg!(input, contentKey => LitStr)); - Ok(()) - } else { - Ok(()) + content_key.replace(parse_kwarg!(input, contentKey => LitStr)); } + + Ok(()) } // #[cfg(test)] diff --git a/src/cid.rs b/src/cid.rs index a3cdb2d..1938683 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -171,14 +171,14 @@ impl Representation for Cid { cfg_if::cfg_if! { if #[cfg(feature = "dag-json")] { if C == DagJson::CODE { - return DagJson::serialize_link(self, serializer); + return DagJson::serialize_cid(self, serializer); } } } cfg_if::cfg_if! { if #[cfg(feature = "dag-cbor")] { if C == DagCbor::CODE { - return DagCbor::serialize_link(self, serializer); + return DagCbor::serialize_cid(self, serializer); } } } @@ -195,14 +195,14 @@ impl Representation for Cid { cfg_if::cfg_if! { if #[cfg(feature = "dag-json")] { if C == DagJson::CODE { - return DagJson::deserialize_link(deserializer, CidVisitor); + return DagJson::deserialize_cid(deserializer, CidVisitor); } } } cfg_if::cfg_if! { if #[cfg(feature = "dag-cbor")] { if C == DagCbor::CODE { - return DagCbor::deserialize_link(deserializer, CidVisitor); + return DagCbor::deserialize_cid(deserializer, CidVisitor); } } } @@ -365,35 +365,14 @@ impl<'de> Visitor<'de> for CidVisitor { Cid::SIZE ) } - // #[inline] - // fn visit_str(self, s: &str) -> Result - // where - // E: de::Error, - // { - // self.visit_link_str(s) - // } - // #[inline] - // fn visit_bytes(self, bytes: &[u8]) -> Result - // where - // E: de::Error, - // { - // self.visit_link_bytes(bytes) - // } } impl<'de> IpldVisitorExt<'de> for CidVisitor { #[inline] - fn visit_link_str(self, cid_str: &str) -> Result + fn visit_cid(self, cid: Cid) -> Result where E: de::Error, { - Self::Value::try_from(cid_str).map_err(E::custom) - } - #[inline] - fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result - where - E: de::Error, - { - Self::Value::try_from(cid_bytes).map_err(E::custom) + Ok(cid) } } @@ -402,41 +381,6 @@ impl<'de> Deserialize<'de> for Cid { where D: Deserializer<'de>, { - // struct CidVisitor; - // impl<'de> Visitor<'de> for CidVisitor { - // type Value = Cid; - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "a Cid of a multihash no longer than {} bytes", Cid::SIZE) - // } - // } - // impl<'de> IpldVisitorExt<'de> for CidVisitor { - // #[inline] - // fn visit_link_str(self, cid_str: &str) -> Result - // where - // E: de::Error, - // { - // Self::Value::try_from(cid_str).map_err(E::custom) - // } - // #[inline] - // fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result - // where - // E: de::Error, - // { - // Self::Value::try_from(cid_bytes).map_err(E::custom) - // } - // } - - // cfg_if::cfg_if! { - // if #[cfg(feature = "serde-codec")] { - // (&mut &mut &mut Decoder(deserializer)).deserialize_link(CidVisitor) - // } else { - // Ok(Self::from(DefaultCid::deserialize(deserializer)?)) - // } - // } - - // deserializer.deserialize_link(CidVisitor) - Ok(Self::from(DefaultCid::deserialize(deserializer)?)) } } diff --git a/src/codecs/dag_cbor.rs b/src/codecs/dag_cbor.rs index 1597335..404fb0e 100644 --- a/src/codecs/dag_cbor.rs +++ b/src/codecs/dag_cbor.rs @@ -1,17 +1,27 @@ //! IPLD DagCbor codec. use crate::dev::*; -use serde::de; use serde_cbor::{ - de::{IoRead, Read as CborRead, SliceRead}, - ser::{IoWrite, Write as CborWrite}, + de::{IoRead, SliceRead}, + ser::IoWrite, tags::Tagged, - Deserializer as CborDeserializer, Error as CborError, Serializer as CborSerializer, + Deserializer as CborDeserializer, Serializer as CborSerializer, }; +// use cbor4ii::{ +// core::{ +// dec::{Decode, Read as CborRead}, +// enc::{Encode, Write as CborWrite}, +// types::{Bytes as CborBytes, Tag}, +// utils::{BufWriter, IoReader, IoWriter, SliceReader}, +// }, +// serde::{Deserializer as CborDeserializer, Serializer as CborSerializer}, +// }; +use delegate::delegate; use std::{ + borrow::Cow, convert::TryFrom, fmt, - io::{Read, Write}, + io::{BufReader, Read, Write}, }; /// The [DagCBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) codec, that delegates to `serde_cbor`. @@ -33,11 +43,12 @@ impl DagCbor { /// #[inline] - pub(crate) fn serialize_link( + pub(crate) fn serialize_cid( cid: &Cid, serializer: S, ) -> Result { Tagged::new(Some(Self::LINK_TAG), &cid.to_bytes()).serialize(serializer) + // EncodableCid(cid).serialize(serializer) } /// @@ -51,13 +62,13 @@ impl DagCbor { D: Deserializer<'de>, V: IpldVisitorExt<'de>, { - // deserializer.deserialize_any(visitor::DagJsonVisitor::<'a', _>(visitor)) + // deserializer.deserialize_any(DagCborVisitor::<'a', _>(visitor)) unimplemented!() } /// #[inline] - pub(crate) fn deserialize_link<'de, D, V>( + pub(crate) fn deserialize_cid<'de, D, V>( deserializer: D, visitor: V, ) -> Result @@ -76,17 +87,61 @@ impl DagCbor { ))), _ => Err(D::Error::custom("expected a Cid")), } + + // deserializer.deserialize_bytes(DagCborVisitor::<'l', _>(visitor)) } - pub(crate) fn read_with_seed<'de, S, R>(&mut self, seed: S, reader: R) -> Result<(), Error> + #[doc(hidden)] + #[inline] + pub fn read_from_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> where - S: CodecDeserializeSeed<'de>, + Ctx: Context, + T: Select, R: Read, { let mut de = CborDeserializer::from_reader(reader); - seed.deserialize::<{ Self::CODE }, _>(&mut de) - .map_err(Error::decoder) + T::__select_from_deserializer::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) } + + // pub(crate) fn deserializer_from_reader( + // &mut self, + // reader: R, + // ) -> CborDeserializer> { + // CborDeserializer::from_reader(reader) + // } + + // pub(crate) fn read_with_seed<'de, S, R>( + // &mut self, + // seed: S, + // reader: R, + // ) -> Result + // where + // S: CodecDeserializeSeed<'de>, + // R: Read, + // { + // let mut de = CborDeserializer::from_reader(reader); + // // let mut de = CborDeserializer::new(IoReader::new(BufReader::new(reader))); + // seed.deserialize::<{ Self::CODE }, _>(&mut de) + // .map_err(Error::decoder) + // } + + // pub(crate) fn read_with_seed<'de, const D: bool, T, R>( + // &mut self, + // seed: T, + // reader: R, + // ) -> Result< as DeserializeSeed<'de>>::Value, Error> + // where + // // S: CodecDeserializeSeed<'de>, + // CodecSeed<{ Self::CODE }, D, T>: DeserializeSeed<'de>, + // R: Read, + // { + // let mut de = CborDeserializer::from_reader(reader); + // // seed.deserialize::<{ Self::CODE }, _>(&mut de) + // // .map_err(Error::decoder) + // CodecSeed::<{ Self::CODE }, D, T>(seed) + // .deserialize(&mut de) + // .map_err(Error::decoder) + // } } impl Codec for DagCbor { @@ -96,6 +151,7 @@ impl Codec for DagCbor { W: Write, { let mut ser = CborSerializer::new(IoWrite::new(writer)); + // let mut ser = CborSerializer::new(IoWriter::new(writer)); Representation::serialize::<{ Self::CODE }, _>(dag, &mut ser).map_err(Error::encoder) } @@ -104,6 +160,7 @@ impl Codec for DagCbor { T: Representation, { let mut de = CborDeserializer::new(SliceRead::new(bytes)); + // let mut de = CborDeserializer::new(SliceReader::new(bytes)); Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) } @@ -113,6 +170,7 @@ impl Codec for DagCbor { R: Read, { let mut de = CborDeserializer::new(IoRead::new(reader)); + // let mut de = CborDeserializer::new(IoReader::new(BufReader::new(reader))); Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) } } @@ -127,19 +185,176 @@ impl TryFrom for DagCbor { } } +// mod visitor { +// use super::*; + +// pub struct DagCborVisitor(V); +// impl<'de> Visitor<'de> for DagCborVisitor<'a', V> +// } + +#[cfg(feature = "cbor4ii")] +use tag::*; +#[cfg(feature = "cbor4ii")] +mod tag { + use super::*; + + // add a null byte to the cid bytes + impl Encode for &Cid { + fn encode( + &self, + writer: &mut W, + ) -> Result<(), cbor4ii::EncodeError> { + writer.push(&[0x00])?; + writer.push(&self.to_bytes())?; + Ok(()) + } + } + + pub struct EncodableCid<'a>(pub &'a Cid); + impl<'a> Serialize for EncodableCid<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut bytes = BufWriter::new(Vec::with_capacity(Cid::SIZE + 8)); + Tag(DagCbor::LINK_TAG, self.0) + .encode(&mut bytes) + .map_err(S::Error::custom)?; + + serializer.serialize_bytes(bytes.buffer()) + } + } + + pub struct DagCborVisitor(pub V); + + // visitor for any + // impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagCborVisitor<'a', V> { + // type Value = V::Value; + // #[inline] + // fn visit_bytes(self, v: &[u8]) -> Result + // where + // E: de::Error, + // { + // let tagged_bytes = + // Tag::>::decode(&mut SliceReader::new(v)).map_err(E::custom)?; + // match tagged_bytes { + // // remove the first byte + // Tag(DagCbor::CODE, CborBytes(cid_bytes)) => { + // self.0.visit_link_bytes(&cid_bytes[1..]) + // } + // Tag(tag, _) => Err(E::custom(format!("unexpected CBOR tag for Cid: {}", tag))), + // _ => Err(E::custom("expected tagged bytes for a Cid")), + // } + // } + // // Some of these are not expected to be called, since the only data model + // // mis-match exists between Serde maps and IPLD maps. + // delegate! { + // to self.0 { + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; + // fn visit_bool(self, v: bool) -> Result; + // fn visit_i8(self, v: i8) -> Result; + // fn visit_i16(self, v: i16) -> Result; + // fn visit_i32(self, v: i32) -> Result; + // fn visit_i64(self, v: i64) -> Result; + // fn visit_i128(self, v: i128) -> Result; + // fn visit_u8(self, v: u8) -> Result; + // fn visit_u16(self, v: u16) -> Result; + // fn visit_u32(self, v: u32) -> Result; + // fn visit_u64(self, v: u64) -> Result; + // fn visit_u128(self, v: u128) -> Result; + // fn visit_f32(self, v: f32) -> Result; + // fn visit_f64(self, v: f64) -> Result; + // fn visit_char(self, v: char) -> Result; + // fn visit_str(self, v: &str) -> Result; + // fn visit_borrowed_str(self, v: &'de str) -> Result; + // fn visit_string(self, v: String) -> Result; + // fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result; + // fn visit_byte_buf(self, v: Vec) -> Result; + // fn visit_none(self) -> Result; + // fn visit_some>(self, deserializer: D) -> Result; + // fn visit_unit(self) -> Result; + // fn visit_newtype_struct>( + // self, + // deserializer: D + // ) -> Result; + // fn visit_seq>(self, seq: A) -> Result; + // fn visit_map>(self, mut map: A) -> Result; + // fn visit_enum>(self, data: A) -> Result; + // } + // } + // } + + // visitor for links + // TODO: does not work, as Cids are tagged differently than bytes + impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagCborVisitor<'l', V> { + type Value = V::Value; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A tagged Cid") + } + #[inline] + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + // TODO: use dec::Reference? + let tagged_bytes = + Tag::>::decode(&mut SliceReader::new(v)).map_err(E::custom)?; + match tagged_bytes { + // remove the first byte + Tag(DagCbor::CODE, CborBytes(cid_bytes)) => { + self.0.visit_link_bytes(&cid_bytes[1..]) + } + Tag(tag, _) => Err(E::custom(format!("unexpected CBOR tag for Cid: {}", tag))), + _ => Err(E::custom("expected tagged bytes for a Cid")), + } + } + } +} + #[cfg(test)] mod tests { + use crate::{codecs_::test_utils::*, prelude::*}; + #[test] - fn test_null() {} + fn test_null() { + // let tests = &[(Null, "null")]; + // roundtrip_bytes_codec::(DagJson::CODE, tests); + } #[test] fn test_bool() {} #[test] - fn test_number() {} + fn test_number() { + // ints + // // u8 + // let vec = to_vec(&24).unwrap(); + // assert_eq!(vec, b"\x18\x18"); + // // i8 + // let vec = to_vec(&-5).unwrap(); + // assert_eq!(vec, b"\x24"); + // // i16 + // let vec = to_vec(&-300).unwrap(); + // assert_eq!(vec, b"\x39\x01\x2b"); + // // i32 + // let vec = to_vec(&-23567997).unwrap(); + // assert_eq!(vec, b"\x3a\x01\x67\x9e\x7c"); + // // u64 + // let vec = to_vec(&::std::u64::MAX).unwrap(); + // assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); + + // floats + let cases = &[(4000.5f32, b"\xfb\x40\xaf\x41\x00\x00\x00\x00\x00".as_ref())]; + roundtrip_bytes_codec::(DagCbor::CODE, cases); + let cases = &[(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a".as_ref())]; + roundtrip_bytes_codec::(DagCbor::CODE, cases); + } #[test] - fn test_string() {} + fn test_string() { + let cases = &[(IpldString::from("foobar"), b"ffoobar".as_ref())]; + roundtrip_bytes_codec::(DagCbor::CODE, cases); + } #[test] fn test_bytes() {} @@ -148,7 +363,10 @@ mod tests { fn test_link() {} #[test] - fn test_seq() {} + fn test_seq() { + let cases = &[(vec![1, 2, 3], b"\x83\x01\x02\x03".as_ref())]; + roundtrip_bytes_codec::>(DagCbor::CODE, cases) + } #[test] fn test_map() {} diff --git a/src/codecs/dag_cose.rs b/src/codecs/dag_cose.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/codecs/dag_jose.rs b/src/codecs/dag_jose.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index d0d06ba..82de253 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -1,14 +1,10 @@ //! IPLD DagJson codec. -use crate::dev::{macros::derive_more::Unwrap, *}; +use crate::dev::*; use delegate::delegate; use serde::{de, ser}; -use serde_json::de::IoRead; #[cfg(not(feature = "simd"))] -use serde_json::{ - de::Read as JsonRead, from_reader, from_slice, to_writer, Deserializer as JsonDeserializer, - Error as JsonError, Serializer as JsonSerializer, -}; +use serde_json::{de::IoRead, Deserializer as JsonDeserializer, Serializer as JsonSerializer}; // #[cfg(feature = "simd")] // use simd_json::{Serializer as JsonSerializer, Deserializer as JsonDeserializer, Error as JsonError}; use std::{ @@ -57,7 +53,7 @@ impl DagJson { /// Serializes links as a newtype variant, e.g. `{ "/": "Qm..." }`. #[inline] - pub(crate) fn serialize_link( + pub(crate) fn serialize_cid( cid: &Cid, serializer: S, ) -> Result { @@ -94,7 +90,7 @@ impl DagJson { /// #[inline] - pub(crate) fn deserialize_link<'de, D, V>( + pub(crate) fn deserialize_cid<'de, D, V>( deserializer: D, visitor: V, ) -> Result @@ -105,14 +101,16 @@ impl DagJson { deserializer.deserialize_map(visitor::DagJsonVisitor::<'l', _>(visitor)) } - pub(crate) fn read_with_seed<'de, S, R>(&mut self, seed: S, reader: R) -> Result<(), Error> + #[doc(hidden)] + #[inline] + pub fn read_from_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> where - S: CodecDeserializeSeed<'de>, + Ctx: Context, + T: Select, R: Read, { let mut de = JsonDeserializer::from_reader(reader); - seed.deserialize::<{ Self::CODE }, _>(&mut de) - .map_err(Error::decoder) + T::__select_from_deserializer::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) } } @@ -158,7 +156,7 @@ mod visitor { use super::*; #[derive(Debug)] - pub(crate) struct DagJsonVisitor(pub(crate) V); + pub(crate) struct DagJsonVisitor(pub(crate) V); // visitor for any impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagJsonVisitor<'a', V> { @@ -345,8 +343,8 @@ mod visitor { A::Error::custom("DagJSON bytes key must be the string \"bytes\"") })?; - // TODO: empty string - let byte_str = map.next_value::()?; + let byte_str = map + .next_value_seed(DeserializeWrapper::<{ DagJson::CODE }, IpldString>::default())?; match multibase::decode(byte_str) { Ok((DagJson::DEFAULT_MULTIBASE, bytes)) => Ok(MapLikeVisitor::Bytes(bytes)), // Ok((mb, _)) => Err(de::Error::custom(format!( @@ -400,44 +398,49 @@ mod tests { #[test] fn test_null() { - let tests = &[(Null, "null")]; - roundtrip_str_codec::(DagJson::CODE, tests); - let tests = &[(None as Option, "null")]; - roundtrip_str_codec::>(DagJson::CODE, tests); + let cases = &[(Null, "null")]; + roundtrip_str_codec::(DagJson::CODE, cases); + let cases = &[(None as Option, "null")]; + roundtrip_str_codec::>(DagJson::CODE, cases); } #[test] fn test_bool() { - let tests = &[(true, "true"), (false, "false")]; - roundtrip_str_codec::(DagJson::CODE, tests); + let cases = &[(true, "true"), (false, "false")]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_number() { - let tests = &[(123, "123"), (65535, "65535")]; - roundtrip_str_codec::(DagJson::CODE, tests); - let tests = &[(123.123, "123.123")]; - roundtrip_str_codec::(DagJson::CODE, tests); + // ints + let cases = &[(123, "123"), (65535, "65535")]; + roundtrip_str_codec::(DagJson::CODE, cases); + + // floats + let cases = &[(123.123, "123.123")]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_string() { - let tests = &[ + let cases = &[ // standard string (IpldString::from("hello world"), "\"hello world\""), + // empty string TODO: + // (IpldString::default(), "\"\""), // non-standard UTF-8 string TODO: // (IpldString::from("ÅΩ"), "\"ÅΩ\""), ]; - roundtrip_str_codec::<_>(DagJson::CODE, tests); + roundtrip_str_codec::<_>(DagJson::CODE, cases); } #[test] fn test_bytes() { - let tests = &[( + let cases = &[( Bytes::from(vec![0x01, 0x02, 0x03]), r#"{"/":{"bytes":"mAQID"}}"#, )]; - roundtrip_str_codec::(DagJson::CODE, tests); + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] @@ -447,16 +450,16 @@ mod tests { let s = String::from("QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"); let json = format!("{{\"/\":\"{}\"}}", s); - let tests = &[( + let cases = &[( TestLink::from(Cid::try_from(s.as_str()).unwrap()), json.as_str(), )]; - roundtrip_str_codec::(DagJson::CODE, tests); + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_seq() { - let tests = &[ + let cases = &[ // (vec![], "[]"), // (vec![Any::Int(1), Any::Int(2)], "[1,2]"), // // ( @@ -464,12 +467,12 @@ mod tests { // // "[{\"/\": }]", // // ), ]; - roundtrip_str_codec::(DagJson::CODE, tests); + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_map() { - let tests = &[]; - roundtrip_str_codec::(DagJson::CODE, tests); + let cases = &[]; + roundtrip_str_codec::(DagJson::CODE, cases); } } diff --git a/src/codecs/dag_pb.rs b/src/codecs/dag_pb.rs deleted file mode 100644 index 156d826..0000000 --- a/src/codecs/dag_pb.rs +++ /dev/null @@ -1,124 +0,0 @@ -use crate::dev::*; -use std::convert::TryFrom; - -/// -#[derive(Debug)] -pub struct DagPb; - -// schema! { -// #[ipld_attr(internal)] -// #[derive(Clone, Debug)] -// pub type DagPbNode struct { -// Links [DabPbLink], -// Data optional Bytes -// } -// } - -schema! { - #[ipld_attr(internal)] - #[derive(Clone, Debug)] - pub type DagPbLink struct { - Hash Link, - Name optional String, - Tsize optional Int, - }; -} - -// pub struct DagPbNode { -// data: &'a [u8], -// links: Vec, -// serializedSize: usize, -// size: usize, -// } - -// pub struct DagPbLink { -// name: String, -// size: usize, -// cid: Cid, -// } - -impl DagPb { - pub const CODE: u64 = 0x70; -} - -impl Into for DagPb { - fn into(self) -> u64 { - Self::CODE - } -} - -impl TryFrom for DagPb { - type Error = Error; - fn try_from(code: u64) -> Result { - match code { - Self::CODE => Ok(Self), - _ => Err(Error::UnknownMulticodec(code)), - } - } -} - -impl Codec for DagPb { - fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> - where - T: Representation, - W: Write, - { - unimplemented!() - } - - fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result - where - T: Representation, - { - unimplemented!() - } - - fn read(&mut self, reader: R) -> Result - where - T: Representation, - R: Read, - { - unimplemented!() - } - - /// Given a `Read`, deserialize a dag. - fn read_with_seed<'de, S, R>( - &mut self, - seed: S, - reader: R, - ) -> Result<>::Value, Error> - where - S: DeserializeSeed<'de>, - R: Read, - { - unimplemented!() - } -} - -// impl<'a, W: CborWrite> Encoder for &'a mut CborSerializer { -// #[inline] -// fn serialize_link(self, cid: &Cid) -> Result<::Ok, CborError> { -// let vec: Vec = cid.to_bytes(); -// let bytes: &[u8] = vec.as_ref(); -// Tagged::new(Some(CBOR_LINK_TAG), bytes).serialize(self) -// } -// } - -// impl<'de, 'a, R: CborRead<'de>> Decoder<'de> for &'a mut CborDeserializer { -// #[inline] -// fn deserialize_link(self, visitor: V) -> Result -// where -// V: IpldVisitorExt<'de>, -// { -// match current_cbor_tag() { -// Some(CBOR_LINK_TAG) => { -// let bytes = <&[u8]>::deserialize(self)?; -// let cid = ToCid::to_cid(bytes) -// .or::(Err(de::Error::custom("expected a CID")))?; -// visitor.visit_link(cid) -// } -// Some(_tag) => Err(de::Error::custom("unexpected CBOR tag")), -// _ => Err(de::Error::custom("expected a CID")), -// } -// } -// } diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index 81d7273..04d4e67 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -36,17 +36,18 @@ use std::{ /// /// Should be implemented by any types representing IPLD links and maps. pub trait IpldVisitorExt<'de>: Visitor<'de> { - /// The input contains the string of a `Cid`. + /// The input contains the string of a [`Cid`]. /// /// The default implementation fails with a type error. fn visit_link_str(self, cid_str: &str) -> Result where E: de::Error, { - Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) + let cid = Cid::try_from(cid_str).map_err(E::custom)?; + self.visit_cid(cid) } - /// The input contains the string of a `Cid`. + /// The input contains the string of a [`Cid`]. /// /// The default implementation delegates to [`visit_link_str`]. #[inline] @@ -57,25 +58,36 @@ pub trait IpldVisitorExt<'de>: Visitor<'de> { self.visit_link_str(cid_str) } - /// The input contains a string representation of a `Cid`. + /// The input contains a string representation of a [`Cid`]. /// /// The default implementation fails with a type error. + #[inline] fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result where E: de::Error, { - Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) + let cid = Cid::try_from(cid_bytes).map_err(E::custom)?; + self.visit_cid(cid) } - /// The input contains a string representation of a `Cid`. + /// The input contains a string representation of a [`Cid`]. /// /// The default implementation delegates to [`visit_link_bytes`]. + #[inline] fn visit_link_borrowed_bytes(self, cid_bytes: &'de [u8]) -> Result where E: de::Error, { self.visit_link_bytes(cid_bytes) } + + /// The input contains an already parsed [`Cid`]. + fn visit_cid(self, cid: Cid) -> Result + where + E: de::Error, + { + Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) + } } pub(crate) mod test_utils { diff --git a/src/codecs/raw.rs b/src/codecs/raw.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/data_model/compat.rs b/src/data_model/compat.rs new file mode 100644 index 0000000..f54c586 --- /dev/null +++ b/src/data_model/compat.rs @@ -0,0 +1,174 @@ +use crate::dev::*; + +mod option { + use super::*; + + impl Representation for Option + where + T: Representation, + { + const NAME: &'static str = concat!("Optional", stringify!(T::NAME)); + // TODO + const SCHEMA: &'static str = unimplemented!(); + // const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); + const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = T::SCHEMA_KIND; + const REPR_KIND: Kind = T::REPR_KIND; + const IS_LINK: bool = T::IS_LINK; + const HAS_LINKS: bool = T::HAS_LINKS; + + fn name(&self) -> &'static str { + match self { + Self::None => Null::NAME, + Self::Some(t) => t.name(), + } + } + + // fn kind(&self) -> Kind { + // match self { + // Self::None => Null::KIND, + // Self::Some(t) => t.kind(), + // } + // } + + fn has_links(&self) -> bool { + match self { + Self::None => false, + Self::Some(t) => t.has_links(), + } + } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + None => Representation::serialize::(&Null, serializer), + Some(inner) => inner.serialize::(serializer), + } + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // DeserializeWrapper::::default().deserialize(deserializer) + unimplemented!() + } + } +} + +mod wrapper { + use super::*; + use std::{rc::Rc, sync::Arc}; + + macro_rules! impl_wrapper { + ($wrapper:ident) => { + impl Representation for $wrapper + where + T: Representation, + { + const NAME: &'static str = T::NAME; + const SCHEMA: &'static str = T::SCHEMA; + const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = T::SCHEMA_KIND; + const REPR_KIND: Kind = T::REPR_KIND; + const IS_LINK: bool = T::IS_LINK; + const HAS_LINKS: bool = T::HAS_LINKS; + + fn name(&self) -> &'static str { + self.as_ref().name() + } + + fn data_model_kind(&self) -> Kind { + self.as_ref().data_model_kind() + } + + fn schema_kind(&self) -> Kind { + self.as_ref().schema_kind() + } + + fn repr_kind(&self) -> Kind { + self.as_ref().repr_kind() + } + + fn has_links(&self) -> bool { + self.as_ref().has_links() + } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_ref().serialize::(serializer) + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) + } + } + }; /* + (@dyn $wrapper:ident) => { + impl Representation for $wrapper { + const NAME: &'static str = T::NAME; + const SCHEMA: &'static str = T::SCHEMA; + const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = T::SCHEMA_KIND; + const REPR_KIND: Kind = T::REPR_KIND; + const IS_LINK: bool = T::IS_LINK; + const HAS_LINKS: bool = T::HAS_LINKS; + + #[inline] + fn name(&self) -> &'static str { + self.as_ref().name() + } + + fn data_model_kind(&self) -> Kind { + self.as_ref().data_model_kind() + } + + fn schema_kind(&self) -> Kind { + self.as_ref().schema_kind() + } + + fn repr_kind(&self) -> Kind { + self.as_ref().repr_kind() + } + + fn has_links(&self) -> bool { + self.as_ref().has_links() + } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // self.as_ref().serialize::(serializer) + unimplemented!() + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) + unimplemented!() + } + } + }; + */ + } + + impl_wrapper!(Box); + impl_wrapper!(Rc); + impl_wrapper!(Arc); +} diff --git a/src/data_model/link.rs b/src/data_model/link.rs index 4704b0b..6855876 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -89,8 +89,9 @@ impl Representation for Link { } impl_selector_seed_serde! { @codec_seed_visitor - { T: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()>, } + { T: Select + 'static } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de, Value = ()>, } + { } Link { #[inline] @@ -100,79 +101,88 @@ impl_selector_seed_serde! { @codec_seed_visitor }} impl_selector_seed_serde! { @codec_seed_visitor_ext - { T: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()>, } + { T: Select + 'static } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de, Value = ()>, } + { } Link { #[inline] - fn visit_link_str(self, cid_str: &str) -> Result + fn visit_cid(self, cid: Cid) -> Result where E: serde::de::Error, { - let cid = Cid::try_from(cid_str).map_err(E::custom)?; - self.visit_link(cid) - } - - #[inline] - fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result - where - E: serde::de::Error, - { - let cid = Cid::try_from(cid_bytes).map_err(E::custom)?; self.visit_link(cid) } }} impl_selector_seed_serde! { @selector_seed_codec_deseed - { T: Representation + 'static } - { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } + { T: Select + 'static } + // { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } + { } Link { + // #[inline] + // fn deserialize(self, deserializer: D) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // cfg_if::cfg_if! { + // if #[cfg(feature = "dag-json")] { + // if C == DagJson::CODE { + // return DagJson::deserialize_cid::<'de, D, _>(deserializer, CodecSeed::(self)); + // } + // } + // } + // cfg_if::cfg_if!{ + // if #[cfg(feature = "dag-cbor")] { + // if C == DagCbor::CODE { + // return DagCbor::deserialize_cid::<'de, D, _>(deserializer, CodecSeed::(self)); + // } + // } + // } + + // Deserialize::deserialize(deserializer) + // } #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result<(), D::Error> where D: Deserializer<'de>, { - // deserializer.deserialize_link(self) - // (&mut &mut &mut Decoder(deserializer)).deserialize_link(self) - cfg_if::cfg_if! { if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::deserialize_link(deserializer, CodecSeed::(self)); + if _C == DagJson::CODE { + return DagJson::deserialize_cid(deserializer, self); } } } cfg_if::cfg_if!{ if #[cfg(feature = "dag-cbor")] { - if C == DagCbor::CODE { - return DagCbor::deserialize_link(deserializer, CodecSeed::(self)); + if _C == DagCbor::CODE { + return DagCbor::deserialize_cid(deserializer, self); } } } - // TODO: Deserialize::deserialize(deserializer) } }} impl_selector_seed_serde! { @selector_seed_select - { T: Representation + 'static } - { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } + { T: Select + 'static } + // { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } + { } Link } -impl<'a, const C: u64, Ctx, T> CodecSeed>> +impl<'a, const C: u64, const D: bool, Ctx, T> CodedSelectorSeed<'a, C, D, Ctx, Link> where Ctx: Context, - T: Representation + 'static, + T: Select + 'static, { - /// - /// TODO: continue selection if the current selector is not a matcher fn visit_link<'de, E>(mut self, cid: Cid) -> Result<(), E> where E: de::Error, - for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, T>: DeserializeSeed<'de, Value = ()>, { if let Some(matcher) = self.0.selector.as_matcher() { match self.0.mode() { @@ -192,6 +202,7 @@ where return Ok(()); } + /// TODO: continue selection if the current selector is not a matcher unimplemented!() } } diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 1aa1194..802f4c6 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -1,5 +1,6 @@ use crate::dev::*; use macros::impl_selector_seed_serde; +use serde::de::value::SeqAccessDeserializer; use std::{ cell::RefCell, fmt, @@ -30,7 +31,7 @@ impl Representation for List { let mut seq = serializer.serialize_seq(Some(self.len()))?; for elem in self { - seq.serialize_element(&EncoderElem::<'_, C, _>(elem))?; + seq.serialize_element(&SerializeWrapper::<'_, C, _>(elem))?; } seq.end() } @@ -60,7 +61,9 @@ impl Representation for List { A: SeqAccess<'de>, { let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); - while let Some(elem) = seq.next_element_seed(DecoderElem::::default())? { + while let Some(elem) = + seq.next_element_seed(DeserializeWrapper::::default())? + { list.push(elem); } Ok(list) @@ -72,8 +75,10 @@ impl Representation for List { } impl_selector_seed_serde! { @codec_seed_visitor - { T: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()> } + // { T: Representation + 'static } + { T: Select + 'static } { } + // { for<'b> CodecSeed<_C, _D, SelectorSeed<'b, Ctx, T>, T>: DeserializeSeed<'de> } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } List { #[inline] @@ -86,41 +91,58 @@ impl_selector_seed_serde! { @codec_seed_visitor where A: SeqAccess<'de>, { - match self.0.selector { - Selector::Matcher(_) => self.match_list(seq), - Selector::ExploreIndex(s) => self.explore_list_range(s.index as usize..s.index as usize, seq), - Selector::ExploreRange(s) => self.explore_list_range(s.start as usize..s.end as usize, seq), - Selector::ExploreAll(_) => self.explore_list_range(0.., seq), - _ => Err(A::Error::custom(Error::unsupported_selector::>( - self.0.selector, - ))), + if Self::D { + unimplemented!() + } else { + match self.0.selector { + Selector::Matcher(_) => self.match_list(seq), + Selector::ExploreIndex(s) => self.explore_list_range(s.index as usize..s.index as usize, seq), + Selector::ExploreRange(s) => self.explore_list_range(s.start as usize..s.end as usize, seq), + Selector::ExploreAll(_) => self.explore_list_range(0.., seq), + _ => Err(A::Error::custom(Error::unsupported_selector::>( + self.0.selector, + ))), + } } } }} impl_selector_seed_serde! { @codec_seed_visitor_ext - { T: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()> } + // { T: Representation + 'static } + { T: Select + 'static } { } + // { for<'b> CodecSeed<_C, _D, SelectorSeed<'b, Ctx, T>, T>: DeserializeSeed<'de> } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } List {} } impl_selector_seed_serde! { @selector_seed_codec_deseed - { T: Representation + 'static } - { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } + // { T: Representation + 'static } + { T: Select + 'static } { } + // { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } List { + // #[inline] + // fn deserialize(self, deserializer: D) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // deserializer.deserialize_seq(CodecSeed::::from(self)) + // } #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - deserializer.deserialize_seq(CodecSeed::(self)) + deserializer.deserialize_seq(self) } }} impl_selector_seed_serde! { @selector_seed_select - { T: Representation + 'static } - { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } + // { T: Representation + 'static } // + Select + { T: Select + 'static } { } + // { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } + // { for<'b, 'de> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } List } @@ -184,17 +206,20 @@ where } */ -// match impl -impl<'a, const C: u64, Ctx, T> CodecSeed>> +impl<'a, const C: u64, const D: bool, Ctx, T> + CodecSeed>, List> where Ctx: Context, - T: Representation + 'static, + // T: Representation + 'static, + T: Select + 'static, + // for<'b> CodecSeed> { /// match fn match_list<'de, A>(mut self, mut seq: A) -> Result<(), A::Error> where A: SeqAccess<'de>, - for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()>, + // CodecSeed: DeserializeSeed<'de>, + // for<'b> CodecSeed, T>: DeserializeSeed<'de>, { let matcher = self .0 @@ -219,14 +244,14 @@ where _ => unimplemented!(), } - let (selector, state, mut params, ctx) = self.0.into_parts(); + let (selector, state, mut cb, ctx) = self.0.into_parts(); // select against each child for index in 0usize.. { - let is_empty = SelectorSeed::field_select_seed::( + let seed = SelectorSeed::field_select_seed::( selector, state, - &mut params, + &mut cb, ctx, index.into(), match mode { @@ -237,8 +262,14 @@ where _ => unreachable!(), }, ) - .map_err(A::Error::custom) - .and_then(|seed| Ok(seq.next_element_seed(CodecSeed(seed))?.is_none()))?; + .map_err(A::Error::custom)?; + + // TODO call T::select_from(seed, SeqAccessDeserializer(&mut seq)) + // let is_empty = seq.next_element_seed(CodecSeed::from(seed))?.is_none(); + let is_empty = T::__select_from_seq::(seed, &mut seq)?.is_none(); + // let de = SeqAccessDeserializer::new(std::iter::from_fn(move || { + // seq.next_element_seed + // })) state.ascend::().map_err(A::Error::custom)?; if is_empty { @@ -248,7 +279,7 @@ where // finally, select the matched dag if mode == SelectionMode::SelectDag { - let mut original_seed = SelectorSeed::from(selector, state, params, ctx); + let mut original_seed = SelectorSeed::from_parts(selector, state, cb, ctx); original_seed .select_matched_dag(dag.into_inner(), matcher.label.as_deref()) .map_err(A::Error::custom)?; @@ -262,7 +293,7 @@ where where A: SeqAccess<'de>, R: RangeBounds + Iterator, - for<'b> CodedSeed<'b, C, Ctx, T>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodecSeed, T>: DeserializeSeed<'de>, { // select the list node if self.0.is_node() { @@ -279,7 +310,7 @@ where // ignore everything before the start (unless 0) // if empty, return an err - let (selector, state, mut params, ctx) = self.0.into_parts(); + let (selector, state, mut cb, ctx) = self.0.into_parts(); if start > 0 { for index in 0usize..start { if seq.next_element::()?.is_none() { @@ -292,16 +323,18 @@ where // explore any/all indices in the range for index in range { - let is_empty = SelectorSeed::field_select_seed::( + let seed = SelectorSeed::field_select_seed::( &selector, state, - &mut params, + &mut cb, ctx, index.into(), None, ) - .map_err(A::Error::custom) - .and_then(|seed| Ok(seq.next_element_seed(CodecSeed(seed))?.is_none()))?; + .map_err(A::Error::custom)?; + + let is_empty = T::__select_from_seq::(seed, &mut seq)?.is_none(); + // .and_then(|seed| Ok(seq.next_element_seed(CodecSeed::from(seed))?.is_none()))?; state.ascend::().map_err(A::Error::custom)?; // if unbounded and empty, then we're done exploring diff --git a/src/data_model/map.rs b/src/data_model/map.rs index e6bd0df..b2be937 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -81,10 +81,11 @@ where } impl_selector_seed_serde! { @codec_seed_visitor - { K: Representation + Clone + Ord + AsRef + 'static, - V: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, K>: DeserializeSeed<'de, Value = ()>, - for<'b> CodedSeed<'b, C, Ctx, V>: DeserializeSeed<'de, Value = ()>, } + { K: Select + Clone + Ord + AsRef + 'static, + V: Select + 'static } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, K>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, V>: DeserializeSeed<'de, Value = ()>, } + { } Map { #[inline] @@ -109,49 +110,59 @@ impl_selector_seed_serde! { @codec_seed_visitor }} impl_selector_seed_serde! { @codec_seed_visitor_ext - { K: Representation + Clone + Ord + AsRef + 'static, - V: Representation + 'static } - { for<'b> CodedSeed<'b, C, Ctx, K>: DeserializeSeed<'de, Value = ()>, - for<'b> CodedSeed<'b, C, Ctx, V>: DeserializeSeed<'de, Value = ()>, } + { K: Select + Clone + Ord + AsRef + 'static, + V: Select + 'static } + // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, K>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, V>: DeserializeSeed<'de, Value = ()>, } + { } Map {} } impl_selector_seed_serde! { @selector_seed_codec_deseed - { K: Representation + Clone + Ord + AsRef + 'static, - V: Representation + 'static } - { for<'b> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de>, - for<'b> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de>, } + { K: Select + Clone + Ord + AsRef + 'static, + V: Select + 'static } + // { for<'b> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de, Value = ()>, + // for<'b> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de, Value = ()>, } + { } Map { + // #[inline] + // fn deserialize(self, deserializer: D) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // deserializer.deserialize_map(CodecSeed::(self)) + // } #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result<(), D::Error> where D: Deserializer<'de>, { - deserializer.deserialize_map(CodecSeed::(self)) + deserializer.deserialize_map(self) } }} impl_selector_seed_serde! { @selector_seed_select - { K: Representation + Clone + Ord + AsRef + 'static, - V: Representation + 'static } - { for<'b, 'de> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de>, - for<'b, 'de> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de>, } + { K: Select + Clone + Ord + AsRef + 'static, + V: Select + 'static } + // { for<'b, 'de> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de, Value = ()>, + // for<'b, 'de> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de, Value = ()>, } + { } Map } -impl<'a, const C: u64, Ctx, K, V> CodedSeed<'a, C, Ctx, Map> +impl<'a, const C: u64, const D: bool, Ctx, K, V> CodedSelectorSeed<'a, C, D, Ctx, Map> where Ctx: Context, - K: Representation + Clone + Ord + AsRef + 'static, - V: Representation + 'static, + K: Select + Clone + Ord + AsRef + 'static, + V: Select + 'static, { /// pub(crate) fn match_map<'de, A>(mut self, mut map: A) -> Result<(), A::Error> where A: MapAccess<'de>, - for<'b> CodedSeed<'b, C, Ctx, K>: DeserializeSeed<'de, Value = ()>, - for<'b> CodedSeed<'b, C, Ctx, V>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, { let matcher = self .0 @@ -175,8 +186,8 @@ where let (selector, state, mut params, ctx) = self.0.into_parts(); // select against each child - while let Some(key) = map.next_key::()? { - SelectorSeed::field_select_seed::( + while let Some(key) = map.next_key_seed(DeserializeWrapper::::default())? { + let seed = SelectorSeed::field_select_seed::( selector, state, &mut params, @@ -191,15 +202,16 @@ where _ => unreachable!(), }, ) - .map_err(A::Error::custom) - .and_then(|seed| map.next_value_seed(CodecSeed::(seed)))?; + .map_err(A::Error::custom)?; + + V::__select_from_map::(seed, &mut map, false)?; state.ascend::().map_err(A::Error::custom)?; } // finally, select the matched dag if mode == SelectionMode::SelectDag { - let mut original_seed = SelectorSeed::from(selector, state, params, ctx); + let mut original_seed = SelectorSeed::from_parts(selector, state, params, ctx); original_seed .select_matched_dag(dag.into_inner(), matcher.label.as_deref()) .map_err(A::Error::custom)?; @@ -212,8 +224,8 @@ where pub(crate) fn explore_map_fields<'de, A>(self, mut map: A) -> Result<(), A::Error> where A: MapAccess<'de>, - for<'b> CodedSeed<'b, C, Ctx, K>: DeserializeSeed<'de, Value = ()>, - for<'b> CodedSeed<'b, C, Ctx, V>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, { unimplemented!() } @@ -222,8 +234,8 @@ where pub(crate) fn explore_map_all<'de, A>(self, mut map: A) -> Result<(), A::Error> where A: MapAccess<'de>, - for<'b> CodedSeed<'b, C, Ctx, K>: DeserializeSeed<'de, Value = ()>, - for<'b> CodedSeed<'b, C, Ctx, V>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, + // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, { unimplemented!() } diff --git a/src/data_model/mod.rs b/src/data_model/mod.rs index 31ed1aa..82f2752 100644 --- a/src/data_model/mod.rs +++ b/src/data_model/mod.rs @@ -1,8 +1,10 @@ //! A general `Value` type, representing all IPLD data model kinds. use crate::dev::*; +use macros::derive_more::From; mod any; +mod compat; // pub mod borrowed; // mod canon; mod link; @@ -20,9 +22,12 @@ pub use primitive::*; /// Wrapper type to connect [`serde::Serialize`] to the underlying type's /// [`Representation::serialize`] codec-specific implementation. #[doc(hidden)] -#[derive(Debug)] -pub struct EncoderElem<'a, const C: u64, T>(pub &'a T); -impl<'a, const C: u64, T: Representation> Serialize for EncoderElem<'a, C, T> { +#[derive(Debug, From)] +pub struct SerializeWrapper<'a, const C: u64, T>(pub &'a T); +impl<'a, const C: u64, T> Serialize for SerializeWrapper<'a, C, T> +where + T: Representation, +{ #[inline(always)] fn serialize(&self, serializer: S) -> Result where @@ -36,13 +41,16 @@ impl<'a, const C: u64, T: Representation> Serialize for EncoderElem<'a, C, T> { /// [`Representation::deserialize`] codec-specific implementation. #[doc(hidden)] #[derive(Debug)] -pub struct DecoderElem(std::marker::PhantomData); -impl Default for DecoderElem { +pub struct DeserializeWrapper(std::marker::PhantomData); +impl Default for DeserializeWrapper { fn default() -> Self { Self(std::marker::PhantomData) } } -impl<'de, const C: u64, T: Representation> DeserializeSeed<'de> for DecoderElem { +impl<'de, const C: u64, T> DeserializeSeed<'de> for DeserializeWrapper +where + T: Representation, +{ type Value = T; #[inline(always)] fn deserialize(self, deserializer: D) -> Result diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index 0718822..b89c001 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -3,7 +3,6 @@ use macros::{ derive_more::{AsMut, AsRef, Deref, DerefMut, From, Index, IndexMut, Into, IntoIterator}, impl_selector_seed_serde, }; -use serde::de::IntoDeserializer; use std::{borrow::Cow, fmt, ops::RangeBounds, str::FromStr}; pub use self::bool::Bool; @@ -28,6 +27,24 @@ mod null { const NAME: &'static str = "Null"; const SCHEMA: &'static str = "type Null null"; const DATA_MODEL_KIND: Kind = Kind::Null; + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // TODO: none or unit? + serializer.serialize_none() + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + <()>::deserialize(deserializer)?; + Ok(Self) + } } impl_selector_seed_serde! { @codec_seed_visitor {} {} Null { @@ -57,11 +74,11 @@ mod null { impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Null { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - deserializer.deserialize_unit(CodecSeed::(self)) + deserializer.deserialize_unit(self) } }} @@ -78,6 +95,22 @@ mod bool { const NAME: &'static str = "Bool"; const SCHEMA: &'static str = "type Bool bool"; const DATA_MODEL_KIND: Kind = Kind::Bool; + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Serialize::serialize(self, serializer) + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer) + } } impl_selector_seed_serde! { @codec_seed_visitor {} {} Bool { @@ -99,11 +132,11 @@ mod bool { impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bool { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - deserializer.deserialize_bool(CodecSeed::(self)) + deserializer.deserialize_bool(self) } }} @@ -130,6 +163,22 @@ mod num { const SCHEMA: &'static str = concat!("type ", stringify!($name), " ", stringify!($ipld_type)); const DATA_MODEL_KIND: Kind = Kind::$kind; + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Serialize::serialize(self, serializer) + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer) + } } impl_selector_seed_serde! { @codec_seed_visitor {} {} $ty { @@ -162,11 +211,11 @@ mod num { impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} $ty { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - deserializer.$deserialize_fn(CodecSeed::(self)) + deserializer.$deserialize_fn(self) } }} @@ -176,7 +225,7 @@ mod num { impl_ipld_num! ( "A fixed-length number type represented as a int8"; - i8 : Int8 Int int { + i8 : Int8 Int int8 { deserialize_i8 visit_i8 @conv { @@ -187,7 +236,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a int16" ; - i16 : Int16 Int int { + i16 : Int16 Int int16 { deserialize_i16 visit_i16 @conv { @@ -198,7 +247,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a int32" ; - i32 : Int32 Int int { + i32 : Int32 Int int32 { deserialize_i32 visit_i32 @conv { @@ -209,7 +258,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a int64" ; - i64 : Int64 Int int { + i64 : Int64 Int int64 { deserialize_i64 visit_i64 @conv { @@ -220,7 +269,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a int128" ; - i128 : Int128 Int int { + i128 : Int128 Int int128 { deserialize_i128 visit_i128 @conv { @@ -231,7 +280,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a uint8" ; - u8 : Uint8 Int int { + u8 : Uint8 Int uint8 { deserialize_u8 visit_u8 @conv { @@ -242,7 +291,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a uint16" ; - u16 : Uint16 Int int { + u16 : Uint16 Int uint16 { deserialize_u16 visit_u16 @conv { @@ -253,7 +302,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a uint32" ; - u32 : Uint32 Int int { + u32 : Uint32 Int uint32 { deserialize_u32 visit_u32 @conv { @@ -264,7 +313,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a uint64" ; - u64 : Uint64 Int int { + u64 : Uint64 Int uint64 { deserialize_u64 visit_u64 @conv { @@ -275,7 +324,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a uint128" ; - u128 : Uint128 Int int { + u128 : Uint128 Int uint128 { deserialize_u128 visit_u128 @conv { @@ -286,7 +335,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a float32" ; - f32 : Float32 Float float { + f32 : Float32 Float float32 { deserialize_f32 visit_f32 @conv { f64:visit_f64 } @@ -294,7 +343,7 @@ mod num { ); impl_ipld_num! ( "A fixed-length number type represented as a float64" ; - f64 : Float64 Float float { + f64 : Float64 Float float64 { deserialize_f64 visit_f64 @conv { f32:visit_f32 } @@ -342,6 +391,22 @@ mod string { const NAME: &'static str = "String"; const SCHEMA: &'static str = "type String string"; const DATA_MODEL_KIND: Kind = Kind::String; + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Serialize::serialize(&self.0, serializer) + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self::from(>::deserialize(deserializer)?)) + } } // TODO: @@ -356,7 +421,11 @@ mod string { where E: de::Error, { - self.match_primitive(IpldString::from(s)) + if Self::is_select() { + self.match_primitive(IpldString::from(s)) + } else { + unimplemented!() + } } // TODO: @@ -365,7 +434,11 @@ mod string { where E: de::Error, { - self.match_primitive(IpldString::from(s)) + if Self::is_select() { + self.match_primitive(IpldString::from(s)) + } else { + unimplemented!() + } } }} @@ -373,11 +446,11 @@ mod string { impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} IpldString { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - deserializer.deserialize_string(CodecSeed::(self)) + deserializer.deserialize_string(self) } }} @@ -422,40 +495,6 @@ mod string { write!(f, "{}", self.as_str()) } } - - // TODO: - impl Serialize for IpldString { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.collect_str(&self.0.nfc()) - } - } - - // TODO: - impl<'de> Deserialize<'de> for IpldString { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // struct IpldStringVisitor; - // impl<'de> Visitor<'de> for IpldStringVisitor { - // type Value = IpldString; - // fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { - // write!(f, "A string or sequence of chars") - // } - // fn visit_seq(self, seq: A) -> Result - // where - // A: SeqAccess<'de>, { - // let iter = SeqAccessDeserializer::new(seq); - - // } - // } - - Ok(Self::from(String::deserialize(deserializer)?)) - } - } } mod bytes { @@ -525,8 +564,7 @@ mod bytes { const SCHEMA: &'static str = "type Bytes bytes"; const DATA_MODEL_KIND: Kind = Kind::Bytes; - /// - #[inline] + #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -542,12 +580,34 @@ mod bytes { Serialize::serialize(self.as_ref(), serializer) } - /// - #[inline] + #[doc(hidden)] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { + struct BytesVisitor; + impl<'de> Visitor<'de> for BytesVisitor { + type Value = Bytes; + #[inline] + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(formatter, "A slice of bytes") + } + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + Ok(Self::Value::copy_from_slice(bytes)) + } + #[inline] + fn visit_byte_buf(self, bytes: Vec) -> Result + where + E: de::Error, + { + Ok(Self::Value::from(bytes.into_boxed_slice())) + } + } + cfg_if::cfg_if! { if #[cfg(feature = "dag-json")] { if C == DagJson::CODE { @@ -556,7 +616,7 @@ mod bytes { } } - Deserialize::deserialize(deserializer) + Ok(Self::from(Box::<[u8]>::deserialize(deserializer)?)) } } @@ -571,7 +631,12 @@ mod bytes { where E: de::Error, { - self.select_bytes(bytes) + if Self::is_select() { + self.select_bytes(bytes) + } else { + // Ok(Self::Value::from(bytes)) + unimplemented!() + } } #[inline] @@ -579,7 +644,12 @@ mod bytes { where E: de::Error, { - self.select_bytes(&bytes) + if Self::is_select() { + self.select_bytes(&bytes) + } else { + // Ok(Self::Value::from(bytes)) + unimplemented!() + } } }} @@ -587,28 +657,25 @@ mod bytes { impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bytes { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - // ::deserialize_bytes(deserializer, self) - // (&mut &mut &mut Decoder(deserializer)).deserialize_bytes(self) - cfg_if::cfg_if! { if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, CodecSeed::(self)); + if _C == DagJson::CODE { + return DagJson::deserialize_bytes(deserializer, self); } } } - deserializer.deserialize_bytes(CodecSeed::(self)) + deserializer.deserialize_bytes(self) } }} impl_selector_seed_serde! { @selector_seed_select {} {} Bytes } - impl<'a, const C: u64, Ctx> CodecSeed> + impl<'a, const C: u64, const D: bool, Ctx> CodedSelectorSeed<'a, C, D, Ctx, Bytes> where Ctx: Context, { @@ -660,50 +727,50 @@ mod bytes { } } - impl Serialize for Bytes { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_bytes(self.as_ref()) - } - } - - struct BytesVisitor; - // impl<'de> IpldVisitorExt<'de> for BytesVisitor {} - impl<'de> Visitor<'de> for BytesVisitor { - type Value = Bytes; - #[inline] - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "A slice of bytes") - } - #[inline] - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: de::Error, - { - Ok(Self::Value::copy_from_slice(bytes)) - } - #[inline] - fn visit_byte_buf(self, bytes: Vec) -> Result - where - E: de::Error, - { - Ok(Self::Value::from(bytes.into_boxed_slice())) - } - } - - impl<'de> Deserialize<'de> for Bytes { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_bytes(BytesVisitor) - } - } + // impl Serialize for Bytes { + // fn serialize(&self, serializer: S) -> Result + // where + // S: Serializer, + // { + // serializer.serialize_bytes(self.as_ref()) + // } + // } + + // struct BytesVisitor; + // // impl<'de> IpldVisitorExt<'de> for BytesVisitor {} + // impl<'de> Visitor<'de> for BytesVisitor { + // type Value = Bytes; + // #[inline] + // fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(formatter, "A slice of bytes") + // } + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::copy_from_slice(bytes)) + // } + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::from(bytes.into_boxed_slice())) + // } + // } + + // impl<'de> Deserialize<'de> for Bytes { + // fn deserialize(deserializer: D) -> Result + // where + // D: Deserializer<'de>, + // { + // deserializer.deserialize_bytes(BytesVisitor) + // } + // } } -impl<'a, const C: u64, Ctx, T> CodecSeed> +impl<'a, const C: u64, const D: bool, Ctx, T> CodedSelectorSeed<'a, C, D, Ctx, T> where Ctx: Context, T: Representation + 'static, diff --git a/src/lib.rs b/src/lib.rs index f91cf3f..926d966 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,16 +33,13 @@ mod specs { use super::*; // codecs - pub use crate::multicodec::Codec; - #[cfg(feature = "dag-cbor")] pub use crate::codecs_::dag_cbor::DagCbor; #[cfg(feature = "dag-json")] pub use crate::codecs_::dag_json::DagJson; // #[cfg(feature = "dag-pb")] // pub use crate::codecs_::dag_pb::DagPb; - #[cfg(feature = "multicodec")] - pub use crate::multicodec::Multicodec; + pub use crate::multicodec::{Codec, Multicodec}; // multiformats pub use multibase::Base as Multibase; diff --git a/src/multicodec.rs b/src/multicodec.rs index 343763a..aa660fb 100644 --- a/src/multicodec.rs +++ b/src/multicodec.rs @@ -4,7 +4,6 @@ use std::{ io::{Read, Write}, }; -#[cfg(feature = "multicodec")] pub use multicodec::Multicodec; /// An unified trait for all IPLD @@ -42,20 +41,21 @@ pub trait Codec: TryFrom { R: Read; } -// TODO: this feature flag isn't right; we should enable/disable variants and panic if none are enabled -#[cfg(feature = "multicodec")] mod multicodec { use super::*; macro_rules! impl_multicodec { ($( + #[cfg(feature = $feature:expr)] $(#[$meta:meta])* $variant:ident -> $ty:ty as $name:expr, )*) => { /// A generic [multicodec]() enum. #[derive(Clone, Debug)] + #[non_exhaustive] pub enum Multicodec { $( + #[cfg(feature = $feature)] $(#[$meta])* $variant($ty), )* @@ -66,7 +66,11 @@ mod multicodec { #[inline] pub const fn name(&self) -> &'static str { match self { - $(Self::$variant(_) => $name,)* + $( + #[cfg(feature = $feature)] + Self::$variant(_) => $name, + )* + // _ => unimplemented!() } } @@ -74,7 +78,11 @@ mod multicodec { #[inline] pub const fn code(&self) -> u64 { match self { - $(Self::$variant(_) => <$ty>::CODE,)* + $( + #[cfg(feature = $feature)] + Self::$variant(_) => <$ty>::CODE, + )* + // _ => unimplemented!() } } @@ -82,7 +90,10 @@ mod multicodec { #[inline] pub fn from_name(name: &str) -> Result { match name { - $($name => Ok(Self::$variant(<$ty>::new())),)* + $( + #[cfg(feature = $feature)] + $name => Ok(Self::$variant(<$ty>::new())), + )* name => Err(Error::UnknownMulticodecName(name.to_string())) } } @@ -91,23 +102,30 @@ mod multicodec { #[inline] pub const fn from_code() -> Result { match C { - $(<$ty>::CODE => Ok(Self::$variant(<$ty>::new())),)* + $( + #[cfg(feature = $feature)] + <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), + )* code => Err(Error::UnknownMulticodecCode(code)) } } - /// - /// Given a `Read`, deserialize a dag using a `SelectorSeed` as a guide. #[doc(hidden)] - pub fn read_with_seed<'de, S, R>(&mut self, seed: S, reader: R) -> Result<(), Error> + pub fn read_from_seed( + &mut self, + seed: SelectorSeed<'_, Ctx, T>, + reader: R, + ) -> Result<(), Error> where - // S: DeserializeSeed<'de, Value = ()>, - // BlockSelectorSeed: DeserializeSeed<'de, Value = ()>, - S: CodecDeserializeSeed<'de>, + Ctx: Context, + T: Select, R: Read, { match self { - $(Self::$variant(inner) => inner.read_with_seed(seed, reader),)* + $( + #[cfg(feature = $feature)] + Self::$variant(_) => <$ty>::read_from_seed(seed, reader), + )* } } } @@ -117,7 +135,10 @@ mod multicodec { #[inline] fn try_from(code: u64) -> Result { match code { - $(<$ty>::CODE => Ok(Self::$variant(<$ty>::default())),)* + $( + #[cfg(feature = $feature)] + <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), + )* _ => Err(Error::UnknownMulticodecCode(code)), } } @@ -128,7 +149,10 @@ mod multicodec { #[inline] fn try_from(s: &'a str) -> Result { match s { - $($name => Ok(Self::$variant(<$ty>::default())),)* + $( + #[cfg(feature = $feature)] + $name => Ok(Self::$variant(<$ty>::new())), + )* _ => Err(Error::UnknownMulticodecName(s.into())), } } @@ -141,7 +165,11 @@ mod multicodec { W: Write, { match self { - $(Self::$variant(inner) => inner.write(dag, writer),)* + $( + #[cfg(feature = $feature)] + Self::$variant(inner) => inner.write(dag, writer), + )* + // _ => unimplemented!() } } @@ -150,7 +178,11 @@ mod multicodec { T: Representation, { match self { - $(Self::$variant(inner) => inner.decode(bytes),)* + $( + #[cfg(feature = $feature)] + Self::$variant(inner) => inner.decode(bytes), + )* + // _ => unimplemented!() } } @@ -160,7 +192,11 @@ mod multicodec { R: Read, { match self { - $(Self::$variant(inner) => inner.read(reader),)* + $( + #[cfg(feature = $feature)] + Self::$variant(inner) => inner.read(reader), + )* + // _ => unimplemented!() } } } @@ -168,11 +204,14 @@ mod multicodec { impl_multicodec! { // Raw -> Raw as "raw", - DagJson -> DagJson as "dag-json", + #[cfg(feature = "dag-cbor")] + /// DagCbor -> DagCbor as "dag-cbor", + #[cfg(feature = "dag-json")] + /// + DagJson -> DagJson as "dag-json", // DagJose -> DagJose as "dag-jose", // DagBipf -> DagBipf as "dag-bipf", - // VerkleDagCbor -> VerkleDagCbor as "verkle-dag-cbor", // Custom(Box), } diff --git a/src/multihash.rs b/src/multihash.rs index d157727..b3cb493 100644 --- a/src/multihash.rs +++ b/src/multihash.rs @@ -38,7 +38,7 @@ macro_rules! impl_multihasher { } } - /// + /// The underlying size of the digest. #[inline] pub const fn size(&self) -> u8 { match self { diff --git a/src/representation.rs b/src/representation.rs index 34e8eeb..55ca228 100644 --- a/src/representation.rs +++ b/src/representation.rs @@ -11,7 +11,6 @@ use crate::dev::*; use downcast_rs::{impl_downcast, Downcast}; -use std::{rc::Rc, sync::Arc}; pub use kind::Kind; @@ -191,10 +190,10 @@ mod kind { /// - TODO: ? stateful visitor derived from selector + type? /// - TODO: ? impl DeserializeSeed for selector? /// - TODO: ? Representation::visitor(selector: &Selector) -pub trait Representation -where - Self: Serialize + for<'de> Deserialize<'de>, -{ +pub trait Representation: Sized { + // TODO: use this seed in Representation::deserialize by default + // type Seed<'de, const C: u64>: Default + DeserializeSeed<'de, Value = Self>; + /// The stringified name of the IPLD type. const NAME: &'static str; @@ -263,7 +262,8 @@ where where S: Serializer, { - ::serialize(self, serializer) + // ::serialize(self, serializer) + unimplemented!() } /// Replacement method for [`serde::Deserialize::deserialize`] that allows @@ -278,9 +278,45 @@ where where D: Deserializer<'de>, { - >::deserialize(deserializer) + // >::deserialize(deserializer) + unimplemented!() } + // /// + // #[inline] + // #[doc(hidden)] + // fn deserialize_seed<'de, const C: u64, S, D>( + // seed: S, + // deserializer: D, + // ) -> Result + // where + // S: CodecDeserializeSeed<'de>, + // D: Deserializer<'de>, + // { + // seed.deserialize(deserializer) + // } + + // /// + // #[inline] + // #[doc(hidden)] + // fn deserialize_with_visitor<'de, const C: u64, D, V>( + // deserializer: D, + // visitor: V, + // ) -> Result + // where + // D: Deserializer<'de>, + // V: Visitor<'de>; + + // #[inline] + // #[doc(hidden)] + // fn deserialize<'de, const C: u64, D, V>( + // deserializer: D, + // visitor: V, + // ) -> Result + // where + // D: Deserializer<'de>, + // V: Visitor<'de>; + // /// // #[inline] // fn deserialize_seed<'de, const C: u64, D, S>( @@ -338,109 +374,6 @@ where // fn links(c: Codec, reader: &mut R, ) } -impl Representation for Option -where - T: Representation, -{ - const NAME: &'static str = concat!("Optional", stringify!(T::NAME)); - // TODO - const SCHEMA: &'static str = unimplemented!(); - // const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); - const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = T::DATA_MODEL_KIND; - const HAS_LINKS: bool = T::HAS_LINKS; - - fn name(&self) -> &'static str { - match self { - Self::None => Null::NAME, - Self::Some(t) => t.name(), - } - } - - // fn kind(&self) -> Kind { - // match self { - // Self::None => Null::KIND, - // Self::Some(t) => t.kind(), - // } - // } - - fn has_links(&self) -> bool { - match self { - Self::None => false, - Self::Some(t) => t.has_links(), - } - } -} - -macro_rules! impl_wrapper { - ($wrapper:ident) => { - impl Representation for $wrapper - where - T: Representation, - { - const NAME: &'static str = T::NAME; - const SCHEMA: &'static str = T::SCHEMA; - const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - const REPR_KIND: Kind = T::REPR_KIND; - - fn name(&self) -> &'static str { - self.as_ref().name() - } - - fn data_model_kind(&self) -> Kind { - self.as_ref().data_model_kind() - } - - fn schema_kind(&self) -> Kind { - self.as_ref().schema_kind() - } - - fn repr_kind(&self) -> Kind { - self.as_ref().repr_kind() - } - - fn has_links(&self) -> bool { - self.as_ref().has_links() - } - } - }; - (@dyn $wrapper:ident) => { - impl Representation for $wrapper { - const NAME: &'static str = T::NAME; - const SCHEMA: &'static str = T::SCHEMA; - const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - const REPR_KIND: Kind = T::REPR_KIND; - - #[inline] - fn name(&self) -> &'static str { - self.as_ref().name() - } - - fn data_model_kind(&self) -> Kind { - self.as_ref().data_model_kind() - } - - fn schema_kind(&self) -> Kind { - self.as_ref().schema_kind() - } - - fn repr_kind(&self) -> Kind { - self.as_ref().repr_kind() - } - - fn has_links(&self) -> bool { - self.as_ref().has_links() - } - } - }; -} - -impl_wrapper!(Box); -impl_wrapper!(Rc); -impl_wrapper!(Arc); - /// /// TODO: possibly look at erased-serde to complete this "hack" pub(crate) trait ErasedRepresentation: Downcast { diff --git a/src/selectors/mod.rs b/src/selectors/mod.rs index 13cee98..1d07b7d 100644 --- a/src/selectors/mod.rs +++ b/src/selectors/mod.rs @@ -33,7 +33,11 @@ use std::{ /// /// TODO: + 'static? /// - Selectable? -pub trait Select: Representation { +pub trait Select: Representation { + // /// + // #[doc(hidden)] + // type Seed<'a, 'de, const C: u64>: From> + DeserializeSeed<'de> = CodedSelectorSeed<'a, C, false, Ctx, Self>; + /// Produces a stream of [`Selection`]s of some type `T`. /// /// Under the hood, this serves as the entrypoint for deserialization of a @@ -43,29 +47,79 @@ pub trait Select: Representation { /// [`Context`] to govern how to interpret the types found in blocks. /// /// - /// TODO: update this interface, since ContextSeed is doing the work and it should be refactored a bit (borrow state, ) - fn select(params: Params<'_, C, Self>, ctx: &mut C) -> Result<(), Error>; + /// TODO: update this interface, since SelectorSeed is doing the work and it should be refactored a bit (borrow state, ) + fn select(params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error>; + + #[doc(hidden)] + fn __select_from_deserializer<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + Err(D::Error::custom("unimplemented")) + // TODO: default impl should use GAT for CodedSeed + // Self::Seed::<'a, 'de, C>::from(seed).deserialize(deserializer) + } + + #[doc(hidden)] + fn __select_from_seq<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + mut seq: A, + ) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + // seq.next_element_seed(CodecSeed::from(seed)) + Err(A::Error::custom("unimplemented")) + // TODO: default impl should use GAT for CodedSeed + // seq.next_element_seed(Self::Seed::<'a, 'de, C>::from(seed)) + } + + #[doc(hidden)] + fn __select_from_map<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + mut map: A, + is_key: bool, + ) -> Result, A::Error> + where + A: MapAccess<'de>, + { + Err(A::Error::custom("unimplemented")) + // TODO: default impl should use GAT for CodedSeed + // let seed = Self::Seed::<'a, 'de, C>::from(seed); + // if is_key { + // map.next_key_seed(seed) + // } else { + // Ok(Some(map.next_value_seed(seed)?)) + // } + } - /// Selects against the dag, loading more blocks from `C` if required. + /// Selects against the dag, loading more blocks from `Ctx` if required. /// /// TODO - fn select_in(&self, params: Params<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { + #[doc(hidden)] + fn select_in(&self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { unimplemented!() } - /// Patches the dag according to the selector, loading more blocks from `C` - /// if required. + /// Patches the dag according to the selector, loading more blocks from + /// `Ctx` if required. Returns `true` it a patch was performed somewhere + /// within the dag. /// /// TODO - fn patch_in(&mut self, params: Params<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { + #[doc(hidden)] + fn patch_in(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { unimplemented!() } - /// Flushes the dag according to the selector, writing blocks to `C` if + /// Flushes the dag according to the selector, writing blocks to `Ctx` if /// flushing linked dags. /// /// TODO - fn flush(&mut self, params: Params<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { + #[doc(hidden)] + fn flush(&mut self, ctx: &mut Ctx) -> Result<(), Error> { unimplemented!() } @@ -405,10 +459,12 @@ mod selection { Float64(Float64), /// + #[serde(skip)] // TODO #[serde(rename = "string")] String(IpldString), /// + #[serde(skip)] // TODO #[serde(rename = "bytes")] Bytes(Bytes), diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index 1946390..12eb6de 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -1,6 +1,6 @@ use super::*; use crate::dev::{macros::derive_more::From, *}; -use std::fmt; +use std::{fmt, marker::PhantomData}; /// A helper type for guided decoding of a dag, using a selector to direct /// and/or ignore fields or entire blocks, and a linked context to fetch more @@ -22,70 +22,172 @@ pub struct SelectorSeed<'a, Ctx, T = Any> { /// ? 3. Link needs to take some seed, uncode it, then use inner to call SelectorSeed::select for the next block #[doc(hidden)] #[derive(Debug)] -pub struct CodecSeed(pub S); -impl<'de, const C: u64, S> DeserializeSeed<'de> for CodecSeed -where - S: CodecDeserializeSeed<'de>, -{ - type Value = (); - #[inline(always)] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - CodecDeserializeSeed::<'_>::deserialize::(self.0, deserializer) +pub struct CodecSeed(pub(crate) S, PhantomData); + +impl CodecSeed { + pub const D: bool = D; + pub const fn is_select() -> bool { + !D } } -/// -#[doc(hidden)] -pub type CodedSeed<'a, const C: u64, Ctx, T> = CodecSeed>; +impl<'a, const C: u64, Ctx, T> CodecSeed, T> { + /// + #[inline] + pub(crate) fn from_parts( + selector: &'a Selector, + state: &'a mut State, + callback: Callback<'a, Ctx, T>, + ctx: &'a mut Ctx, + ) -> Self { + Self( + SelectorSeed { + selector, + state, + callback, + ctx, + // visitor, + // _t: PhantomData, + }, + PhantomData, + ) + } -// pub struct CodecSeed<'a, const C: u64, Ctx, T = Any>(SelectorSeed<'a, Ctx, T>); -// impl<'a, const C: u64, Ctx, T> Into> for CodecSeed<'a, C, Ctx, T> { -// fn into(self) -> SelectorSeed<'a, Ctx, T> { -// self.0 + /// + #[inline] + #[doc(hidden)] + pub(crate) fn into_parts( + self, + ) -> ( + &'a Selector, + &'a mut State, + Callback<'a, Ctx, T>, + &'a mut Ctx, + ) { + (self.0.selector, self.0.state, self.0.callback, self.0.ctx) + } +} + +impl<'de, const C: u64, T> CodecSeed, T> +// where +// Self: Visitor<'de>, +{ + #[inline] + #[doc(hidden)] + pub fn empty() -> Self { + CodecSeed(PhantomData, PhantomData) + } +} + +// impl<'a, const C: u64, Ctx, T> CodecSeed> { +// fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { +// Self(inner) // } // } -// impl<'a, const C: u64, Ctx, T> From> for CodecSeed<'a, C, Ctx, T> { -// fn from(seed: SelectorSeed<'a, Ctx, T>) -> Self { -// Self(seed) +// impl CodecSeed> { +// fn from(inner: PhantomData) -> Self { +// Self(inner) +// } +// } +impl<'a, const C: u64, Ctx, T> From> + for CodecSeed, T> +{ + fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { + Self(inner, PhantomData) + } +} +impl From> for CodecSeed, T> { + fn from(inner: PhantomData) -> Self { + Self(inner, PhantomData) + } +} +// impl<'a, const C: u64, Ctx, T> Into> for SelectorSeed<'a, Ctx, T> { +// fn into(self) -> CodecSeed { +// CodecSeed(self) +// } +// } +// impl Into> for PhantomData { +// fn into(self) -> CodecSeed { +// CodecSeed(self) +// } +// } + +// impl CodecSeed { +// pub fn into_inner(self) -> T { +// self.0 // } // } -/// Replacement trait for [`serde::de::DeserializeSeed`], that allows us to -/// switch deserialization behaviour based on the current block's [`Codec`]. /// -/// How to use: -/// ? implement this for SelectorSeed -/// ? call the appropriate deserializer method for the codec -/// ? pass itself as a visitor -/// ? for compounds, create CodecSeed -/// ? pass that as a seed #[doc(hidden)] -pub trait CodecDeserializeSeed<'de> { - // pub trait CodecDeserializeSeed<'de>: DeserializeSeed<'de, Value = ()> { - fn deserialize(self, deserializer: D) -> Result<(), D::Error> - where - // CodecSeed: DeserializeSeed<'de, Value = ()>, - D: Deserializer<'de>; - // { - // // CodecSeed::(self).deserialize(deserializer) - // DeserializeSeed::<'_>::deserialize(self, deserializer) - // } -} -// impl<'a, 'de, Ctx, T> CodecDeserializeSeed<'de> for SelectorSeed<'a, Ctx, T> -// // where -// // CodecSeed: DeserializeSeed<'de, Value = ()>, -// { -// fn deserialize(self, deserializer: D) -> Result<(), D::Error> +pub type CodedSelectorSeed<'a, const C: u64, const D: bool, Ctx, T> = + CodecSeed, T>; + +// /// Replacement trait for [`serde::de::DeserializeSeed`], that allows us to +// /// switch deserialization behaviour based on the current block's [`Codec`]. +// /// +// /// How to use: +// /// ? implement this for SelectorSeed +// /// ? call the appropriate deserializer method for the codec +// /// ? pass itself as a visitor +// /// ? for compounds, create CodecSeed +// /// ? pass that as a seed +// #[doc(hidden)] +// pub trait CodecDeserializeSeed<'de> { +// type Value; +// // pub trait CodecDeserializeSeed<'de>: DeserializeSeed<'de, Value = ()> { +// fn deserialize(self, deserializer: D) -> Result // where -// CodecSeed: DeserializeSeed<'de, Value = ()>, -// D: Deserializer<'de>, -// { -// CodecSeed::(self).deserialize(deserializer) +// // CodecSeed: DeserializeSeed<'de, Value = ()>, +// D: Deserializer<'de>; +// // { +// // // CodecSeed::(self).deserialize(deserializer) +// // DeserializeSeed::<'_>::deserialize(self, deserializer) +// // } +// +// fn mode(&self) -> SelectionMode { +// unimplemented!() // } +// +// // fn to_field_select_seed<'b, U>( +// // &mut self, +// // field: Field<'b>, +// // match_cb: Option, +// // post_cb: Option, +// // ) -> Result<(), Error> { +// // unimplemented!() +// // } // } +// +// // impl<'de, T> CodecDeserializeSeed<'de> for PhantomData +// // where +// // T: Representation, +// // { +// // type Value = T; +// // +// // fn deserialize(self, deserializer: D) -> Result +// // where +// // D: Deserializer<'de>, +// // { +// // ::deserialize::(deserializer) +// // } +// // } +// // +// // impl<'a, 'de, Ctx, T> CodecDeserializeSeed<'de> for SelectorSeed<'a, Ctx, T> +// // // where +// // // CodecSeed: DeserializeSeed<'de, Value = ()>, +// // { +// // const D: bool = false; +// // type Value = (); +// // fn deserialize(self, deserializer: De) -> Result<(), De::Error> +// // where +// // // CodecSeed as CodecDeserializeSeed<'de>>::D }, Self>: +// // // DeserializeSeed<'de, Value = ()>, +// // De: Deserializer<'de>, +// // { +// // CodecSeed::(self).deserialize(deserializer) +// // } +// // } impl<'a, Ctx, T> fmt::Debug for SelectorSeed<'a, Ctx, T> where @@ -326,24 +428,49 @@ where Ctx: Context, T: Representation, { + // #[inline] + // pub(crate) fn mode(&self) -> SelectionMode<'_> { + // match (&self.callback, self.selector) { + // (Callback::SelectNode { .. }, Selector::Matcher(m)) => { + // SelectionMode::SelectNode(m.label.as_deref()) + // } + // (Callback::SelectNode { .. }, _) => SelectionMode::SelectNode(None), + // (Callback::SelectDag { .. } | Callback::MatchDag { .. }, _) => SelectionMode::SelectDag, + // // Self::Patch { .. } => SelectionMode::Patch, + // } + // } + + /// #[inline] - pub(crate) const fn mode(&self) -> SelectionMode { - self.callback.mode() + pub const fn mode(&self) -> SelectionMode { + match &self.callback { + Callback::SelectNode { .. } => SelectionMode::SelectNode, + Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::SelectDag, + // Self::Patch { .. } => SelectionMode::Patch, + } } + /// #[inline] - pub(crate) const fn is_node(&self) -> bool { - self.callback.is_node() + pub const fn is_node(&self) -> bool { + match self.callback { + Callback::SelectNode { .. } => true, + _ => false, + } } + /// #[inline] - pub(crate) const fn is_dag(&self) -> bool { - self.callback.is_dag() + pub const fn is_dag(&self) -> bool { + match self.callback { + Callback::SelectDag { .. } | Callback::MatchDag { .. } => true, + _ => false, + } } /// #[inline] - pub(crate) fn from( + pub(crate) fn from_parts( selector: &'a Selector, state: &'a mut State, callback: Callback<'a, Ctx, T>, @@ -372,17 +499,6 @@ where ) { (self.selector, self.state, self.callback, self.ctx) } - - // /// - // #[inline] - // pub fn encode(self, dag: &T) -> Result<(), Error> { - // // let mut encoder = self.ctx.encoder(); - // // let encoder_mut = encoder.as_mut(); - // // dag.serialize(encoder_mut).map_err(Error::encoder)?; - // // Ok(()) - // - // unimplemented!() - // } } // dag selection methods @@ -391,19 +507,13 @@ where Ctx: Context, T: Representation, { - const DEFAULT_SELECTOR: Selector = Selector::DEFAULT; - /// #[doc(hidden)] #[inline] pub fn select(params: Params<'_, Ctx, T>, mut ctx: &mut Ctx) -> Result<(), Error> where Ctx: 'a, - // for<'b, 'de> SelectorSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, - for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de>, - // for<'b, 'de> BlockSelectorSeed<0, SelectorSeed<'b, Ctx, T>>: - // DeserializeSeed<'de, Value = ()>, - // for<'de> BlockSelectorSeed<0, SelectorSeed<'a, Ctx, T>>: DeserializeSeed<'de, Value = ()>, + T: Select, { let Params { cid, @@ -418,12 +528,11 @@ where ..Default::default() }; - let root = cid.ok_or_else(|| { + let root_cid = cid.ok_or_else(|| { Error::InvalidSelectionParams("selection must start against some cid") })?; - let mut codec = Multicodec::try_from(&root)?; - let block = ctx.block_reader(&root)?; - let default_selector = Self::DEFAULT_SELECTOR; + let block = ctx.block_reader(&root_cid)?; + let default_selector = Selector::DEFAULT; let seed = SelectorSeed { selector: &selector.unwrap_or(&default_selector), state: &mut state, @@ -431,7 +540,8 @@ where ctx: &mut ctx, }; - codec.read_with_seed(seed, block) + root_cid.multicodec()?.read_from_seed(seed, block)?; + Ok(()) } /// @@ -493,8 +603,50 @@ where }; state.descend::(field)?; - Ok(SelectorSeed::from(next, state, callback, ctx)) + Ok(SelectorSeed::from_parts(next, state, callback, ctx)) } + + // pub(crate) fn select_field<'b, 'de, U, D>( + // &'b mut self, + // field: Field<'b>, + // match_cb: Option + 'b>>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // 'a: 'b, + // U: Representation + Select, + // D: Deserializer<'de>, + // { + // let next = self + // .selector + // .next(Some(&field)) + // .ok_or_else(|| Error::missing_next_selector(self.selector)) + // .map_err(D::Error::custom)?; + // let callback = match (match_cb, &self.callback) { + // // + // (None, Callback::SelectNode { cb, only_matched }) => Callback::SelectNode { + // cb: cb.clone(), + // only_matched: *only_matched, + // }, + // // + // (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, + // // matching the field + // (Some(field_cb), _) => Callback::MatchDag { cb: field_cb }, + // _ => unreachable!(), + // }; + // self.state.descend::(field).map_err(D::Error::custom)?; + // + // let seed = SelectorSeed { + // selector: next, + // state: &mut self.state, + // callback, + // ctx: &mut self.ctx, + // }; + // + // U::__select_from(seed, deserializer).map_err(D::Error::custom)?; + // self.state.ascend::().map_err(D::Error::custom)?; + // Ok(()) + // } } // patch methods @@ -579,7 +731,7 @@ macro_rules! impl_selector_seed_serde { // $($bounds)* // { // type Value = (); - + // // $($visit_fns)* // } // }; @@ -606,15 +758,38 @@ macro_rules! impl_selector_seed_serde { $ty:ty { $($visit_fns:tt)* } ) => { - impl<'a, 'de, const C: u64, Ctx, $($generics)*> $crate::dev::Visitor<'de> for $crate::dev::CodedSeed<'a, C, Ctx, $ty> - where - Ctx: $crate::dev::Context, - $($bounds)* - { - type Value = (); + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = false; + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + Visitor<'de> for + CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> + where + Ctx: Context, + $($bounds)* + { + type Value = (); + $($visit_fns)* + } + }; - $($visit_fns)* - } + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = true; + // impl<'a, 'de, const _C: u64, $($generics)*> + // Visitor<'de> for + // CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // where + // $($generics)* + // { + // type Value = $ty; + // $($visit_fns)* + // } + }; }; // impl IpldVisitorExt for CodedSeed (@codec_seed_visitor_ext @@ -622,13 +797,36 @@ macro_rules! impl_selector_seed_serde { $ty:ty { $($visit_fns:tt)* } ) => { - impl<'a, 'de, const C: u64, Ctx, $($generics)*> $crate::dev::IpldVisitorExt<'de> for $crate::dev::CodedSeed<'a, C, Ctx, $ty> - where - Ctx: $crate::dev::Context, - $($bounds)* - { - $($visit_fns)* - } + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = false; + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + IpldVisitorExt<'de> for + CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> + where + Ctx: Context, + $($bounds)* + { + $($visit_fns)* + } + }; + + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = true; + // impl<'a, 'de, const _C: u64, $($generics)*> + // IpldVisitorExt<'de> for + // CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // where + // $($generics)* + // { + // $($visit_fns)* + // } + }; }; // CodecDeserializeSeed @@ -639,15 +837,59 @@ macro_rules! impl_selector_seed_serde { $ty:ty { $($deseed_fn:tt)* } ) => { - impl<'a, 'de, Ctx, $($generics)*> $crate::dev::CodecDeserializeSeed<'de> for $crate::dev::SelectorSeed<'a, Ctx, $ty> - where - Ctx: $crate::dev::Context, - $($bounds)* - { - // type Value = (); + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = false; + // impl<'_a, 'de, Ctx, $($generics)*> + // CodecDeserializeSeed<'de> for + // SelectorSeed<'_a, Ctx, $ty> + // where + // Ctx: Context, + // $($bounds)* + // { + // type Value = (); + // $($deseed_fn)* + // // CodecSeed::(self).deserialize(deserializer) + // } + + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + DeserializeSeed<'de> for + CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> + where + Ctx: Context, + // Self: Visitor<'de>, + { + // type Value = >::Value; + type Value = (); + $($deseed_fn)* + } + }; - $($deseed_fn)* - } + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _D: bool = true; + // impl<'a, 'de, $($generics)*> + // $crate::dev::CodecDeserializeSeed<'de> for + // std::marker::PhantomData<$ty> + // { + // type Value = $ty; + // $($deseed_fn)* + // } + + // impl<'de, const _C: u64 $($generics)*> + // $crate::dev::DeserializeSeed<'de> for + // $crate::dev::CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // where + // Self: $crate::dev::Visitor<'de>, + // { + // type Value = >::Value; + // $($deseed_fn)* + // } + }; }; // impl CodecDeserializeSeed for SelectorSeed, using deserialize_any (@selector_seed_codec_deseed @any @@ -658,22 +900,19 @@ macro_rules! impl_selector_seed_serde { @selector_seed_codec_deseed { $($generics)* } { $($bounds)* } $ty { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where - D: $crate::dev::Deserializer<'de>, + D: Deserializer<'de>, { - use $crate::dev::*; - // ::deserialize_any(deserializer, self) - - $crate::dev::macros::cfg_if! { + macros::cfg_if! { if #[cfg(feature = "dag-json")] { - if C == $crate::dev::DagJson::CODE { - DagJson::deserialize_any(deserializer, $crate::dev::CodecSeed::(self)) + if _C == DagJson::CODE { + DagJson::deserialize_any(deserializer, self) } else { - deserializer.deserialize_any($crate::dev::CodecSeed::(self)) + deserializer.deserialize_any(self) } } else if #[cfg(featureu = "dag-cbor")] { - if C == $crate::dev::DagCbor::CODE { + if _C == DagCbor::CODE { DagCbor::deserialize_any(deserializer, self) } else { deserializer.deserialize_any(self) @@ -693,22 +932,92 @@ macro_rules! impl_selector_seed_serde { { $($generics:tt)* } { $($bounds:tt)* } $ty:ty ) => { - impl $crate::dev::Select for $ty - where - Ctx: $crate::dev::Context, - $($bounds)* - { - #[inline] - fn select( - params: $crate::dev::Params<'_, Ctx, Self>, - ctx: &mut Ctx, - ) -> Result<(), $crate::dev::Error> { - // TODO: - $crate::dev::SelectorSeed::<'_, Ctx, Self>::select(params, ctx) - // unimplemented!() + const _: () = { + use $crate::dev::*; + + impl Select for $ty + where + Ctx: Context, + $($bounds)* + { + #[inline] + fn select( + params: Params<'_, Ctx, Self>, + ctx: &mut Ctx, + ) -> Result<(), Error> { + SelectorSeed::<'_, Ctx, Self>::select(params, ctx) + } + + #[doc(hidden)] + fn __select_from_deserializer<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = CodecSeed::::from(seed); + seed.deserialize(deserializer) + } + + #[doc(hidden)] + fn __select_from_seq<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + mut seq: A, + ) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + let seed = CodecSeed::::from(seed); + seq.next_element_seed(seed) + } + + #[doc(hidden)] + fn __select_from_map<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + mut map: A, + is_key: bool, + ) -> Result, A::Error> + where + A: MapAccess<'de>, + { + let seed = CodecSeed::::from(seed); + if is_key { + map.next_key_seed(seed) + } else { + Ok(Some(map.next_value_seed(seed)?)) + } + } } - } + }; }; + (@seed_from_params $params:ident $ctx:ident) => {{ + let Params { + cid, + selector, + max_path_depth, + max_link_depth, + callback, + } = $params; + let mut state = State { + max_path_depth, + max_link_depth, + ..Default::default() + }; + + let root = cid.ok_or_else(|| { + Error::InvalidSelectionParams("selection must start against some cid") + })?; + let block = $ctx.block_reader(&root)?; + + let default_selector = Selector::DEFAULT; + SelectorSeed { + selector: &selector.unwrap_or(&default_selector), + state: &mut state, + callback, + ctx: &mut $ctx, + } + }}; // newtype impls @@ -720,36 +1029,46 @@ macro_rules! impl_selector_seed_serde { $crate::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed { $($generics)* } { $($bounds)* } $ty { + // #[inline] + // fn deserialize(self, deserializer: D) -> Result + // where + // D: Deserializer<'de>, + // { #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> + fn deserialize(self, deserializer: D) -> Result where - D: $crate::dev::Deserializer<'de>, + D: Deserializer<'de>, { - let inner_seed = $crate::dev::macros::impl_selector_seed_serde! { - @selector_seed_wrap - // TODO: probably need to pass a closure - self { $ty => $inner_ty } - }; - - // cfg_if::cfg_if! { - // if #[cfg(feature = "serde-codec")] { - // // (&mut &mut &mut Decoder(deserializer)).deserialize_any(self) - // inner_seed.deserialize((&mut &mut &mut Decoder(deserializer))) - // } else { - // // deserializer.deserialize_any(self) - // inner_seed.deserialize(deserializer) - // } - // } - - inner_seed.deserialize::(deserializer) + if _D { + unimplemented!() + } else { + let inner_seed = macros::impl_selector_seed_serde! { + @selector_seed_wrap + // TODO: probably need to pass a closure + self { $ty => $inner_ty } + }; + + // cfg_if::cfg_if! { + // if #[cfg(feature = "serde-codec")] { + // // (&mut &mut &mut Decoder(deserializer)).deserialize_any(self) + // inner_seed.deserialize((&mut &mut &mut Decoder(deserializer))) + // } else { + // // deserializer.deserialize_any(self) + // inner_seed.deserialize(deserializer) + // } + // } + + // inner_seed.deserialize::(deserializer) + inner_seed.deserialize(deserializer) + } } }} }; // produces an seed for the inner_ty, providing the original cb with ty (@selector_seed_wrap $seed:ident { $constructor:expr => $inner_ty:ty }) => {{ - use $crate::dev::{SelectorSeed, DagSelection, Callback::*}; + use $crate::dev::{DagSelection, Callback::*}; - let (selector, state, callback, ctx) = $seed.into_parts(); + let (selector, state, callback, ctx) = $seed.0.into_parts(); let callback = match callback { SelectNode { cb, only_matched } => SelectNode { cb, only_matched }, SelectDag { mut cb } => SelectDag { @@ -761,7 +1080,7 @@ macro_rules! impl_selector_seed_serde { }, _ => unreachable!(), }; - SelectorSeed::<'_, _, $inner_ty>::from(selector, state, callback, ctx) + Self::from(SelectorSeed::from_parts(selector, state, callback, ctx)) }}; // (@empty $seed:ident $constructor:expr => $inner_ty:tt) => { unimplemented!() }; diff --git a/src/selectors/state.rs b/src/selectors/state.rs index 64dd746..1ac19d9 100644 --- a/src/selectors/state.rs +++ b/src/selectors/state.rs @@ -378,30 +378,30 @@ where // } // } - /// - pub const fn mode(&self) -> SelectionMode { - match self { - Self::SelectNode { .. } => SelectionMode::SelectNode, - Self::SelectDag { .. } | Self::MatchDag { .. } => SelectionMode::SelectDag, - // Self::Patch { .. } => SelectionMode::Patch, - } - } + // /// + // pub const fn mode(&self) -> SelectionMode { + // match self { + // Self::SelectNode { .. } => SelectionMode::SelectNode, + // Self::SelectDag { .. } | Self::MatchDag { .. } => SelectionMode::SelectDag, + // // Self::Patch { .. } => SelectionMode::Patch, + // } + // } - /// - pub const fn is_node(&self) -> bool { - match self { - Self::SelectNode { .. } => true, - _ => false, - } - } + // /// + // pub const fn is_node(&self) -> bool { + // match self { + // Self::SelectNode { .. } => true, + // _ => false, + // } + // } - /// - pub const fn is_dag(&self) -> bool { - match self { - Self::SelectDag { .. } | Self::MatchDag { .. } => true, - _ => false, - } - } + // /// + // pub const fn is_dag(&self) -> bool { + // match self { + // Self::SelectDag { .. } | Self::MatchDag { .. } => true, + // _ => false, + // } + // } pub(super) fn select_node( &mut self, diff --git a/tests/codec-fixtures.rs b/tests/codec-fixtures.rs index 0c5a220..e118070 100644 --- a/tests/codec-fixtures.rs +++ b/tests/codec-fixtures.rs @@ -6,10 +6,10 @@ use std::{ path::PathBuf, }; -const DEFAULT_CID_VERSION: Version = Version::V1; -const DEFAULT_MH: u64 = Multihash::SHA2_256; - -static CODEC_SKIPLIST: &[&str] = &[]; +static CODEC_SKIPLIST: &[&str] = &[ + // "dag-cbor", + // "dag-json", +]; static FIXTURE_SKIPLIST: &[(&str, &str)] = &[ // unfamiliar, or incorrectly/confusingly labeled ("bytes-a1", "unsupported multibase"), @@ -216,6 +216,9 @@ impl Fixture { /// Sets up a `MemoryContext` to provide the fixture's block. fn setup_ctx(&self) -> MemoryContext { + const DEFAULT_CID_VERSION: Version = Version::V1; + const DEFAULT_MH: u64 = Multihash::SHA2_256; + let mut ctx = MemoryContext::default(); let cid = ctx .add_block( @@ -235,8 +238,8 @@ impl Fixture { FixtureType::Null => self.run_for::(), FixtureType::Bool => self.run_for::(), FixtureType::Int => self.run_for::(), - // FixtureType::Float => self.run_for::(), - // FixtureType::Bytes => self.run_for::(), // none of the fixtures have the right multibase... + // FixtureType::Float => self.run_for::(), // floats arent round-tripping with dag-cbor correctly... + // FixtureType::Bytes => self.run_for::(), // none of the fixtures match the multibase... FixtureType::String => self.run_for::(), // FixtureType::Array => self.run_for::>(), // FixtureType::Map => self.run_for::>(), @@ -294,6 +297,7 @@ impl Fixture { } } + /* { // next, decode the concrete type using the Matcher selector let mut ctx = self.setup_ctx(); @@ -339,7 +343,7 @@ impl Fixture { ); } } - + */ true } From a6e583bed242efd0984b1e2d1ab73cf6099a6adc Mon Sep 17 00:00:00 2001 From: sunny-g Date: Sun, 9 Oct 2022 14:40:45 -0500 Subject: [PATCH 2/9] make typekinds a typenum, blanked deseed, other updates --- Cargo.toml | 12 +- macros-internals/Cargo.toml | 4 +- macros-internals/src/common.rs | 9 +- macros-internals/src/lib.rs | 8 +- .../src/schema/compound/expand_list.rs | 35 +- .../src/schema/compound/expand_map.rs | 78 +- macros-internals/src/schema/compound/parse.rs | 8 +- macros-internals/src/schema/expand.rs | 11 +- macros-internals/src/schema/mod.rs | 327 +++-- .../src/schema/primitive/expand.rs | 36 +- macros-internals/src/schema/struct/expand.rs | 70 +- .../src/schema/struct/expand_listpairs.rs | 4 +- .../src/schema/struct/expand_stringjoin.rs | 4 +- .../src/schema/struct/expand_stringpairs.rs | 4 +- .../src/schema/struct/expand_tuple.rs | 4 +- macros-internals/src/schema/struct/mod.rs | 4 +- macros-internals/src/schema/struct/parse.rs | 13 +- macros-internals/src/schema/union/parse.rs | 8 +- src/cid.rs | 175 +-- src/codecs/dag_cbor.rs | 4 +- src/codecs/dag_json.rs | 36 +- src/data_model/any.rs | 12 +- src/data_model/compat.rs | 128 +- src/data_model/link.rs | 162 ++- src/data_model/list.rs | 547 ++++----- src/data_model/map.rs | 491 +++++--- src/data_model/primitive.rs | 556 +++------ src/error.rs | 108 +- src/lib.rs | 38 +- src/multicodec.rs | 4 +- src/multihash.rs | 156 ++- .../mod.rs} | 271 +++-- src/selectors/context.rs | 29 +- src/selectors/mod.rs | 339 ++++-- src/selectors/seed.rs | 1048 ++++++++--------- src/selectors/selectors.rs | 391 ++++-- src/selectors/state.rs | 507 ++++---- tests/codec-fixtures.rs | 5 +- 38 files changed, 3339 insertions(+), 2307 deletions(-) rename src/{representation.rs => representation/mod.rs} (70%) diff --git a/Cargo.toml b/Cargo.toml index ccd0551..797071b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,14 +13,14 @@ path = "src/lib.rs" [dependencies] # core bytes = { version = "1.2", features = ["serde"] } -cid = { version = "0.8", features = ["alloc", "std", "serde-codec"] } +cid = { version = "0.8", features = ["alloc", "serde-codec"] } # erased-serde = { version = "0.3", features = ["std"] } # ipfs = { git = "https://github.com/ipfs-rust/rust-ipfs", branch = "master", optional = true } ipld-macros = { path = "./macros" } ipld-macros-internals = { path = "./macros-internals" } multibase = "0.9" -multihash = { version = "0.16", default-features = false, features = ["std"] } -serde = { version = "1.0", features = ["derive", "rc"] } +multihash = { version = "0.16", default-features = false } +serde = { version = "1.0", default-features = false, features = ["derive", "rc"] } # serde_repr = "0.1" thiserror = "1.0" unicode-normalization = "0.1" @@ -38,6 +38,7 @@ bitflags = "1.3" cfg-if = "1" # const-str = "0.3" # const_format = "0.2" +core2 = { version = "0.4", optional = true } delegate = { version = "0.8", optional = true } downcast-rs = "1.2" @@ -46,7 +47,10 @@ criterion = "0.4" proptest = "1.0" [features] -default = ["multicodec"] +default = ["multicodec", "std"] +std = ["cid/std", "core2/std", "multihash/std"] + +# codecs dag-cbor = ["serde_cbor"] # dag-cbor = ["cbor4ii", "delegate"] # dag-cbor = ["serde_ipld_dagcbor", "delegate"] diff --git a/macros-internals/Cargo.toml b/macros-internals/Cargo.toml index a9b6c05..94ae955 100644 --- a/macros-internals/Cargo.toml +++ b/macros-internals/Cargo.toml @@ -4,8 +4,6 @@ version = "0.0.3" authors = ["sunny-g "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] bitflags = "1.3" derive_more = "0.99" @@ -18,6 +16,8 @@ quote = "1.0" # static_assertions = "1.1.0" syn = { version = "1.0", features = ["extra-traits", "printing"] } # tylift = "0.3" +typenum = "1.15" +typenum-macro = { git = "https://github.com/paholg/typenum", branch = "proc_macro" } [dev-dependencies] syn = { version = "1.0", features = ["full"] } diff --git a/macros-internals/src/common.rs b/macros-internals/src/common.rs index d3319fa..148ef74 100644 --- a/macros-internals/src/common.rs +++ b/macros-internals/src/common.rs @@ -153,11 +153,14 @@ pub fn is_end(input: ParseStream) -> bool { input.peek(Token![;]) } -/// Parses the ending semicolon, asserting that the token stream is empty. +/// Parses on optional ending semicolon, then assert that the token stream is +/// empty. pub fn parse_end(input: ParseStream) -> ParseResult<()> { - input.parse::()?; + if input.peek(Token![;]) { + input.parse::()?; + } if !input.is_empty() { - Err(input.error("must end IPLD schema definitions with a semicolon")) + Err(input.error("unexpected tokens at the end of the IPLD schema definition")) } else { Ok(()) } diff --git a/macros-internals/src/lib.rs b/macros-internals/src/lib.rs index 42c4a43..b57a5b2 100644 --- a/macros-internals/src/lib.rs +++ b/macros-internals/src/lib.rs @@ -1,4 +1,8 @@ pub extern crate derive_more; +#[macro_use] +pub extern crate typenum; +#[macro_use] +pub extern crate typenum_macro; // #[macro_use] // pub extern crate static_assertions; @@ -17,8 +21,4 @@ pub mod dev { pub use crate::schema::{expand::*, parse::*, *}; pub use crate::selector::*; pub use crate::*; - - pub use derive_more; - // pub use static_assertions; - // pub use tylift; } diff --git a/macros-internals/src/schema/compound/expand_list.rs b/macros-internals/src/schema/compound/expand_list.rs index 97a3458..b662158 100644 --- a/macros-internals/src/schema/compound/expand_list.rs +++ b/macros-internals/src/schema/compound/expand_list.rs @@ -13,40 +13,41 @@ impl ExpandBasicRepresentation for ListReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let child_ty = self.child_ty(); - expand::impl_repr( - meta, - quote! { - // const SCHEMA: &'static str = macros::concatcp!("type ", Self::NAME, " [", <#child_ty>::NAME, "]"); - const DATA_MODEL_KIND: Kind = Kind::List; - const HAS_LINKS: bool = false; + let name = &meta.name; + let (_, child_name) = self.child_ty(); + let schema = quote! { + const SCHEMA: &'static str = concat!( + "type ", stringify!(#name), " [", #child_name, "]", + ); + }; - // fn has_links(&self) -> bool { - // self.0.has_links() - // } - }, - ) + let inner_ty = self.inner_ty(); + derive_newtype!(@repr { schema } meta => inner_ty) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); derive_newtype!(@select meta => inner_ty) - // quote!() } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { + // let dm_ty = SchemaKind::List.data_model_kind(); + // derive_newtype!(@conv self, meta => dm_ty dm_ty) quote!() } } impl ListReprDefinition { - fn child_ty(&self) -> Type { + fn child_ty(&self) -> (Type, TokenStream) { match self { - Self::Basic { elem, nullable } if *nullable => Type::Verbatim(quote!(Option<#elem>)), - Self::Basic { elem, .. } => elem.clone(), + Self::Basic { elem, nullable } if *nullable => ( + Type::Verbatim(quote!(Option<#elem>)), + quote!("nullable ", stringify!(#elem)), + ), + Self::Basic { elem, .. } => (elem.clone(), quote!(stringify!(#elem))), Self::Advanced(..) => unimplemented!(), } } fn inner_ty(&self) -> Type { - let child_ty = self.child_ty(); + let (child_ty, _) = self.child_ty(); Type::Verbatim(quote!(List<#child_ty>)) } } diff --git a/macros-internals/src/schema/compound/expand_map.rs b/macros-internals/src/schema/compound/expand_map.rs index 25d27cc..6c27856 100644 --- a/macros-internals/src/schema/compound/expand_map.rs +++ b/macros-internals/src/schema/compound/expand_map.rs @@ -13,20 +13,54 @@ impl ExpandBasicRepresentation for MapReprDefinition { match self { Self::Basic { .. } => derive_newtype!(@typedef self, meta => inner_ty), - Self::Stringpairs { .. } => unimplemented!(), - Self::Listpairs { .. } => unimplemented!(), + Self::Stringpairs { .. } => derive_newtype!(@typedef self, meta => inner_ty), + Self::Listpairs { .. } => derive_newtype!(@typedef self, meta => inner_ty), Self::Advanced(..) => unimplemented!(), } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; + let key_ty = self.key_ty(); + let (val_ty, val_name) = self.val_ty(); + let inner_ty = self.inner_ty(); let repr_kind = self.repr_kind(); - expand::impl_repr( - meta, - quote! { - const DATA_MODEL_KIND: Kind = Kind::Map; - const REPR_KIND: Kind = #repr_kind; - }, - ) + + let base_schema = quote! { + "type ", stringify!(#name), " ", + "{", stringify!(#key_ty), ":", stringify!(#val_name), "}", + }; + match self { + Self::Basic { .. } => { + let schema = quote! { + const SCHEMA: &'static str = concat!(#base_schema); + }; + derive_newtype!(@repr { schema } meta => inner_ty) + } + Self::Listpairs { .. } => { + let schema = quote! { + const SCHEMA: &'static str = + concat!(#base_schema, "representation listpairs"); + }; + derive_newtype!(@repr { schema } meta => inner_ty) + } + Self::Stringpairs { + inner_delim, + entry_delim, + .. + } => { + let schema = quote! { + const SCHEMA: &'static str = concat!( + #base_schema, + "representation stringpairs { ", + "innerDelim ", #inner_delim, " ", + "entryDelim ", #entry_delim, " ", + "}", + ); + }; + derive_newtype!(@repr { schema } meta => inner_ty) + } + _ => unimplemented!(), + } } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); @@ -50,35 +84,43 @@ impl MapReprDefinition { } } - fn val_ty(&self) -> Type { + fn val_ty(&self) -> (Type, TokenStream) { match self { Self::Basic { value, nullable, .. } - | Self::Stringpairs { + | Self::Listpairs { value, nullable, .. } - | Self::Listpairs { + | Self::Stringpairs { value, nullable, .. - } if *nullable => Type::Verbatim(quote!(Option<#value>)), + } if *nullable => ( + Type::Verbatim(quote!(Option<#value>)), + quote!("nullable ", stringify!(#value)), + ), Self::Basic { value, .. } - | Self::Stringpairs { value, .. } - | Self::Listpairs { value, .. } => value.clone(), + | Self::Listpairs { value, .. } + | Self::Stringpairs { value, .. } => (value.clone(), quote!(stringify!(#value))), Self::Advanced(..) => unimplemented!(), } } fn inner_ty(&self) -> Type { let key_ty = self.key_ty(); - let val_ty = self.val_ty(); - Type::Verbatim(quote!(Map<#key_ty, #val_ty>)) + let (val_ty, _) = self.val_ty(); + match self { + Self::Basic { .. } => Type::Verbatim(quote!(Map<#key_ty, #val_ty>)), + Self::Listpairs { .. } => Type::Verbatim(quote!(ListPairsMap<#key_ty, #val_ty>)), + Self::Stringpairs { .. } => Type::Verbatim(quote!(StringPairsMap<#key_ty, #val_ty>)), + _ => unimplemented!(), + } } fn repr_kind(&self) -> TokenStream { match self { Self::Basic { .. } => quote!(Kind::Map), - Self::Stringpairs { .. } => quote!(Kind::String), Self::Listpairs { .. } => quote!(Kind:::List), + Self::Stringpairs { .. } => quote!(Kind::String), Self::Advanced(..) => unimplemented!(), } } diff --git a/macros-internals/src/schema/compound/parse.rs b/macros-internals/src/schema/compound/parse.rs index 394205d..23e909a 100644 --- a/macros-internals/src/schema/compound/parse.rs +++ b/macros-internals/src/schema/compound/parse.rs @@ -13,11 +13,12 @@ use syn::{ impl Parse for ListReprDefinition { fn parse(input: ParseStream) -> ParseResult { // parse list typedef - let mut nullable = false; - let typedef_stream; // parse type, which may be nullable + let typedef_stream; bracketed!(typedef_stream in input); + + let mut nullable = false; if typedef_stream.peek(kw::nullable) { typedef_stream.parse::()?; nullable = true; @@ -46,13 +47,14 @@ impl Parse for ListReprDefinition { impl Parse for MapReprDefinition { fn parse(input: ParseStream) -> ParseResult { // parse map typedef - let mut nullable = false; + let typedef_stream; braced!(typedef_stream in input); // parse key let key = typedef_stream.parse::()?; // parse value, which may be nullable + let mut nullable = false; typedef_stream.parse::()?; if typedef_stream.peek(kw::nullable) { typedef_stream.parse::()?; diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index d6ff1d9..7575a58 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -350,13 +350,13 @@ macro_rules! derive_newtype { quote::quote! { impl From<#name> for SelectedNode { fn from(t: #name) -> Self { - Self::#$selected_node(t.0.into()) + Self::from(t.0) } } impl Into for #name { fn into(self) -> Any { - Any::#$dm_ty(self.0.into()) + self.0.into() } } @@ -364,7 +364,12 @@ macro_rules! derive_newtype { type Error = Error; fn try_from(any: Any) -> Result { match any { - Any::#$dm_ty(inner) => Ok(Self(inner.into())), + Any::#$dm_ty(inner) => { + let any_variant = Representation::name(&inner); + let inner = inner.try_into() + .or_else(|_| Err(Error::failed_any_conversion::(any_variant)))?; + Ok(Self(inner)) + }, _ => Err(Error::MismatchedAny) } } diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index b695116..381b16c 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -12,6 +12,7 @@ mod union; pub use compound::*; pub use expand::*; +pub use kind::{type_kinds, SchemaKind, TypedKind}; pub use parse::*; pub use primitive::*; pub use r#enum::*; @@ -135,85 +136,255 @@ impl ReprDefinition { } } -// /// -// #[derive(Debug, PartialEq, Eq, Hash)] -// pub enum SchemaKind { -// Null, -// Bool, -// Int, // same as Int128 -// Int8, -// Int16, -// Int32, -// Int64, -// Int128, -// Uint8, -// Uint16, -// Uint32, -// Uint64, -// Uint128, -// Float, // same as Float64 -// Float32, -// Float64, -// Bytes, -// String, -// List, -// Map, -// Link, -// Struct, -// Enum, -// Union, -// Copy, -// } -bitflags::bitflags! { - /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. - /// - pub struct SchemaKind: u32 { - // data model kinds - - const Null = 0b0000_0000_0000_0001; - const Bool = 0b0000_0000_0000_0010; - const Int = 0b0000_0000_0000_0100; - - const Float = 0b0000_0000_0000_1000; - const String = 0b0000_0000_0001_0000; - const Bytes = 0b0000_0000_0010_0000; - const List = 0b0000_0000_0100_0000; - const Map = 0b0000_0000_1000_0000; - const Link = 0b0000_0001_0000_0000; - - // schema kinds - - const Struct = 0b0000_0010_0000_0000; - const Enum = 0b0000_0100_0000_0000; - const Union = 0b0000_1000_0000_0000; - const Copy = 0b0001_0000_0000_0000; - - // any - - const Any = Self::Null.bits - | Self::Bool.bits - | Self::Int.bits - | Self::Float.bits - | Self::String.bits - | Self::Bytes.bits - | Self::List.bits - | Self::Map.bits - | Self::Link.bits; - - const Typed = 0b0010_0000_0000_0000; - const Int8 = 0b0100_0000_0000_0000; - const Int16 = 0b1000_0000_0000_0000; - const Int32 = 0b0000_0001_0000_0000_0000_0000; - const Int64 = 0b0000_0010_0000_0000_0000_0000; - const Int128 = 0b0000_0100_0000_0000_0000_0000; - const Uint8 = 0b0000_1000_0000_0000_0000_0000; - const Uint16 = 0b0001_0000_0000_0000_0000_0000; - const Uint32 = 0b0010_0000_0000_0000_0000_0000; - const Uint64 = 0b0100_0000_0000_0000_0000_0000; - const Uint128 = 0b1000_0000_0000_0000_0000_0000; - const Float32 = 0b0000_0001_0000_0000_0000_0000_0000_0000; - const Float64 = 0b0000_0010_0000_0000_0000_0000_0000_0000; +pub mod kind { + use super::*; + use std::ops::BitAnd; + use type_kinds::*; + use typenum::*; + use typenum_macro::tyuint; + + // /// + // #[derive(Debug, PartialEq, Eq, Hash)] + // pub enum SchemaKind { + // Null, + // Bool, + // Int, // same as Int128 + // Int8, + // Int16, + // Int32, + // Int64, + // Int128, + // Uint8, + // Uint16, + // Uint32, + // Uint64, + // Uint128, + // Float, // same as Float64 + // Float32, + // Float64, + // Bytes, + // String, + // List, + // Map, + // Link, + // Struct, + // Enum, + // Union, + // Copy, + // } + + // /// + // pub trait TypedKind { + // const KIND: SchemaKind = SchemaKind::from::(); + // const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); + // const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); + // const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); + // const IS_SCHEMA: bool = SchemaKind::Any.contains(Self::KIND); + // } + + pub trait TypedKind + where + Self: NonZero + + Unsigned + + IsLessOrEqual // replace with And: IsEqual, + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd, + { + const KIND: SchemaKind; + const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); + const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); + const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); + const IS_SCHEMA: bool = SchemaKind::Schema.contains(Self::KIND) || Self::IS_TYPED_NUM; + const IS_TYPED_NUM: bool = SchemaKind::TypedNum.contains(Self::KIND) && !Self::IS_VARIOUS; + const IS_VARIOUS: bool = !is_unary::(); + } + + impl TypedKind for T + where + T: NonZero + + Unsigned + + IsLessOrEqual + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd + + BitAnd, + // And: IsEqual, + { + const KIND: SchemaKind = SchemaKind::from_bits_truncate(T::U32); + } + + // pub trait DataModelKind: TypedKind + // where + // And: IsEqual, + // { + // } + // impl DataModelKind for T + // where + // T: TypedKind, + // // T: IsLessOrEqual, + // // T: BitAnd, + // And: IsEqual, + // { + // } + + macro_rules! def_kind { + ($( + $name:ident = $b:expr; + )*) => { + bitflags::bitflags! { + /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. + /// + #[repr(transparent)] + pub struct SchemaKind: u32 { + $(const $name = $b;)* + + const Scalar = Self::Null.bits + | Self::Bool.bits + | Self::Int.bits + | Self::Float.bits + | Self::String.bits + | Self::Bytes.bits + | Self::Link.bits; + const Recursive = Self::List.bits | Self::Map.bits; + const Any = Self::Scalar.bits | Self::Recursive.bits; + const Schema = Self::Any.bits + | Self::Struct.bits + | Self::Enum.bits + | Self::Union.bits + | Self::Copy.bits + | Self::Advanced.bits; + const TypedNum = Self::Int8.bits + | Self::Int16.bits + | Self::Int32.bits + | Self::Int64.bits + | Self::Int128.bits + | Self::Uint8.bits + | Self::Uint16.bits + | Self::Uint32.bits + | Self::Uint64.bits + | Self::Uint128.bits + | Self::Float32.bits + | Self::Float64.bits; + } + } + + pub mod type_kinds { + $(pub type $name = tyuint!($b);)* + + pub type Scalar = op!(Null | Bool | Int | Float | String | Bytes | Link); + pub type Recursive = op!(List | Map); + pub type Any = op!(Scalar | Recursive); + pub type Schema = op!(Any | Struct | Enum | Union | Copy | Advanced); + pub type TypedNum = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128 | Float32 | Float64); + + #[doc(hidden)] + pub type All = op!(Any | Schema | TypedNum); + } + + }; + // (@custom $name:ident $($kind:ident,)*) => { + // pub type $name = $crate::typenum::op!($($kind | )*); + // impl Sealed for $name {} + // } + } + + def_kind! { + Null = 0b0000_0000_0000_0001; + Bool = 0b0000_0000_0000_0010; + Int = 0b0000_0000_0000_0100; + Float = 0b0000_0000_0000_1000; + String = 0b0000_0000_0001_0000; + Bytes = 0b0000_0000_0010_0000; + List = 0b0000_0000_0100_0000; + Map = 0b0000_0000_1000_0000; + Link = 0b0000_0001_0000_0000; + // + Struct = 0b0000_0010_0000_0000; + Enum = 0b0000_0100_0000_0000; + Union = 0b0000_1000_0000_0000; + Copy = 0b0001_0000_0000_0000; + Advanced = 0b0010_0000_0000_0000; + // + Int8 = 0b0100_0000_0000_0000; + Int16 = 0b1000_0000_0000_0000; + Int32 = 0b0000_0001_0000_0000_0000_0000; + Int64 = 0b0000_0010_0000_0000_0000_0000; + Int128 = 0b0000_0100_0000_0000_0000_0000; + Uint8 = 0b0000_1000_0000_0000_0000_0000; + Uint16 = 0b0001_0000_0000_0000_0000_0000; + Uint32 = 0b0010_0000_0000_0000_0000_0000; + Uint64 = 0b0100_0000_0000_0000_0000_0000; + Uint128 = 0b1000_0000_0000_0000_0000_0000; + Float32 = 0b0000_0001_0000_0000_0000_0000_0000_0000; + Float64 = 0b0000_0010_0000_0000_0000_0000_0000_0000; + } + + impl SchemaKind { + /// Const function for determining equality between [`Kind`]s. + #[doc(hidden)] + pub const fn eq(&self, other: &Self) -> bool { + match (*self, *other) { + (Self::Null, Self::Null) + | (Self::Bool, Self::Bool) + | (Self::Int, Self::Int) + | (Self::Int8, Self::Int8) + | (Self::Int16, Self::Int16) + | (Self::Int32, Self::Int32) + | (Self::Int64, Self::Int64) + | (Self::Int128, Self::Int128) + | (Self::Uint8, Self::Uint8) + | (Self::Uint16, Self::Uint16) + | (Self::Uint32, Self::Uint32) + | (Self::Uint64, Self::Uint64) + | (Self::Uint128, Self::Uint128) + | (Self::Float, Self::Float) + | (Self::Float32, Self::Float32) + | (Self::Float64, Self::Float64) + | (Self::String, Self::String) + | (Self::Bytes, Self::Bytes) + | (Self::List, Self::List) + | (Self::Map, Self::Map) + | (Self::Link, Self::Link) + | (Self::Struct, Self::Struct) + | (Self::Enum, Self::Enum) + | (Self::Union, Self::Union) + | (Self::Copy, Self::Copy) => true, + _ => false, + } + } + + /// + pub const fn is_link(&self) -> bool { + self.contains(Self::Link) + } + + /// + pub const fn is_dm(&self) -> bool { + Self::Any.contains(*self) + } + + pub const fn from() -> Self { + Self::from_bits_truncate(K) + } + + // /// + // pub const fn is_ } + + const fn is_unary() -> bool { + T::KIND.bits.count_ones() == 1 + } + + // pub trait BitOps: BitAnd + BitOr {} + // impl BitOps for T where T: BitAnd + BitOr {} } // #[derive(Debug)] diff --git a/macros-internals/src/schema/primitive/expand.rs b/macros-internals/src/schema/primitive/expand.rs index ee7fe1f..36c0e85 100644 --- a/macros-internals/src/schema/primitive/expand.rs +++ b/macros-internals/src/schema/primitive/expand.rs @@ -89,9 +89,10 @@ impl expand::ExpandBasicRepresentation for NullReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = Self::inner_ty(); let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " null"); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " null"); }; derive_newtype!(@repr { schema } meta => inner_ty) } @@ -100,19 +101,29 @@ impl expand::ExpandBasicRepresentation for NullReprDefinition { derive_newtype!(@select meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let ident = &meta.name; + let name = &meta.name; quote! { - impl From<#ident> for SelectedNode { - fn from(t: #ident) -> Self { + impl From<#name> for SelectedNode { + fn from(t: #name) -> Self { Self::Null } } - impl Into for #ident { + impl Into for #name { fn into(self) -> Any { Any::Null(Null) } } + + impl TryFrom for #name { + type Error = Error; + fn try_from(any: Any) -> Result { + match any { + Any::Null(inner) => Ok(Self(inner)), + _ => Err(Error::MismatchedAny) + } + } + } } } } @@ -131,9 +142,10 @@ impl expand::ExpandBasicRepresentation for BoolReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = Self::inner_ty(); let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " bool"); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " bool"); }; derive_newtype!(@repr { schema } meta => inner_ty) } @@ -155,9 +167,10 @@ impl expand::ExpandBasicRepresentation for IntReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " int"); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " int"); }; derive_newtype!(@repr { schema } meta => inner_ty) } @@ -180,9 +193,10 @@ impl expand::ExpandBasicRepresentation for FloatReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " float"); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " float"); }; derive_newtype!(@repr { schema } meta => inner_ty) } @@ -211,9 +225,10 @@ impl expand::ExpandBasicRepresentation for StringReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = Self::inner_ty(); let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " string"); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " string"); }; derive_newtype!(@repr { schema } meta => inner_ty) } @@ -235,9 +250,10 @@ impl expand::ExpandBasicRepresentation for CopyReprDefinition { derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " = ", stringify!(<#inner_ty>::NAME)); + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " = ", stringify!(#inner_ty)); // #[inline] // fn name(&self) -> &'static str { diff --git a/macros-internals/src/schema/struct/expand.rs b/macros-internals/src/schema/struct/expand.rs index eca8011..477fbeb 100644 --- a/macros-internals/src/schema/struct/expand.rs +++ b/macros-internals/src/schema/struct/expand.rs @@ -82,7 +82,7 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { .as_ref() .map(|g| quote!(#g)) .unwrap_or(TokenStream::default()); - let fields: Vec = self.iter().map(field_def).collect(); + let fields = self.iter().map(StructField::field_def); quote! { #(#attrs)* @@ -93,7 +93,7 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - impl_repr(self.iter(), meta, SchemaKind::Map.data_model_kind()) + impl_repr(self, meta, &Self::dm_kind()) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() @@ -103,10 +103,16 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { } } -pub(super) fn impl_repr<'a>( - iter: impl Iterator, +impl BasicStructReprDefinition { + pub fn dm_kind() -> Ident { + SchemaKind::Map.data_model_kind() + } +} + +pub(super) fn impl_repr<'a, D: Deref>( + fields: &D, meta: &SchemaMeta, - repr_kind: Ident, + repr_kind: &Ident, ) -> TokenStream { let lib = &meta.lib; let name = &meta.name; @@ -136,37 +142,39 @@ pub(super) fn impl_repr<'a>( repr_body } -pub(crate) fn default_field_def(field: &StructField) -> TokenStream { - let attrs = &field.attrs; - let vis = &field.vis; - let key = &field.key; - let value = field_value(field); - let generics = &field.generics; +impl StructField { + pub fn default_field_def(&self) -> TokenStream { + let attrs = &self.attrs; + let vis = &self.vis; + let key = &self.key; + let value = field_value(self); + let generics = &self.generics; - quote! { - #(#attrs)* - #vis #key: #value #generics + quote! { + #(#attrs)* + #vis #key: #value #generics + } } -} -fn field_def(field: &StructField) -> TokenStream { - let attrs = &field.attrs; - let vis = &field.vis; - let key = &field.key; - let value = field_value(field); - let generics = &field.generics; + fn field_def(&self) -> TokenStream { + let attrs = &self.attrs; + let vis = &self.vis; + let key = &self.key; + let value = field_value(self); + let generics = &self.generics; - let implicit_attr = field.implicit.as_ref().map(|_| quote!(#[serde(default)])); - let rename_attr = field - .rename - .as_ref() - .map(|name| quote!(#[serde(rename = #name)])); + let implicit_attr = self.implicit.as_ref().map(|_| quote!(#[serde(default)])); + let rename_attr = self + .rename + .as_ref() + .map(|name| quote!(#[serde(rename = #name)])); - quote! { - #(#attrs)* - // #implicit_attr - // #rename_attr - #vis #key: #value #generics + quote! { + #(#attrs)* + // #implicit_attr + // #rename_attr + #vis #key: #value #generics + } } } diff --git a/macros-internals/src/schema/struct/expand_listpairs.rs b/macros-internals/src/schema/struct/expand_listpairs.rs index 90289d1..f3673e9 100644 --- a/macros-internals/src/schema/struct/expand_listpairs.rs +++ b/macros-internals/src/schema/struct/expand_listpairs.rs @@ -16,7 +16,7 @@ impl ExpandBasicRepresentation for ListpairsStructReprDefinition { let attrs = &meta.attrs; let vis = &meta.vis; let ident = &meta.name; - let fields: Vec = self.iter().map(super::expand::default_field_def).collect(); + let fields = self.iter().map(StructField::default_field_def); quote! { #(#attrs)* @@ -29,7 +29,7 @@ impl ExpandBasicRepresentation for ListpairsStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self.iter(), meta, SchemaKind::List.data_model_kind()) + super::expand::impl_repr(self, meta, &SchemaKind::List.data_model_kind()) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_stringjoin.rs b/macros-internals/src/schema/struct/expand_stringjoin.rs index 080d280..21b4551 100644 --- a/macros-internals/src/schema/struct/expand_stringjoin.rs +++ b/macros-internals/src/schema/struct/expand_stringjoin.rs @@ -16,7 +16,7 @@ impl ExpandBasicRepresentation for StringjoinStructReprDefinition { let attrs = &meta.attrs; let vis = &meta.vis; let ident = &meta.name; - let fields: Vec = self.iter().map(super::expand::default_field_def).collect(); + let fields = self.iter().map(StructField::default_field_def); quote! { #(#attrs)* @@ -30,7 +30,7 @@ impl ExpandBasicRepresentation for StringjoinStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self.iter(), meta, SchemaKind::String.data_model_kind()) + super::expand::impl_repr(self, meta, &SchemaKind::String.data_model_kind()) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_stringpairs.rs b/macros-internals/src/schema/struct/expand_stringpairs.rs index f7703d3..d1b7f59 100644 --- a/macros-internals/src/schema/struct/expand_stringpairs.rs +++ b/macros-internals/src/schema/struct/expand_stringpairs.rs @@ -16,7 +16,7 @@ impl ExpandBasicRepresentation for StringpairsStructReprDefinition { let attrs = &meta.attrs; let vis = &meta.vis; let ident = &meta.name; - let fields: Vec = self.iter().map(super::expand::default_field_def).collect(); + let fields = self.iter().map(StructField::default_field_def); quote! { #(#attrs)* @@ -30,7 +30,7 @@ impl ExpandBasicRepresentation for StringpairsStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self.iter(), meta, SchemaKind::String.data_model_kind()) + super::expand::impl_repr(self, meta, &SchemaKind::String.data_model_kind()) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_tuple.rs b/macros-internals/src/schema/struct/expand_tuple.rs index 864f020..5c11141 100644 --- a/macros-internals/src/schema/struct/expand_tuple.rs +++ b/macros-internals/src/schema/struct/expand_tuple.rs @@ -16,7 +16,7 @@ impl ExpandBasicRepresentation for TupleStructReprDefinition { let attrs = &meta.attrs; let vis = &meta.vis; let ident = &meta.name; - let fields: Vec = self.iter().map(super::expand::default_field_def).collect(); + let fields = self.iter().map(StructField::default_field_def); quote! { #(#attrs)* @@ -30,7 +30,7 @@ impl ExpandBasicRepresentation for TupleStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self.iter(), meta, SchemaKind::List.data_model_kind()) + super::expand::impl_repr(self, meta, &SchemaKind::List.data_model_kind()) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/mod.rs b/macros-internals/src/schema/struct/mod.rs index 21fc731..9285679 100644 --- a/macros-internals/src/schema/struct/mod.rs +++ b/macros-internals/src/schema/struct/mod.rs @@ -5,7 +5,7 @@ mod expand_stringpairs; mod expand_tuple; mod parse; -use crate::dev::{OuterAttributes, SchemaMeta}; +use crate::dev::{Fields, OuterAttributes, SchemaMeta}; use proc_macro2::TokenStream; use std::ops::Deref; use syn::{ @@ -97,7 +97,7 @@ pub struct AdvancedStructReprDefinition { pub rest: TokenStream, } -pub type StructFields = Punctuated; +pub type StructFields = Fields; #[derive(Debug)] pub struct StructField { diff --git a/macros-internals/src/schema/struct/parse.rs b/macros-internals/src/schema/struct/parse.rs index f3fdba3..8a1aa52 100644 --- a/macros-internals/src/schema/struct/parse.rs +++ b/macros-internals/src/schema/struct/parse.rs @@ -17,12 +17,14 @@ impl Parse for StructReprDefinition { fn parse(input: ParseStream) -> ParseResult { let typedef_stream; braced!(typedef_stream in input); - let fields: StructFields = typedef_stream.parse_terminated(StructField::parse)?; + let fields = typedef_stream.parse::()?; + // map if !input.peek(kw::representation) { return Ok(Self::Map(BasicStructReprDefinition { fields })); } + // defined representation input.parse::()?; let struct_repr = match input { // map @@ -39,6 +41,7 @@ impl Parse for StructReprDefinition { // TODO? assert that any fields do not have optional + implicit? _ if input.peek(kw::tuple) => { input.parse::()?; + if input.is_empty() | input.peek(Token![;]) { Self::Tuple(TupleStructReprDefinition { fields, @@ -58,8 +61,8 @@ impl Parse for StructReprDefinition { // stringpairs _ if input.peek(kw::stringpairs) => { input.parse::()?; - let (inner_delim, entry_delim) = parse_stringpair_args(input)?; + let (inner_delim, entry_delim) = parse_stringpair_args(input)?; Self::Stringpairs(StringpairsStructReprDefinition { fields, inner_delim, @@ -69,6 +72,7 @@ impl Parse for StructReprDefinition { // stringjoin _ if input.peek(kw::stringjoin) => { input.parse::()?; + let args; braced!(args in input); let join = parse_kwarg!(args, join => LitStr); @@ -119,6 +123,11 @@ impl Parse for StructField { return Err(input.error("invalid IPLD struct representation definition: field cannot have `optional` and `implicit` directives")); } + // parse optional comma + if input.peek(Token![,]) { + input.parse::()?; + } + Ok(StructField { attrs, vis, diff --git a/macros-internals/src/schema/union/parse.rs b/macros-internals/src/schema/union/parse.rs index c8b09a2..0fe2989 100644 --- a/macros-internals/src/schema/union/parse.rs +++ b/macros-internals/src/schema/union/parse.rs @@ -29,9 +29,9 @@ impl Parse for UnionReprDefinition { _ if input.peek(kw::envelope) => { input.parse::()?; let fields = field_input.parse()?; + let args; braced!(args in input); - let mut discriminant_key = None; let mut content_key = None; try_parse_envelope_args(&args, &mut discriminant_key, &mut content_key)?; @@ -42,6 +42,7 @@ impl Parse for UnionReprDefinition { let content_key = content_key.ok_or( args.error("invalid IPLD union envelope representation: missing `contentKey`"), )?; + Self::Envelope(EnvelopeUnionReprDefinition { fields, discriminant_key, @@ -52,9 +53,11 @@ impl Parse for UnionReprDefinition { _ if input.peek(kw::inline) => { input.parse::()?; let fields = field_input.parse()?; + let args; braced!(args in input); let discriminant_key = parse_kwarg!(args, discriminantKey => LitStr); + Self::Inline(InlineUnionReprDefinition { fields, discriminant_key, @@ -64,6 +67,7 @@ impl Parse for UnionReprDefinition { _ if input.peek(kw::byteprefix) => { input.parse::()?; let fields = field_input.parse()?; + // TODO: assert that all field types are Bytes Self::BytePrefix(BytePrefixUnionReprDefinition { fields }) } // kinded @@ -81,7 +85,7 @@ impl Parse for UnionReprDefinition { "invalid IPLD union kinded representation: schema contains non-data model types", )); } - if fields.len() != all.bits.count_ones() as usize { + if fields.len() != all.bits().count_ones() as usize { return Err(input .error("invalid IPLD union kinded representation: schema contains duplicate type fields")); } diff --git a/src/cid.rs b/src/cid.rs index 1938683..f69b898 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -1,7 +1,7 @@ use crate::dev::{macros::*, *}; use cid::Error as CidError; +use maybestd::{cmp, convert::TryFrom, fmt, hash, io, str::FromStr}; use multibase::Error as MultibaseError; -use std::{cmp, convert::TryFrom, fmt, hash, io}; /// #[derive(Copy, Clone, Debug, Eq)] @@ -48,7 +48,6 @@ impl Cid { // } /// - #[cfg(feature = "multicodec")] #[inline] pub fn multicodec(&self) -> Result { Multicodec::try_from(self.multicodec_code()) @@ -103,38 +102,25 @@ impl Cid { } /// Generates an [`Cid`] from a [`BufRead`] of a block's bytes. - pub fn new( + pub fn new( cid_version: Version, multicodec_code: u64, multihash_code: u64, - mut block: R, + block: R, ) -> Result { - let mut hasher = Multihash::try_from(multihash_code)?; - - loop { - let bytes = block.fill_buf().map_err(multihash::Error::Io)?; - match bytes.len() { - 0 => break, - len => { - hasher.update(bytes); - block.consume(len); - } - } - } - - let mh = hasher.finalize()?; - let inner = DefaultCid::new(cid_version, multicodec_code, mh)?; - Ok(Self::from(inner)) + let hasher = Multihash::try_from(multihash_code)?; + CidGenerator::new(cid_version, multicodec_code, hasher).derive(block) } /// - pub fn derive_new(&self, block: R) -> Result { + pub fn derive_new(&self, block: R) -> Result { Self::new( self.version(), self.multicodec_code(), self.multihash_code(), block, - ) + )? + .with_multibase(self.multibase) } /// @@ -192,22 +178,38 @@ impl Representation for Cid { where D: Deserializer<'de>, { - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::deserialize_cid(deserializer, CidVisitor); - } + struct CidVisitor; + impl<'de> Visitor<'de> for CidVisitor { + type Value = Cid; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "a Cid containing a multihash no longer than {} bytes", + Cid::SIZE + ) } } - cfg_if::cfg_if! { - if #[cfg(feature = "dag-cbor")] { - if C == DagCbor::CODE { - return DagCbor::deserialize_cid(deserializer, CidVisitor); - } + impl<'de> IpldVisitorExt<'de> for CidVisitor { + #[inline] + fn visit_cid(self, cid: Cid) -> Result + where + E: de::Error, + { + Ok(cid) } } - Deserialize::deserialize(deserializer) + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_cid(deserializer, CidVisitor); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::deserialize_cid(deserializer, CidVisitor); + } + + Ok(Self::from(Deserialize::deserialize(deserializer)?)) } } @@ -315,13 +317,11 @@ impl<'a> TryFrom<&'a str> for Cid { let inner = DefaultCid::try_from(s)?; let multibase = match inner.version() { Version::V0 => Multibase::Base58Btc, - _ => { - let code = s - .chars() - .next() - .ok_or_else(|| Error::Multibase(MultibaseError::InvalidBaseString))?; - Multibase::from_code(code)? - } + _ => s + .chars() + .next() + .ok_or_else(|| MultibaseError::InvalidBaseString) + .and_then(Multibase::from_code)?, }; Ok(Self { inner, multibase }) @@ -335,44 +335,27 @@ impl TryFrom for Cid { } } -/// Defaults to the `Serialize` impl of `CidGeneric`. -impl Serialize for Cid { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - // cfg_if::cfg_if! { - // if #[cfg(feature = "serde-codec")] { - // (&mut &mut &mut Encoder(serializer)).serialize_link(self) - // } else { - // self.inner.serialize(serializer) - // } - // } - // serializer.serialize_link(self) - - self.inner.serialize(serializer) +impl FromStr for Cid { + type Err = Error; + fn from_str(s: &str) -> Result { + Self::try_from(s) } } -struct CidVisitor; -impl<'de> Visitor<'de> for CidVisitor { - type Value = Cid; - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "a Cid containing a multihash no longer than {} bytes", - Cid::SIZE - ) +// TODO: support direct encoding to formatter, rather than allocating a string +impl fmt::Display for Cid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) } } -impl<'de> IpldVisitorExt<'de> for CidVisitor { - #[inline] - fn visit_cid(self, cid: Cid) -> Result + +/// Defaults to the `Serialize` impl of `CidGeneric`. +impl Serialize for Cid { + fn serialize(&self, serializer: S) -> Result where - E: de::Error, + S: Serializer, { - Ok(cid) + self.inner.serialize(serializer) } } @@ -385,6 +368,56 @@ impl<'de> Deserialize<'de> for Cid { } } +/// A generator of [`Cid`]s. +#[derive(Debug)] +pub struct CidGenerator { + version: Version, + mc_code: u64, + hasher: Multihash, +} + +impl CidGenerator { + /// + pub fn new(version: Version, multicodec_code: u64, hasher: Multihash) -> Self { + Self { + version, + mc_code: multicodec_code, + hasher, + } + } + + fn derive(mut self, mut block: R) -> Result { + io::copy(&mut block, &mut self).map_err(CidError::Io)?; + let inner = DefaultCid::new(self.version, self.mc_code, self.hasher.try_finalize()?)?; + Ok(Cid::from(inner)) + } +} + +impl multihash::Hasher for CidGenerator { + #[inline] + fn update(&mut self, input: &[u8]) { + self.hasher.update(input) + } + #[inline] + fn finalize(&mut self) -> &[u8] { + self.hasher.finalize() + } + #[inline] + fn reset(&mut self) { + self.hasher.reset() + } +} + +impl std::io::Write for CidGenerator { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.hasher.write(buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/codecs/dag_cbor.rs b/src/codecs/dag_cbor.rs index 404fb0e..2db62c6 100644 --- a/src/codecs/dag_cbor.rs +++ b/src/codecs/dag_cbor.rs @@ -93,14 +93,14 @@ impl DagCbor { #[doc(hidden)] #[inline] - pub fn read_from_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> + pub fn read_with_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> where Ctx: Context, T: Select, R: Read, { let mut de = CborDeserializer::from_reader(reader); - T::__select_from_deserializer::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) + T::__select_de::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) } // pub(crate) fn deserializer_from_reader( diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index 82de253..094d7f2 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -103,14 +103,14 @@ impl DagJson { #[doc(hidden)] #[inline] - pub fn read_from_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> + pub fn read_with_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> where Ctx: Context, T: Select, R: Read, { let mut de = JsonDeserializer::from_reader(reader); - T::__select_from_deserializer::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) + T::__select_de::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) } } @@ -343,8 +343,9 @@ mod visitor { A::Error::custom("DagJSON bytes key must be the string \"bytes\"") })?; - let byte_str = map - .next_value_seed(DeserializeWrapper::<{ DagJson::CODE }, IpldString>::default())?; + // let byte_str = map + // .next_value_seed(DeserializeWrapper::<{ DagJson::CODE }, IpldString>::default())?; + let byte_str = map.next_value::>()?; match multibase::decode(byte_str) { Ok((DagJson::DEFAULT_MULTIBASE, bytes)) => Ok(MapLikeVisitor::Bytes(bytes)), // Ok((mb, _)) => Err(de::Error::custom(format!( @@ -374,8 +375,7 @@ mod visitor { { use de::IntoDeserializer; - if self.first_key.is_some() { - let first_key = self.first_key.take().unwrap(); + if let Some(first_key) = self.first_key.take() { seed.deserialize(first_key.into_deserializer()).map(Some) } else { self.map.next_key_seed(seed) @@ -427,7 +427,7 @@ mod tests { // standard string (IpldString::from("hello world"), "\"hello world\""), // empty string TODO: - // (IpldString::default(), "\"\""), + (IpldString::default(), "\"\""), // non-standard UTF-8 string TODO: // (IpldString::from("ÅΩ"), "\"ÅΩ\""), ]; @@ -459,8 +459,13 @@ mod tests { #[test] fn test_seq() { + // raw types + let cases = &[(vec![], "[]"), (vec![1, 2], "[1,2]")]; + roundtrip_str_codec::>(DagJson::CODE, cases); + + // any types let cases = &[ - // (vec![], "[]"), + (vec![], "[]"), // (vec![Any::Int(1), Any::Int(2)], "[1,2]"), // // ( // // vec![Any::Link(Link::Cid(Default::default()).into())], @@ -472,6 +477,21 @@ mod tests { #[test] fn test_map() { + // raw types + let cases = &[ + (Default::default(), "{}"), + ( + { + let mut map: Map = Default::default(); + map.insert("abc".into(), 123i64); + map + }, + "{\"abc\":123}", + ), + ]; + roundtrip_str_codec::>(DagJson::CODE, cases); + + // any types let cases = &[]; roundtrip_str_codec::(DagJson::CODE, cases); } diff --git a/src/data_model/any.rs b/src/data_model/any.rs index 780feb0..34d28fe 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -1,6 +1,7 @@ use crate::dev::*; use macros::derive_more::{From, IsVariant, TryInto, Unwrap}; -use std::{boxed::Box, path::Path, rc::Rc}; +use maybestd::rc::Rc; +use std::path::Path; // /// // #[derive(Clone, Debug, IsVariant, Unwrap)] @@ -17,15 +18,24 @@ schema! { #[try_into(owned, ref, ref_mut)] // TODO: impl from(forward) and try_into for all unions and enums pub type Any union { + /// #[from(ignore)] | Null null + /// | Bool bool + /// | Int int + /// | Float float + /// | String string + /// | Bytes bytes + /// | List list + /// | Map map + /// // todo? should this be listed above? decoding untagged variants is attempted in def order #[ipld_attr(wrapper = "Rc")] | Link link diff --git a/src/data_model/compat.rs b/src/data_model/compat.rs index f54c586..58a1907 100644 --- a/src/data_model/compat.rs +++ b/src/data_model/compat.rs @@ -1,4 +1,34 @@ use crate::dev::*; +use maybestd::{fmt, marker::PhantomData}; + +mod ignored { + use super::*; + + impl Representation for IgnoredAny { + const NAME: &'static str = "IgnoredAny"; + const SCHEMA: &'static str = "type IgnoredAny = Any"; + const DATA_MODEL_KIND: Kind = Kind::Null; + const SCHEMA_KIND: Kind = Kind::Any; + const REPR_KIND: Kind = Kind::Any; + const __IGNORED: bool = true; + + #[doc(hidden)] + fn serialize(&self, _: S) -> Result + where + S: Serializer, + { + unreachable!() + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer) + } + } +} mod option { use super::*; @@ -8,9 +38,7 @@ mod option { T: Representation, { const NAME: &'static str = concat!("Optional", stringify!(T::NAME)); - // TODO - const SCHEMA: &'static str = unimplemented!(); - // const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); + const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; const REPR_KIND: Kind = T::REPR_KIND; @@ -38,6 +66,10 @@ mod option { } } + fn as_field(&self) -> Option> { + self.as_ref().and_then(Representation::as_field) + } + #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where @@ -54,15 +86,46 @@ mod option { where D: Deserializer<'de>, { - // DeserializeWrapper::::default().deserialize(deserializer) - unimplemented!() + struct OptionVisitor(PhantomData); + impl<'de, const C: u64, T: Representation> Visitor<'de> for OptionVisitor { + type Value = Option; + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("Optional") + } + #[inline] + fn visit_unit(self) -> Result { + Ok(None) + } + #[inline] + fn visit_none(self) -> Result { + Ok(None) + } + #[inline] + fn visit_some>( + self, + deserializer: D, + ) -> Result { + T::deserialize::(deserializer).map(Some) + } + fn __private_visit_untagged_option( + self, + deserializer: D, + ) -> Result + where + D: Deserializer<'de>, + { + Ok(T::deserialize::(deserializer).ok()) + } + } + + deserializer.deserialize_option(OptionVisitor::(PhantomData)) } } } mod wrapper { use super::*; - use std::{rc::Rc, sync::Arc}; + use maybestd::{rc::Rc, sync::Arc}; macro_rules! impl_wrapper { ($wrapper:ident) => { @@ -98,6 +161,10 @@ mod wrapper { self.as_ref().has_links() } + fn as_field(&self) -> Option> { + self.as_ref().as_field() + } + #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where @@ -114,6 +181,55 @@ mod wrapper { Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) } } + + impl Select for $wrapper + where + Ctx: Context, + T: Select + 'static, + { + // #[doc(hidden)] + // #[inline] + // fn __select<'a>(seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { + // T::__select(seed.wrap::($wrapper::from)) + // } + + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + T::__select_de::(seed.wrap::($wrapper::from), deserializer) + } + + #[doc(hidden)] + #[inline] + fn __select_seq<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + seq: A, + ) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + T::__select_seq::(seed.wrap::($wrapper::from), seq) + } + + #[doc(hidden)] + #[inline] + fn __select_map<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + map: A, + is_key: bool, + ) -> Result, A::Error> + where + A: MapAccess<'de>, + { + T::__select_map::(seed.wrap::($wrapper::from), map, is_key) + } + } }; /* (@dyn $wrapper:ident) => { impl Representation for $wrapper { diff --git a/src/data_model/link.rs b/src/data_model/link.rs index 6855876..5109a20 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -1,16 +1,17 @@ use crate::dev::*; use macros::{derive_more::From, impl_selector_seed_serde}; -use std::fmt; +use maybestd::fmt; /// #[derive( + Copy, Clone, Debug, - Eq, + Eq, // todo From, // Hash, Ord, - PartialEq, - // PartialOrd + PartialEq, // todo + // PartialOrd )] pub enum Link { /// @@ -26,11 +27,29 @@ impl Link { #[inline] pub const fn cid(&self) -> &Cid { match self { - Self::Cid(inner) => inner, + Self::Cid(cid) => cid, Self::Inner { cid, .. } => cid, } } + /// + #[inline] + pub const fn is_dirty(&self) -> bool { + match self { + Self::Cid(_) => false, + Self::Inner { dirty, .. } => *dirty, + } + } + + /// + #[inline] + pub const fn as_ref(&self) -> Option<&T> { + match self { + Self::Cid(_) => None, + Self::Inner { t, .. } => Some(t), + } + } + /* /// #[inline] @@ -67,13 +86,18 @@ impl Representation for Link { } /// - /// TODO: dirty links? #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { - Representation::serialize::(self.cid(), serializer) + if self.is_dirty() { + Err(S::Error::custom( + "cannot serialize dirty links; flush changes first", + )) + } else { + Representation::serialize::(self.cid(), serializer) + } } /// @@ -89,10 +113,7 @@ impl Representation for Link { } impl_selector_seed_serde! { @codec_seed_visitor - { T: Select + 'static } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de, Value = ()>, } - { } - Link + { T: Select + 'static } { } Link { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -101,103 +122,60 @@ impl_selector_seed_serde! { @codec_seed_visitor }} impl_selector_seed_serde! { @codec_seed_visitor_ext - { T: Select + 'static } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de, Value = ()>, } - { } - Link + { T: Select + 'static } { } Link { #[inline] fn visit_cid(self, cid: Cid) -> Result where - E: serde::de::Error, + E: de::Error, { - self.visit_link(cid) + self.0.select_link::<_C>(cid).map_err(E::custom) } }} -impl_selector_seed_serde! { @selector_seed_codec_deseed - { T: Select + 'static } - // { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } - { } - Link -{ - // #[inline] - // fn deserialize(self, deserializer: D) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // cfg_if::cfg_if! { - // if #[cfg(feature = "dag-json")] { - // if C == DagJson::CODE { - // return DagJson::deserialize_cid::<'de, D, _>(deserializer, CodecSeed::(self)); - // } - // } - // } - // cfg_if::cfg_if!{ - // if #[cfg(feature = "dag-cbor")] { - // if C == DagCbor::CODE { - // return DagCbor::deserialize_cid::<'de, D, _>(deserializer, CodecSeed::(self)); - // } - // } - // } - - // Deserialize::deserialize(deserializer) - // } - #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if _C == DagJson::CODE { - return DagJson::deserialize_cid(deserializer, self); - } - } - } - cfg_if::cfg_if!{ - if #[cfg(feature = "dag-cbor")] { - if _C == DagCbor::CODE { - return DagCbor::deserialize_cid(deserializer, self); - } - } - } - - Deserialize::deserialize(deserializer) - } -}} +// impl_selector_seed_serde! { @selector_seed_codec_deseed +// { T: Select + 'static } { } Link +// { +// #[inline] +// fn deserialize(self, deserializer: D) -> Result<(), D::Error> +// where +// D: Deserializer<'de>, +// { +// cfg_if::cfg_if! { +// if #[cfg(feature = "dag-json")] { +// if _C == DagJson::CODE { +// return DagJson::deserialize_cid(deserializer, self); +// } +// } +// } +// cfg_if::cfg_if!{ +// if #[cfg(feature = "dag-cbor")] { +// if _C == DagCbor::CODE { +// return DagCbor::deserialize_cid(deserializer, self); +// } +// } +// } +// +// Deserialize::deserialize(deserializer) +// } +// }} impl_selector_seed_serde! { @selector_seed_select - { T: Select + 'static } - // { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } - { } - Link + { T: Select + 'static } { } Link } -impl<'a, const C: u64, const D: bool, Ctx, T> CodedSelectorSeed<'a, C, D, Ctx, Link> +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, Link> where Ctx: Context, T: Select + 'static, { - fn visit_link<'de, E>(mut self, cid: Cid) -> Result<(), E> - where - E: de::Error, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, T>: DeserializeSeed<'de, Value = ()>, - { - if let Some(matcher) = self.0.selector.as_matcher() { - match self.0.mode() { - SelectionMode::SelectNode => { - self.0 - .select_matched_node(cid.into(), matcher.label.as_deref()) - .map_err(E::custom)?; - } - SelectionMode::SelectDag => { - self.0 - .select_matched_dag(Link::Cid(cid), matcher.label.as_deref()) - .map_err(E::custom)?; - } - _ => unimplemented!(), - }; + fn select_link<'de, const C: u64>(mut self, cid: Cid) -> Result<(), Error> { + if self.selector.is_matcher() { + if self.is_dag_select() { + self.select_dag(Link::Cid(cid))?; + } else { + self.select_node(cid.into())?; + } return Ok(()); } diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 802f4c6..ad9526f 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -1,12 +1,14 @@ use crate::dev::*; use macros::impl_selector_seed_serde; -use serde::de::value::SeqAccessDeserializer; -use std::{ +use maybestd::{ cell::RefCell, - fmt, + fmt, iter, marker::PhantomData, ops::{Bound, RangeBounds}, }; +use serde::de::value::SeqAccessDeserializer; + +pub use iterators::*; /// pub type List = Vec; @@ -15,6 +17,8 @@ impl Representation for List { const NAME: &'static str = "List"; const SCHEMA: &'static str = concat!("type List [", stringify!(T::NAME), "]"); const DATA_MODEL_KIND: Kind = Kind::List; + const SCHEMA_KIND: Kind = Kind::List; + const REPR_KIND: Kind = Kind::List; const HAS_LINKS: bool = T::HAS_LINKS; fn has_links(&self) -> bool { @@ -43,43 +47,35 @@ impl Representation for List { D: Deserializer<'de>, { struct ListVisitor(PhantomData); - impl Default for ListVisitor { - fn default() -> Self { - Self(PhantomData) - } - } - impl<'de, const C: u64, T: Representation> Visitor<'de> for ListVisitor { + impl<'de, const C: u64, T> Visitor<'de> for ListVisitor + where + T: Representation, + { type Value = List; #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A list of `{}`", T::NAME) } - #[inline] - fn visit_seq(self, mut seq: A) -> Result + fn visit_seq(self, seq: A) -> Result where A: SeqAccess<'de>, { let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); - while let Some(elem) = - seq.next_element_seed(DeserializeWrapper::::default())? - { - list.push(elem); + let mut iter = SerdeListIterator::<'de, A>::from(seq); + while let Some(dag) = iter.next::().map_err(A::Error::custom)? { + list.push(dag); } Ok(list) } } - deserializer.deserialize_seq(ListVisitor::::default()) + deserializer.deserialize_seq(ListVisitor::(PhantomData)) } } impl_selector_seed_serde! { @codec_seed_visitor - // { T: Representation + 'static } - { T: Select + 'static } { } - // { for<'b> CodecSeed<_C, _D, SelectorSeed<'b, Ctx, T>, T>: DeserializeSeed<'de> } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } - List + { T: Select + 'static } {} List { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -91,267 +87,167 @@ impl_selector_seed_serde! { @codec_seed_visitor where A: SeqAccess<'de>, { - if Self::D { - unimplemented!() - } else { - match self.0.selector { - Selector::Matcher(_) => self.match_list(seq), - Selector::ExploreIndex(s) => self.explore_list_range(s.index as usize..s.index as usize, seq), - Selector::ExploreRange(s) => self.explore_list_range(s.start as usize..s.end as usize, seq), - Selector::ExploreAll(_) => self.explore_list_range(0.., seq), - _ => Err(A::Error::custom(Error::unsupported_selector::>( - self.0.selector, - ))), + if let Some(s) = self.0.selector.as_explore_union() { + if s.matches_first() { + let list = >::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; + return list.__select_in(self.0).map_err(A::Error::custom); + } else { + // todo: support multiple non-overlapping ranges } } - } -}} - -impl_selector_seed_serde! { @codec_seed_visitor_ext - // { T: Representation + 'static } - { T: Select + 'static } { } - // { for<'b> CodecSeed<_C, _D, SelectorSeed<'b, Ctx, T>, T>: DeserializeSeed<'de> } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } - List {} -} - -impl_selector_seed_serde! { @selector_seed_codec_deseed - // { T: Representation + 'static } - { T: Select + 'static } { } - // { for<'b> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de, Value = ()> } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } - List -{ - // #[inline] - // fn deserialize(self, deserializer: D) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // deserializer.deserialize_seq(CodecSeed::::from(self)) - // } - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_seq(self) - } -}} - -impl_selector_seed_serde! { @selector_seed_select - // { T: Representation + 'static } // + Select - { T: Select + 'static } { } - // { for<'b, 'de> SelectorSeed<'b, Ctx, T>: CodecDeserializeSeed<'de> } - // { for<'b, 'de> CodedSelectorSeed<'b, _C, _D, Ctx, T>: DeserializeSeed<'de> } - List -} - -/* -impl<'a, 'de, Ctx, T> Visitor<'de> for ContextSeed<'a, C, List> -where - C: Context, - T: Representation + 'static, - for<'b> ContextSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, -{ - type Value = (); - #[inline] - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "{}", >::NAME) - } - - #[inline] - fn visit_seq(self, seq: A) -> Result - where - A: SeqAccess<'de>, - { - match self.selector { - Selector::Matcher(matcher) => self.match_list(matcher, seq), - Selector::ExploreIndex(s) => self.explore_list(s.index as usize..s.index as usize, seq), - Selector::ExploreRange(s) => self.explore_list(s.start as usize..s.end as usize, seq), - Selector::ExploreAll(s) => self.explore_list(0.., seq), + let iter = SerdeListIterator::<'de, _>::from(seq); + match self.0.selector { + Selector::Matcher(_) => { + self.0.match_list::<_C, T, _, _, _, _, _>( + iter, + |iter| { + let len = <_ as ListIterator>::size_hint(iter).unwrap_or(8); + RefCell::new(List::::with_capacity(len)) + }, + |dag| Box::new(|child, _| Ok(dag.borrow_mut().push(child))), + RefCell::into_inner, + ).map_err(A::Error::custom) + }, + Selector::ExploreIndex(s) => self.0 + .explore_list_range::<_C, T, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), + Selector::ExploreRange(s) => self.0 + .explore_list_range::<_C, T, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), + Selector::ExploreAll(s) => self.0 + .explore_list_range::<_C, T, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), _ => Err(A::Error::custom(Error::unsupported_selector::>( - self.selector, + self.0.selector, ))), } } -} - -impl<'a, 'de, Ctx, T> DeserializeSeed<'de> for ContextSeed<'a, C, List> -where - C: Context, - T: Representation + 'static, - for<'b> ContextSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, -{ - type Value = (); +}} - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_seq(self) - } +impl_selector_seed_serde! { @codec_seed_visitor_ext + { T: Select + 'static } {} List {} } -// TODO replace with impl_selector_seed_serde -impl<'a, Ctx, T> Select for List -where - C: Context, - T: Representation + Send + Sync + 'static, -{ - fn select(params: SelectionParams<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { - unimplemented!() - } +// impl_selector_seed_serde! { @selector_seed_codec_deseed +// { T: Select + 'static } {} List +// { +// #[inline] +// fn deserialize(self, deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// deserializer.deserialize_seq(self) +// } +// }} + +impl_selector_seed_serde! { @selector_seed_select + { T: Select + 'static } {} List } - */ -impl<'a, const C: u64, const D: bool, Ctx, T> - CodecSeed>, List> +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, - // T: Representation + 'static, T: Select + 'static, - // for<'b> CodecSeed> { /// match - fn match_list<'de, A>(mut self, mut seq: A) -> Result<(), A::Error> + /// todo could probably use a collection trait instead of multiple Fns + pub fn match_list( + mut self, + mut iter: I, + init_new_dag: F1, + mut match_cb: F2, + into_dag: F3, + ) -> Result<(), Error> where - A: SeqAccess<'de>, - // CodecSeed: DeserializeSeed<'de>, - // for<'b> CodecSeed, T>: DeserializeSeed<'de>, + U: Select, + I: ListIterator, + T2: Default, + F1: FnOnce(&I) -> T2, + for<'b> F2: FnMut(&'b T2) -> Box + 'b>, + F3: FnOnce(T2) -> T, { - let matcher = self - .0 - .selector - .as_matcher() - .expect("should know that this is a matcher"); - - // select list node, or set up list - let mode = self.0.mode(); - let mut dag: RefCell> = Default::default(); - - match mode { - SelectionMode::SelectNode => { - self.0 - .select_matched_node(SelectedNode::List, matcher.label.as_deref()) - .map_err(A::Error::custom)?; - } - SelectionMode::SelectDag => { - // set up the dag - *dag.get_mut() = List::::with_capacity(seq.size_hint().unwrap_or(8)); - } - _ => unimplemented!(), - } - - let (selector, state, mut cb, ctx) = self.0.into_parts(); + // select the matched list node, or setup the list + self.select_node(SelectedNode::List)?; + let new_dag = self + .is_dag_select() + .then(|| init_new_dag(&iter)) + .unwrap_or_default(); // select against each child - for index in 0usize.. { - let seed = SelectorSeed::field_select_seed::( - selector, - state, - &mut cb, - ctx, - index.into(), - match mode { - SelectionMode::SelectNode => None, - SelectionMode::SelectDag => { - Some(Box::new(|child, _| Ok(dag.borrow_mut().push(child)))) - } - _ => unreachable!(), - }, - ) - .map_err(A::Error::custom)?; - - // TODO call T::select_from(seed, SeqAccessDeserializer(&mut seq)) - // let is_empty = seq.next_element_seed(CodecSeed::from(seed))?.is_none(); - let is_empty = T::__select_from_seq::(seed, &mut seq)?.is_none(); - // let de = SeqAccessDeserializer::new(std::iter::from_fn(move || { - // seq.next_element_seed - // })) - state.ascend::().map_err(A::Error::custom)?; - - if is_empty { + for idx in 0usize.. { + // TODO: should be iter.next_element_seed(self.to_field_select_seed()) + if self.select_index::( + idx, + self.is_dag_select().then(|| match_cb(&new_dag)), + &mut iter, + )? { break; } } - // finally, select the matched dag - if mode == SelectionMode::SelectDag { - let mut original_seed = SelectorSeed::from_parts(selector, state, cb, ctx); - original_seed - .select_matched_dag(dag.into_inner(), matcher.label.as_deref()) - .map_err(A::Error::custom)?; + // finally, select the dag itself (if applicable) + if self.is_dag_select() { + self.select_dag(into_dag(new_dag))?; } Ok(()) } /// explore index, range, or all - fn explore_list_range<'de, A, R>(mut self, range: R, mut seq: A) -> Result<(), A::Error> + pub fn explore_list_range( + mut self, + mut iter: I, + range: R, + ) -> Result<(), Error> where - A: SeqAccess<'de>, + U: Select, + I: ListIterator, R: RangeBounds + Iterator, - // for<'b> CodecSeed, T>: DeserializeSeed<'de>, { - // select the list node - if self.0.is_node() { - self.0 - .select_node(SelectedNode::List) - .map_err(A::Error::custom)?; - } + let range_copy = (range.start_bound().cloned(), range.end_bound().cloned()); - let is_unbounded = range.end_bound() == Bound::Unbounded; - let start = match range.start_bound() { - Bound::Included(start) => *start, + let (start_idx, ignore_end_idx) = match range_copy { + (Bound::Included(start), Bound::Unbounded) => (start, None), + (Bound::Included(start), Bound::Included(i)) => (start, Some(i + 1)), + (Bound::Included(start), Bound::Excluded(i)) => (start, Some(i)), _ => unreachable!(), }; + let is_unbounded = ignore_end_idx.is_none(); + + // select the list node + self.select_node(SelectedNode::List)?; // ignore everything before the start (unless 0) // if empty, return an err - let (selector, state, mut cb, ctx) = self.0.into_parts(); - if start > 0 { - for index in 0usize..start { - if seq.next_element::()?.is_none() { - return Err(A::Error::custom(Error::explore_list_failure( - selector, index, - ))); + if start_idx > 0 { + for index in 0usize..start_idx { + if iter.next_ignored()? { + return Err(Error::explore_list_failure::(self.selector, index)); } } } // explore any/all indices in the range for index in range { - let seed = SelectorSeed::field_select_seed::( - &selector, - state, - &mut cb, - ctx, - index.into(), - None, - ) - .map_err(A::Error::custom)?; - - let is_empty = T::__select_from_seq::(seed, &mut seq)?.is_none(); - // .and_then(|seed| Ok(seq.next_element_seed(CodecSeed::from(seed))?.is_none()))?; - state.ascend::().map_err(A::Error::custom)?; + // TODO: should be iter.next_element_seed(self.to_field_select_seed()) + let is_empty = self.select_index::(index, None, &mut iter)?; // if unbounded and empty, then we're done exploring // if bounded and empty, then we failed to explore everything if is_unbounded && is_empty { return Ok(()); - } else if is_empty { - return Err(A::Error::custom(Error::explore_list_failure( - &selector, index, - ))); + } else if is_empty && range_copy.contains(&index) { + return Err(Error::explore_list_failure::(&self.selector, index)); } } // finish ignoring the remainder of the list - for _ in 0usize.. { - if seq.next_element::()?.is_none() { - break; + if !is_unbounded { + for _ in ignore_end_idx.unwrap().. { + if iter.next_ignored()? { + break; + } } } @@ -359,135 +255,138 @@ where } } -/* -impl<'a, Ctx, T> ContextSeed<'a, C, List> -where - C: Context, - T: Representation + Send + Sync + 'static, -{ - /// exploreindex - fn visit_list_index<'de, A>( - mut self, - explore_index: &ExploreIndex, - mut seq: A, - ) -> Result<(), A::Error> +mod iterators { + use super::*; + + /// A [`Select`]able list iterator over a serde sequence representation. + #[doc(hidden)] + #[derive(Debug)] + pub struct SerdeListIterator<'de, A> where A: SeqAccess<'de>, - for<'b> ContextSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, { - // select the list node - if self.params.is_node() { - self.select_node(Node::List).map_err(A::Error::custom)?; - } - - // ignore elements until index - let target_index = explore_index.index as usize; - for _ in 0usize..target_index { - if let None = seq.next_element::()? { - return Err(A::Error::custom(Error::ExploreIndexFailure( - "too few nodes to explore index", - explore_index.index as usize, - ))); - } - } - - // create the child's seed, then select the index - let (_, state, mut params, ctx) = self.into_parts(); - Self::select_at_index_seed::(&explore_index.next, state, &mut params, ctx, target_index) - .map_err(A::Error::custom) - .and_then(|seed| seq.next_element_seed(seed))?; - state.ascend::().map_err(A::Error::custom)?; + inner: A, + index: usize, + _t: PhantomData<&'de ()>, + } - // finish ignoring the remaining elements - for _ in 0usize.. { - if seq.next_element::()?.is_none() { - break; + impl<'de, A> From for SerdeListIterator<'de, A> + where + A: SeqAccess<'de>, + { + fn from(inner: A) -> Self { + Self { + inner, + index: 0, + _t: PhantomData, } } - - Ok(()) } - /// explorerange - fn visit_list_range<'de, A>( - mut self, - explore_range: &ExploreRange, - mut seq: A, - ) -> Result<(), A::Error> + impl<'de, T, A> ListIterator for SerdeListIterator<'de, A> where A: SeqAccess<'de>, - for<'b> ContextSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, { - // select the list node - if self.params.is_node() { - self.select_node(Node::List).map_err(A::Error::custom)?; + fn size_hint(&self) -> Option { + self.inner.size_hint() + } + + fn field(&self) -> Field<'_> { + Field::Index(self.index) } - // ignore elements until start - let start = explore_range.start as usize; - let end = explore_range.end as usize; - for _ in 0usize..start { - if let None = seq.next_element::()? { - return Err(A::Error::custom(Error::ExploreRangeFailure( - "too few nodes to explore range", - explore_range.start as usize, - explore_range.end as usize, - ))); + fn next_ignored(&mut self) -> Result { + let is_empty = self + .inner + .next_element::() + .map_err(|_| Error::explore_index_failure::(self.index))? + .is_none(); + if !is_empty { + self.index += 1; } + Ok(is_empty) } - // select the range - let (_, state, mut params, ctx) = self.into_parts(); - for index in start..end { - Self::select_at_index_seed::(&explore_range.next, state, &mut params, ctx, index) - .map_err(A::Error::custom) - .and_then(|seed| seq.next_element_seed(seed))?; - state.ascend::().map_err(A::Error::custom)?; + fn next(&mut self) -> Result, Error> + where + T: Representation, + { + let dag = self + .inner + .next_element_seed(DeserializeWrapper::::default()) + .map_err(|_| Error::explore_index_failure::(self.index))?; + + if dag.is_none() { + Ok(None) + } else { + self.index += 1; + Ok(dag) + } } - // finish ignoring the remaining elements - for _ in 0usize.. { - if seq.next_element::()?.is_none() { - break; + fn next_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, T>, + ) -> Result + where + T: Select, + { + let is_empty = T::__select_seq::(seed, &mut self.inner) + .map_err(|_| Error::explore_index_failure::(self.index))? + .is_none(); + if !is_empty { + self.index += 1; } + Ok(is_empty) } + } - Ok(()) + /// A [`Select`]able list iterator over an underlying iterator. + pub struct MemoryListIterator<'a, T, I> { + iter: I, + index: usize, + len: usize, + _t: PhantomData<&'a T>, } - /// exploreall - fn visit_list_all<'de, A>( - mut self, - explore_all: &ExploreAll, - mut seq: A, - ) -> Result<(), A::Error> + impl<'a, T, I> ListIterator for MemoryListIterator<'a, T, I> where - A: SeqAccess<'de>, - for<'b> ContextSeed<'b, Ctx, T>: DeserializeSeed<'de, Value = ()>, + T: Representation, + I: Iterator, { - // select the list node - if self.params.is_node() { - self.select_node(Node::List).map_err(A::Error::custom)?; + fn field(&self) -> Field<'_> { + Field::Index(self.index) } - // select the range - let (_, state, mut params, ctx) = self.into_parts(); - for index in 0usize.. { - let is_empty = - Self::select_at_index_seed::(&explore_all.next, state, &mut params, ctx, index) - .map_err(A::Error::custom) - .and_then(|seed| Ok(seq.next_element_seed(seed)?.is_none()))?; - state.ascend::().map_err(A::Error::custom)?; + fn size_hint(&self) -> Option { + Some(self.len) + } - if is_empty { - break; - } + // + fn next_ignored(&mut self) -> Result { + self.iter + .next() + .ok_or_else(|| Error::explore_index_failure::(self.index))?; + self.index += 1; + Ok(self.len == self.index) } - Ok(()) + fn next_seed<'_a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'_a, Ctx, T>, + ) -> Result + where + T: Select, + { + self.iter + .next() + .ok_or_else(|| Error::explore_index_failure::(self.index))? + .__select_in(seed)?; + self.index += 1; + Ok(self.len == self.index) + } } } - */ #[cfg(test)] mod tests { diff --git a/src/data_model/map.rs b/src/data_model/map.rs index b2be937..817444e 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -1,15 +1,19 @@ use crate::dev::*; use macros::impl_selector_seed_serde; -use std::{cell::RefCell, collections::BTreeMap, fmt}; +use maybestd::{cell::RefCell, collections::BTreeMap, fmt, iter, marker::PhantomData}; +use serde::de::value::MapAccessDeserializer; + +pub use iterators::*; /// /// TODO: indexmap? -pub type Map = BTreeMap; +pub type Map = BTreeMap; impl Representation for Map where // TODO: remove clone requirement by switching up callbacks - K: Representation + Clone + Ord + AsRef, + K: StringRepresentation, + // K: AsRef> V: Representation, { const NAME: &'static str = "Map"; @@ -34,12 +38,14 @@ where { use ser::SerializeMap; - // let mut seq = serializer.serialize_seq(Some(self.len()))?; - // for elem in self { - // seq.serialize_element(&EncoderElem::<'_, C, _>(elem))?; - // } - // seq.end() - unimplemented!() + let mut map = serializer.serialize_map(Some(self.len()))?; + for (key, val) in self { + map.serialize_entry( + &SerializeWrapper::<'_, C, _>(key), + &SerializeWrapper::<'_, C, _>(val), + )?; + } + map.end() } #[inline] @@ -48,43 +54,50 @@ where where D: Deserializer<'de>, { - // struct ListVisitor(PhantomData); - // impl Default for ListVisitor { - // fn default() -> Self { - // Self(PhantomData) - // } - // } - // impl<'de, const C: u64, T: Representation> Visitor<'de> for ListVisitor { - // type Value = List; - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "A list of `{}`", T::NAME) - // } - - // #[inline] - // fn visit_seq(self, mut seq: A) -> Result - // where - // A: SeqAccess<'de>, - // { - // let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); - // while let Some(elem) = seq.next_element_seed(DecoderElem::::default())? { - // list.push(elem); - // } - // Ok(list) - // } - // } - - // deserializer.deserialize_seq(ListVisitor::::default()) + struct MapVisitor(PhantomData<(K, V)>); + impl<'de, const C: u64, K, V> Visitor<'de> for MapVisitor + where + K: Representation + Ord, + V: Representation, + { + type Value = Map; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A map of `{}` to `{}`", K::NAME, V::NAME) + } + #[inline] + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'de>, + { + let mut new_map = Map::new(); + let mut iter = SerdeMapIterator::<'de, A>::from(map); + while let Some(key) = + as MapIterator>::next_key::(&mut iter, None) + .map_err(A::Error::custom)? + { + let val = key + .as_field() + .ok_or_else(|| Error::explore_key_failure::(None)) + .and_then(|field| { + as MapIterator>::next_value::( + &mut iter, &field, + ) + }) + .map_err(A::Error::custom)?; + new_map.insert(key, val); + } + Ok(new_map) + } + } - unimplemented!() + deserializer.deserialize_map(MapVisitor::(PhantomData)) } } impl_selector_seed_serde! { @codec_seed_visitor - { K: Select + Clone + Ord + AsRef + 'static, + { K: Select + StringRepresentation + 'static, V: Select + 'static } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, K>: DeserializeSeed<'de, Value = ()>, - // for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, V>: DeserializeSeed<'de, Value = ()>, } { } Map { @@ -93,15 +106,35 @@ impl_selector_seed_serde! { @codec_seed_visitor write!(f, "{}", Map::::NAME) } - #[inline] + #[inline] fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { + if let Some(s) = self.0.selector.as_explore_union() { + if s.matches_first() { + let map = >::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; + return map.__select_in(self.0).map_err(A::Error::custom); + } + } + + let iter = SerdeMapIterator::<'de, _>::from(map); match self.0.selector { - Selector::Matcher(_) => self.match_map(map), - Selector::ExploreFields(_) => self.explore_map_fields(map), - Selector::ExploreAll(_) => self.explore_map_all(map), + Selector::Matcher(_) => { + self.0.match_map::<_C, K, V, _, _, _, _, _>( + iter, + |iter| RefCell::>::default(), + |key, dag| Box::new(|child, _| { + dag.borrow_mut().insert(key.clone(), child); + Ok(()) + }), + RefCell::into_inner, + ).map_err(A::Error::custom) + }, + Selector::ExploreFields(_) => self.0 + .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), + Selector::ExploreAll(_) => self.0 + .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), _ => Err(A::Error::custom(Error::unsupported_selector::>( self.0.selector, ))), @@ -110,163 +143,287 @@ impl_selector_seed_serde! { @codec_seed_visitor }} impl_selector_seed_serde! { @codec_seed_visitor_ext - { K: Select + Clone + Ord + AsRef + 'static, + { K: Select + StringRepresentation + 'static, V: Select + 'static } - // { for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, K>: DeserializeSeed<'de, Value = ()>, - // for<'b> CodedSelectorSeed<'b, _C, _D, Ctx, V>: DeserializeSeed<'de, Value = ()>, } - { } - Map {} + {} Map {} } -impl_selector_seed_serde! { @selector_seed_codec_deseed - { K: Select + Clone + Ord + AsRef + 'static, - V: Select + 'static } - // { for<'b> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de, Value = ()>, - // for<'b> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de, Value = ()>, } - { } - Map -{ - // #[inline] - // fn deserialize(self, deserializer: D) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // deserializer.deserialize_map(CodecSeed::(self)) - // } - #[inline] - fn deserialize(self, deserializer: D) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - deserializer.deserialize_map(self) - } -}} +// impl_selector_seed_serde! { @selector_seed_codec_deseed +// { K: Select + StringRepresentation + 'static, +// V: Select + 'static } +// {} Map +// { +// #[inline] +// fn deserialize(self, deserializer: D) -> Result<(), D::Error> +// where +// D: Deserializer<'de>, +// { +// deserializer.deserialize_map(self) +// } +// }} impl_selector_seed_serde! { @selector_seed_select - { K: Select + Clone + Ord + AsRef + 'static, + { K: Select + StringRepresentation + 'static, V: Select + 'static } - // { for<'b, 'de> SelectorSeed<'b, Ctx, K>: CodecDeserializeSeed<'de, Value = ()>, - // for<'b, 'de> SelectorSeed<'b, Ctx, V>: CodecDeserializeSeed<'de, Value = ()>, } - { } - Map + {} Map } -impl<'a, const C: u64, const D: bool, Ctx, K, V> CodedSelectorSeed<'a, C, D, Ctx, Map> +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, - K: Select + Clone + Ord + AsRef + 'static, - V: Select + 'static, + T: Select + 'static, { /// - pub(crate) fn match_map<'de, A>(mut self, mut map: A) -> Result<(), A::Error> + pub fn match_map( + mut self, + mut iter: I, + init_new_dag: F1, + mut match_cb: F2, + into_dag: F3, + ) -> Result<(), Error> where - A: MapAccess<'de>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, + K: Select + StringRepresentation, + V: Select, + I: MapIterator, + T2: Default + 'static, + F1: FnOnce(&I) -> T2, + for<'b> F2: FnMut(&'b K, &'b T2) -> Box + 'b>, + F3: FnOnce(T2) -> T, { - let matcher = self - .0 - .selector - .as_matcher() - .expect("should know that this is a matcher"); - - let mode = self.0.mode(); - let dag: RefCell> = Default::default(); - - match mode { - SelectionMode::SelectNode => { - self.0 - .select_matched_node(SelectedNode::Map, matcher.label.as_deref()) - .map_err(A::Error::custom)?; - } - SelectionMode::SelectDag => (), - _ => unimplemented!(), - } - - let (selector, state, mut params, ctx) = self.0.into_parts(); + // select the matched node, or set up the dag + self.select_node(SelectedNode::Map)?; + let new_dag = self + .is_dag_select() + .then(|| init_new_dag(&iter)) + .unwrap_or_default(); // select against each child - while let Some(key) = map.next_key_seed(DeserializeWrapper::::default())? { - let seed = SelectorSeed::field_select_seed::( - selector, - state, - &mut params, - ctx, - key.as_ref().into(), - match mode { - SelectionMode::SelectNode => None, - SelectionMode::SelectDag => Some(Box::new(|child, _| { - dag.borrow_mut().insert(key.clone(), child); - Ok(()) - })), - _ => unreachable!(), - }, - ) - .map_err(A::Error::custom)?; + while let Some(key) = iter.next_key::(None)? { + self.select_field::( + self.is_dag_select().then(|| match_cb(&key, &new_dag)), + &mut iter, + )?; + } - V::__select_from_map::(seed, &mut map, false)?; + // // let mut seed = self; + // // let match_cb = &mut match_cb; + // loop { + // // let seed = self.to_field_select_seed(field, match_cb) + // // let mut seed = self; + // if iter.next_entry_seed::(|key| { + // let field = key + // .as_field() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // self.to_field_select_seed( + // &field, + // self.is_dag_select().then(|| match_cb(&key, &new_dag)), + // ) + // })? { + // break; + // } + // } - state.ascend::().map_err(A::Error::custom)?; - } + // TODO: should be iter.next_entry_seed(|key| self.to_field_select_seed()) + // while !iter.next_entry_seed::(&mut self)? {} // finally, select the matched dag - if mode == SelectionMode::SelectDag { - let mut original_seed = SelectorSeed::from_parts(selector, state, params, ctx); - original_seed - .select_matched_dag(dag.into_inner(), matcher.label.as_deref()) - .map_err(A::Error::custom)?; + if self.is_dag_select() { + self.select_dag(into_dag(new_dag))?; } Ok(()) } /// - pub(crate) fn explore_map_fields<'de, A>(self, mut map: A) -> Result<(), A::Error> + pub(crate) fn explore_map_fields(self, mut iter: I) -> Result<(), Error> where - A: MapAccess<'de>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, + K: Select + StringRepresentation + 'static, + V: Select + 'static, + I: MapIterator, { unimplemented!() } +} + +// pub(crate) fn match_map(seed: SelectorSeed<'_, Ctx, T>, mut iter: I) -> Result<(), Error> +// where +// I: MapReprIterator, +// { + +// } + +mod iterators { + use super::*; /// - pub(crate) fn explore_map_all<'de, A>(self, mut map: A) -> Result<(), A::Error> + #[doc(hidden)] + #[derive(Debug)] + pub struct SerdeMapIterator<'de, A> where A: MapAccess<'de>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, K>: DeserializeSeed<'de, Value = ()>, - // for<'b> CodedSelectorSeed<'b, C, D, Ctx, V>: DeserializeSeed<'de, Value = ()>, { - unimplemented!() + inner: A, + _t: PhantomData<&'de ()>, } -} -// impl<'de, 'a, C, K, V> DeserializeSeed<'de> for ContextSeed<'a, C, Map> -// where -// C: Context, -// K: Representation + Ord + 'static, -// V: Representation + 'static, -// // ContextSeed<'a, C, V, W>: DeserializeSeed<'de, Value = Option>, -// // ContextSeed<'a, C, Map>: Visitor<'de, Value = ()>, -// { -// type Value = (); -// -// #[inline] -// fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// deserializer.deserialize_map(self) -// } -// } -// -// impl<'a, C, K, V> Select for Map -// where -// C: Context, -// K: Representation + Ord + 'static, -// V: Representation + Send + Sync + 'static, -// { -// fn select(params: SelectionParams<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { -// unimplemented!() -// } -// } + impl<'de, A> From for SerdeMapIterator<'de, A> + where + A: MapAccess<'de>, + { + fn from(inner: A) -> Self { + Self { + inner, + _t: PhantomData, + } + } + } + + impl<'de, K, V, A> MapIterator for SerdeMapIterator<'de, A> + where + A: MapAccess<'de>, + { + fn size_hint(&self) -> Option { + self.inner.size_hint() + } + + fn field(&self) -> Field<'_> { + unimplemented!() + } + + fn next_key( + &mut self, + expected_field_name: Option<&'static str>, + ) -> Result, Error> + where + K: Representation, + { + let key = self + .inner + .next_key_seed(DeserializeWrapper::::default()) + .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; + + // TODO: assert that key == expected_field_name + Ok(key) + } + + fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { + self.inner + .next_value::() + .or_else(|_| Err(Error::explore_value_failure::(field)))?; + Ok(()) + } + + fn next_value(&mut self, field: &Field<'_>) -> Result + where + V: Representation, + { + self.inner + .next_value_seed(DeserializeWrapper::::default()) + .or_else(|_| Err(Error::explore_value_failure::(field))) + } + + fn next_value_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + // field: &Field<'_>, + ) -> Result<(), Error> + where + K: Representation, + V: Select, + { + // let key = >::key(self); + // let field = Representation::as_field(key); + // let field = self.field(); + // let err = || Error::explore_value_failure::(field); + + // V::__select_map::(seed, &mut self.inner, false) + // .ok() + // .flatten() + // .ok_or_else(|| Error::explore_value_failure::(field)) + unimplemented!() + } + } + + struct MemoryMapIterator<'a, K, V, I> { + iter: I, + // index: usize, + _t: PhantomData<&'a (K, V)>, + } + + impl<'a, K, V, I> MemoryMapIterator<'a, K, V, I> { + // const fn is_last(&self) -> bool { + // self.len == self.index + 1 + // } + } + + impl<'a, K, V, I> MapIterator for MemoryMapIterator<'a, K, V, I> + where + K: Representation, + V: Representation, + I: Iterator + iter::ExactSizeIterator, + { + fn size_hint(&self) -> Option { + Some(self.iter.len()) + } + + fn field(&self) -> Field<'_> { + unimplemented!() + } + + fn next_key( + &mut self, + expected_field_name: Option<&'static str>, + ) -> Result, Error> + where + K: Representation, + { + // let key = self + // .inner + // .next_key_seed(DeserializeWrapper::::default()) + // .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; + + // // TODO: assert that key == expected_field_name + // Ok(key) + unimplemented!() + } + + fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { + // self.inner + // .next_value::() + // .or_else(|_| Err(Error::explore_value_failure::(field)))?; + // Ok(()) + unimplemented!() + } + + fn next_value(&mut self, field: &Field<'_>) -> Result + where + V: Representation, + { + // self.inner + // .next_value_seed(DeserializeWrapper::::default()) + // .or_else(|_| Err(Error::explore_value_failure::(field))) + unimplemented!() + } + + fn next_value_seed<'b, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'b, Ctx, V>, + // field: &Field<'_>, + ) -> Result<(), Error> + where + K: Representation, + V: Select, + { + // let key = >::key(self); + // let field = Representation::as_field(key); + // let field = self.field(); + // let err = || Error::explore_value_failure::(field); + + // V::__select_map::(seed, &mut self.inner, false) + // .ok() + // .flatten() + // .ok_or_else(|| Error::explore_value_failure::(field)) + unimplemented!() + } + } +} diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index b89c001..d0fe89f 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -3,7 +3,7 @@ use macros::{ derive_more::{AsMut, AsRef, Deref, DerefMut, From, Index, IndexMut, Into, IntoIterator}, impl_selector_seed_serde, }; -use std::{borrow::Cow, fmt, ops::RangeBounds, str::FromStr}; +use maybestd::{borrow::Cow, fmt, str::FromStr}; pub use self::bool::Bool; pub use self::bytes::Bytes; @@ -33,7 +33,6 @@ mod null { where S: Serializer, { - // TODO: none or unit? serializer.serialize_none() } @@ -49,8 +48,8 @@ mod null { impl_selector_seed_serde! { @codec_seed_visitor {} {} Null { #[inline] - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "Null") + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", Null::NAME) } #[inline] @@ -58,7 +57,7 @@ mod null { where E: de::Error, { - self.match_primitive(Null) + self.0.select_primitive::<_C>(Null).map_err(E::custom) } #[inline] @@ -72,15 +71,30 @@ mod null { impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Null {} } - impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Null { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_unit(self) - } - }} + // impl_selector_seed_serde! { @codec_seed_visitor_rk Null + // { T: From + 'static } {} T + // { + // #[inline] + // fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // write!(f, "{}, a nothing type", T::NAME) + // } + + // #[inline] + // fn visit_none(self) -> Result + // where + // E: de::Error, + // { + // self.0.select_primitive::<_C>(T::from(Null)).map_err(E::custom) + // } + + // #[inline] + // fn visit_unit(self) -> Result + // where + // E: de::Error, + // { + // self.visit_none() + // } + // }} impl_selector_seed_serde! { @selector_seed_select {} {} Null } } @@ -116,7 +130,7 @@ mod bool { impl_selector_seed_serde! { @codec_seed_visitor {} {} Bool { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A boolean type") + write!(f, "{}, a boolean type", Bool::NAME) } #[inline] @@ -124,21 +138,46 @@ mod bool { where E: de::Error, { - self.match_primitive(v) + if self.0.selector.is_explore_union() { + v.__select_in(self.0).map_err(E::custom) + } else { + self.0.match_primitive::<_C>(v).map_err(E::custom) + } } }} impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bool {} } - impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bool { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_bool(self) - } - }} + // impl_selector_seed_serde! { @codec_seed_visitor_rk Bool + // { T: From } {} T + // { + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "{}, a boolean type", Bool::NAME) + // } + + // #[inline] + // fn visit_bool(self, v : bool) -> Result + // where + // E: de::Error, + // { + // if self.0.selector.is_explore_union() { + // T::from(v).__select_in(self.0).map_err(E::custom) + // } else { + // self.0.match_primitive::<_C>(T::from(v)).map_err(E::custom) + // } + // } + // }} + + // impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bool { + // #[inline] + // fn deserialize(self, deserializer: D) -> Result + // where + // D: Deserializer<'de>, + // { + // deserializer.deserialize_bool(self) + // } + // }} impl_selector_seed_serde! { @selector_seed_select {} {} Bool } } @@ -148,21 +187,23 @@ mod num { /// Implements IPLD traits for native number types. macro_rules! impl_ipld_num { - ( $doc_str:expr ; - $ty:ident : $name:ident $kind:ident $ipld_type:ident { + ( $ty:ident : $name:ident $kind:ident { $deserialize_fn:ident $visit_fn:ident @conv { $($other_ty:ty : $other_visit_fn:ident)* } } ) => { - #[doc = $doc_str] + #[doc = concat!("a fixed-length number type represented as a(n)", stringify!($ty))] pub type $name = $ty; impl Representation for $ty { const NAME: &'static str = stringify!($name); - const SCHEMA: &'static str = - concat!("type ", stringify!($name), " ", stringify!($ipld_type)); + const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); const DATA_MODEL_KIND: Kind = Kind::$kind; + const SCHEMA_KIND: Kind = Kind::$name; + const REPR_KIND: Kind = Kind::$kind; + + impl_ipld_num!(@field $kind $ty); #[doc(hidden)] fn serialize(&self, serializer: S) -> Result @@ -184,7 +225,7 @@ mod num { impl_selector_seed_serde! { @codec_seed_visitor {} {} $ty { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, $doc_str) + write!(f, "{}, a fixed-length number type represented as a(n) {}", <$ty>::NAME, stringify!($ty)) } #[inline] @@ -192,7 +233,7 @@ mod num { where E: de::Error, { - self.match_primitive(v) + self.0.select_primitive::<_C>(v).map_err(E::custom) } $( @@ -201,31 +242,26 @@ mod num { where E: de::Error, { - let n = <$ty as Deserialize<'_>>::deserialize(v.into_deserializer())?; - self.match_primitive(n) + let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; + self.$visit_fn(n) } )* }} impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } - impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} $ty { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.$deserialize_fn(self) - } - }} - impl_selector_seed_serde! { @selector_seed_select {} {} $ty } }; + (@field Int $ty:ty) => { + fn as_field(&self) -> Option> { + usize::try_from(*self).ok().map(Field::Index) + } + }; + (@field Float $ty:ty) => {}; } impl_ipld_num! ( - "A fixed-length number type represented as a int8"; - i8 : Int8 Int int8 { + i8 : Int8 Int { deserialize_i8 visit_i8 @conv { @@ -235,8 +271,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a int16" ; - i16 : Int16 Int int16 { + i16 : Int16 Int { deserialize_i16 visit_i16 @conv { @@ -246,8 +281,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a int32" ; - i32 : Int32 Int int32 { + i32 : Int32 Int { deserialize_i32 visit_i32 @conv { @@ -257,8 +291,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a int64" ; - i64 : Int64 Int int64 { + i64 : Int64 Int { deserialize_i64 visit_i64 @conv { @@ -268,8 +301,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a int128" ; - i128 : Int128 Int int128 { + i128 : Int128 Int { deserialize_i128 visit_i128 @conv { @@ -279,8 +311,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a uint8" ; - u8 : Uint8 Int uint8 { + u8 : Uint8 Int { deserialize_u8 visit_u8 @conv { @@ -290,8 +321,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a uint16" ; - u16 : Uint16 Int uint16 { + u16 : Uint16 Int { deserialize_u16 visit_u16 @conv { @@ -301,8 +331,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a uint32" ; - u32 : Uint32 Int uint32 { + u32 : Uint32 Int { deserialize_u32 visit_u32 @conv { @@ -312,8 +341,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a uint64" ; - u64 : Uint64 Int uint64 { + u64 : Uint64 Int { deserialize_u64 visit_u64 @conv { @@ -323,8 +351,7 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a uint128" ; - u128 : Uint128 Int uint128 { + u128 : Uint128 Int { deserialize_u128 visit_u128 @conv { @@ -334,16 +361,14 @@ mod num { } ); impl_ipld_num! ( - "A fixed-length number type represented as a float32" ; - f32 : Float32 Float float32 { + f32 : Float32 Float { deserialize_f32 visit_f32 @conv { f64:visit_f64 } } ); impl_ipld_num! ( - "A fixed-length number type represented as a float64" ; - f64 : Float64 Float float64 { + f64 : Float64 Float { deserialize_f64 visit_f64 @conv { f32:visit_f32 } @@ -382,6 +407,7 @@ mod string { pub struct IpldString(String); impl IpldString { + /// pub fn as_str(&self) -> &str { self.0.as_str() } @@ -392,6 +418,10 @@ mod string { const SCHEMA: &'static str = "type String string"; const DATA_MODEL_KIND: Kind = Kind::String; + fn as_field(&self) -> Option> { + Some(self.0.as_str().into()) + } + #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where @@ -421,49 +451,31 @@ mod string { where E: de::Error, { - if Self::is_select() { - self.match_primitive(IpldString::from(s)) - } else { - unimplemented!() - } + let v = IpldString::from(s); + self.0.select_primitive::<_C>(v).map_err(E::custom) } - // TODO: #[inline] fn visit_string(self, s: String) -> Result where E: de::Error, { - if Self::is_select() { - self.match_primitive(IpldString::from(s)) - } else { - unimplemented!() - } + self.visit_str(s.as_ref()) } }} impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} IpldString {} } - impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} IpldString { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_string(self) - } - }} - impl_selector_seed_serde! { @selector_seed_select {} {} IpldString } - impl<'a> From<&'a str> for IpldString { + impl From<&str> for IpldString { #[inline] - fn from(s: &'a str) -> Self { + fn from(s: &str) -> Self { Self(s.nfc().collect::()) } } - impl<'a> From<&'a mut str> for IpldString { - fn from(s: &'a mut str) -> Self { + impl From<&mut str> for IpldString { + fn from(s: &mut str) -> Self { Self::from(&*s) } } @@ -492,72 +504,16 @@ mod string { impl fmt::Display for IpldString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.as_str()) + self.0.fmt(f) } } } mod bytes { use super::*; - use crate::dev::bytes::Bytes as InnerBytes; - - /// A `bytes` type, which thinly wraps [`bytes::Bytes`]. - /// - /// [`Bytes`]: bytes::Bytes - #[derive( - AsRef, - AsMut, - Clone, - Debug, - Default, - Deref, - Eq, - From, - Hash, - Index, - IndexMut, - IntoIterator, - Ord, - PartialOrd, - PartialEq, - )] - #[as_ref(forward)] - #[as_mut(forward)] - #[deref(forward)] - #[from(forward)] - pub struct Bytes(InnerBytes); - - impl Bytes { - /// - pub const fn new() -> Self { - Self(InnerBytes::new()) - } - - /// - pub fn copy_from_slice(bytes: &[u8]) -> Self { - Self(InnerBytes::copy_from_slice(bytes)) - } - - /// - pub const fn len(&self) -> usize { - self.0.len() - } - - /// - pub const fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// - pub fn slice(&self, range: impl RangeBounds) -> Self { - Self(self.0.slice(range)) - } - /// - pub fn clear(&mut self) { - self.0.clear() - } - } + /// A bytes type. + pub type Bytes = crate::dev::bytes::Bytes; impl Representation for Bytes { const NAME: &'static str = "Bytes"; @@ -569,12 +525,9 @@ mod bytes { where S: Serializer, { - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::serialize_bytes(self.as_ref(), serializer); - } - } + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::serialize_bytes(self.as_ref(), serializer); } Serialize::serialize(self.as_ref(), serializer) @@ -604,19 +557,15 @@ mod bytes { where E: de::Error, { - Ok(Self::Value::from(bytes.into_boxed_slice())) + Ok(Self::Value::from(bytes)) } } - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, BytesVisitor); - } - } + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_bytes(deserializer, BytesVisitor); } - - Ok(Self::from(Box::<[u8]>::deserialize(deserializer)?)) + deserializer.deserialize_bytes(BytesVisitor) } } @@ -631,12 +580,7 @@ mod bytes { where E: de::Error, { - if Self::is_select() { - self.select_bytes(bytes) - } else { - // Ok(Self::Value::from(bytes)) - unimplemented!() - } + self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) } #[inline] @@ -644,243 +588,97 @@ mod bytes { where E: de::Error, { - if Self::is_select() { - self.select_bytes(&bytes) - } else { - // Ok(Self::Value::from(bytes)) - unimplemented!() - } + self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) } }} impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bytes {} } - impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bytes { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if _C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, self); - } - } - } - - deserializer.deserialize_bytes(self) - } - }} - impl_selector_seed_serde! { @selector_seed_select {} {} Bytes } - impl<'a, const C: u64, const D: bool, Ctx> CodedSelectorSeed<'a, C, D, Ctx, Bytes> + impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> where Ctx: Context, { + /// #[inline] - fn select_bytes(mut self, bytes: &[u8]) -> Result<(), E> - where - E: de::Error, - { - match self.0.selector { - Selector::Matcher(matcher) => { - let bytes = matcher - .subset - .as_ref() - .map(|Slice { from, to }| &bytes[*from as usize..*to as usize]) - .unwrap_or(bytes); - - match self.0.mode() { - SelectionMode::SelectNode => { - self.0 - .select_matched_node(bytes.into(), matcher.label.as_deref()) - .map_err(E::custom)?; - } - SelectionMode::SelectDag => { - self.0 - .select_matched_dag( - Bytes::copy_from_slice(bytes), - matcher.label.as_deref(), - ) - .map_err(E::custom)?; - } - _ => unimplemented!(), - } - - // self.nodes.push_back(NodeRow::Match { - // repr: Adl::Bytes, - // path: self.path.clone(), - // value: Value::Blob(bytes.into()), - // }); - - todo!(); + pub fn select_bytes(mut self, bytes: Bytes) -> Result<(), Error> { + // if let Some(s) = self.selector.as_explore_union() { + // s.assert_matches_first::()?; + // bytes.__select_in(self) + // } else { + // self.match_primitive::(raw) + // } + + if let Some(matcher) = self.selector.as_matcher() { + let bytes = matcher + .subset + .as_ref() + .map(|slice| bytes.slice(slice.to_range())) + .unwrap_or(bytes); + + if self.is_node_select() { + self.select_node(bytes.into())?; + } else if self.is_dag_select() { + self.select_dag(bytes)?; + }; + + return Ok(()); + } - Ok(()) - } - Selector::ExploreInterpretAs(inner) => { + match self.selector { + Selector::ExploreInterpretAs(_) => { todo!("what reprs and ADLs are interpreted from byte nodes?") } - selector => Err(Error::unsupported_selector::(&selector)).map_err(E::custom), + selector => Err(Error::unsupported_selector::(&selector)), } } } +} - // impl Serialize for Bytes { - // fn serialize(&self, serializer: S) -> Result - // where - // S: Serializer, - // { - // serializer.serialize_bytes(self.as_ref()) - // } - // } - - // struct BytesVisitor; - // // impl<'de> IpldVisitorExt<'de> for BytesVisitor {} - // impl<'de> Visitor<'de> for BytesVisitor { - // type Value = Bytes; - // #[inline] - // fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(formatter, "A slice of bytes") - // } - // #[inline] - // fn visit_bytes(self, bytes: &[u8]) -> Result - // where - // E: de::Error, - // { - // Ok(Self::Value::copy_from_slice(bytes)) - // } - // #[inline] - // fn visit_byte_buf(self, bytes: Vec) -> Result - // where - // E: de::Error, - // { - // Ok(Self::Value::from(bytes.into_boxed_slice())) - // } - // } +enum Assert {} +trait IsTrue {} +impl IsTrue for Assert {} - // impl<'de> Deserialize<'de> for Bytes { - // fn deserialize(deserializer: D) -> Result - // where - // D: Deserializer<'de>, - // { - // deserializer.deserialize_bytes(BytesVisitor) - // } - // } -} +// impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed, T> +// where +// Ctx: Context, +// T: Representation + 'static, +// Assert<{ (Kind::Scalar.bits() & RK) == RK }>: IsTrue, +// { +// } -impl<'a, const C: u64, const D: bool, Ctx, T> CodedSelectorSeed<'a, C, D, Ctx, T> +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, T: Representation + 'static, { - #[inline] - fn match_primitive<'de, E>(mut self, dag: T) -> Result<(), E> + /// + pub fn select_primitive(self, raw: T) -> Result<(), Error> where - T: Into, - E: de::Error, + T: Select, { - let matcher = self - .0 - .selector - .as_matcher() - .expect("should know that this is a matcher"); - - match self.0.mode() { - SelectionMode::SelectNode => { - self.0 - .select_matched_node(dag.into(), matcher.label.as_deref()) - .map_err(E::custom)?; - } - SelectionMode::SelectDag => { - self.0 - .select_matched_dag(dag, matcher.label.as_deref()) - .map_err(E::custom)?; - } - _ => unimplemented!(), + if let Some(s) = self.selector.as_explore_union() { + s.assert_matches_first::()?; + raw.__select_in(self) + } else { + self.match_primitive::(raw) } - - Ok(()) } -} -// /// Implements selection (matching) for primitive types. -// #[inline] -// pub fn primitive_select<'a, 'de, C, T, S>( -// selector: &Selector, -// state: SelectorState, -// ctx: &mut C -// ) -> Result, Error> -// where -// C: Context, -// T: Representation, -// S: Representation, -// ContextSeed<'a, C, S, S>: DeserializeSeed<'de, Value = Option>, -// // Node: From, -// { -// // if type_eq::() { -// // T::r#match(selector, state, ctx) -// // } else { -// // Err(Error::invalid_type_selection::()) -// // } -// -// // const are_eq: bool = type_eq::(); -// // static_assertions::const_assert!(type_eq::()); -// -// // unimplemented!() -// } + #[inline] + fn match_primitive<'de, const C: u64>(mut self, dag: T) -> Result<(), Error> { + self.selector.try_as_matcher()?; -// /// Implements patch selection for primitive types. -// #[inline] -// pub fn primitive_patch( -// self_: &mut T, -// selector: &Selector, -// _state: SelectorState, -// dag: T, -// _ctx: &mut C, -// ) -> Result<(), Error> -// where -// T: Select, -// C: Context, -// Node: From, -// { -// match selector { -// Selector::Matcher(Matcher { .. }) => { -// *self_ = dag; -// Ok(()) -// } -// _ => Err(Error::unsupported_selector::(selector)), -// } -// } + if self.is_node_select() { + self.select_node(dag.to_selected_node())?; + } else if self.is_dag_select() { + self.select_dag(dag)?; + }; -// fn primitive_select_base( -// seed: SelectorState, -// ctx: &mut C, -// on_matched: F, -// ) -> Result -// where -// T: Select, -// C: Context, -// F: Fn(&SelectorState, T, &Option) -> Result, -// Node: From, -// { -// let deserializer = ctx.path_decoder(seed.path())?; -// let selector = seed.as_selector(); -// -// match selector { -// Selector::Matcher(Matcher { ref label, .. }) => { -// let inner = ::deserialize(deserializer) -// .map_err(|err| Error::Decoder(anyhow::anyhow!(err.to_string())))?; -// -// on_matched(&seed, inner, label) -// } -// _ => Err(Error::UnsupportedSelector { -// type_name: T::NAME, -// selector_name: selector.name(), -// }), -// } -// } + Ok(()) + } +} #[cfg(test)] mod tests { diff --git a/src/error.rs b/src/error.rs index c8411cf..47625ee 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,8 +4,8 @@ use multibase::Error as MultibaseError; use multihash::Error as MultihashError; use serde::{de, ser}; use std::{ - convert::Infallible, error::Error as StdError, num::TryFromIntError, string::FromUtf8Error, - sync::mpsc::SendError, + convert::Infallible, error::Error as StdError, fmt::Display, num::TryFromIntError, + string::FromUtf8Error, sync::mpsc::SendError, }; use thiserror::Error; @@ -23,6 +23,12 @@ pub enum Error { #[error("Mismatched `Any` data model type")] MismatchedAny, + #[error("Failed conversion from `Any::{any_variant}` to `{type_name}`")] + FailedAnyConversion { + type_name: &'static str, + any_variant: &'static str, + }, + ////////////////////////////////////////////////////////////////////// // codec ////////////////////////////////////////////////////////////////////// @@ -34,15 +40,17 @@ pub enum Error { UnknownMulticodecName(String), #[error("IPLD codec encoding error: {0}")] - Encoder(Box), + Encoder(Box), #[error("IPLD codec decoding error: {0}")] - Decoder(Box), + Decoder(Box), // #[error("Value error: {0}")] // Value(&'static str), // #[error("{0}")] // BlockMeta(&'static str), + #[error("Map field parse error: {0}")] + FieldParse(Box), ////////////////////////////////////////////////////////////////////// // selector @@ -72,11 +80,31 @@ pub enum Error { // actual_type_name: &'static str, // desired_type_name: &'static str, // }, - #[error("ExploreIndex failure: no node at index {0}")] - ExploreIndexFailure(usize), + #[error("ExploreIndex failure for type `{type_name}`: no node at index {index}")] + ExploreIndexFailure { + type_name: &'static str, + index: usize, + }, + + #[error("ExploreRange failure for type `{type_name}`: missing node at index {index}; range {start}..{end}")] + ExploreRangeFailure { + type_name: &'static str, + index: usize, + start: Int, + end: Int, + }, - #[error("ExploreRange failure: missing node at index {0}; range {1}..{2}")] - ExploreRangeFailure(usize, Int, Int), + #[error("Failed to explore field key `{field_name}` of type `{key_type_name}`")] + ExploreFieldKeyFailure { + key_type_name: &'static str, + field_name: &'static str, + }, + + #[error("Failed to explore field value of type `{value_type_name}` for key `{key}`")] + ExploreFieldValueFailure { + value_type_name: &'static str, + key: String, + }, #[error("Selector depth error: {0}: {1}")] SelectorDepth(&'static str, usize), @@ -90,14 +118,27 @@ pub enum Error { ////////////////////////////////////////////////////////////////////// // misc ////////////////////////////////////////////////////////////////////// - #[error("Downcast failure for type `{0}`: {1}")] - DowncastFailure(&'static str, &'static str), + #[error("Downcast failure for type `{type_name}`: {msg}")] + DowncastFailure { + type_name: &'static str, + msg: &'static str, + }, #[error("{0}")] Custom(anyhow::Error), } impl Error { + pub(crate) fn failed_any_conversion(any_variant: &'static str) -> Self + where + T: Representation, + { + Self::FailedAnyConversion { + type_name: T::NAME, + any_variant, + } + } + pub(crate) fn unsupported_selector(selector: &Selector) -> Self where T: Representation, @@ -113,10 +154,21 @@ impl Error { Self::MissingNextSelector(Representation::name(selector)) } - pub(crate) fn explore_list_failure(selector: &Selector, current_index: usize) -> Self { + pub(crate) fn explore_list_failure( + selector: &Selector, + index: usize, + ) -> Self { match selector { - Selector::ExploreIndex(_) => Self::ExploreIndexFailure(current_index), - Selector::ExploreRange(s) => Self::ExploreRangeFailure(current_index, s.start, s.end), + Selector::ExploreIndex(_) => Self::ExploreIndexFailure { + type_name: E::NAME, + index, + }, + Selector::ExploreRange(s) => Self::ExploreRangeFailure { + type_name: E::NAME, + index, + start: s.start(), + end: s.end(), + }, _ => unreachable!(), } } @@ -129,8 +181,32 @@ impl Error { } } + pub(crate) fn explore_index_failure(index: usize) -> Self { + Self::ExploreIndexFailure { + type_name: E::NAME, + index, + } + } + + pub(crate) fn explore_key_failure(field_name: Option<&'static str>) -> Self { + Self::ExploreFieldKeyFailure { + key_type_name: K::NAME, + field_name: field_name.unwrap_or("anonymous key"), + } + } + + pub(crate) fn explore_value_failure(field: impl Display) -> Self { + Self::ExploreFieldValueFailure { + value_type_name: V::NAME, + key: field.to_string(), + } + } + pub(crate) fn downcast_failure(msg: &'static str) -> Self { - Self::DowncastFailure(T::NAME, msg) + Self::DowncastFailure { + type_name: T::NAME, + msg, + } } // pub(crate) fn invalid_type_selection() -> Self @@ -148,7 +224,7 @@ impl Error { #[inline] pub fn decoder(err: E) -> Self where - E: de::Error + Send + Sync + 'static, + E: de::Error + 'static, { Error::Decoder(Box::new(err)) } @@ -157,7 +233,7 @@ impl Error { #[inline] pub fn encoder(err: E) -> Self where - E: ser::Error + Send + Sync + 'static, + E: ser::Error + 'static, { Error::Encoder(Box::new(err)) } diff --git a/src/lib.rs b/src/lib.rs index 926d966..c881600 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ //! - replace boxed callbacks with a ref #![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)] +#[cfg_attr(not(feature = "std"), no_std)] #[forbid(unsafe_code)] // #[path = "cid.rs"] @@ -43,10 +44,7 @@ mod specs { // multiformats pub use multibase::Base as Multibase; - pub use multihash::{ - self, Code as Multihashes, Hasher as _, Multihash as DefaultMultihash, - MultihashDigest as _, MultihashGeneric, - }; + pub use multihash::{self, Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}; pub use multihash_::Multihash; // cid @@ -55,7 +53,7 @@ mod specs { // data model, schemas and representation pub use crate::data_model::*; - pub use crate::representation::Representation; + pub use crate::representation::{Kind, Representation, TypedKind as _}; pub use ipld_macros::{ipld_attr, schema}; // selectors @@ -70,8 +68,7 @@ pub mod prelude { #[doc(inline)] pub use crate::specs::*; #[doc(inline)] - pub use crate::{Any, Cid, Context, Error, Representation, Select, Selector}; - + pub use crate::Error; #[doc(hidden)] pub use serde::{Deserialize, Deserializer, Serialize, Serializer}; } @@ -95,6 +92,9 @@ pub mod dev { pub use ipld_macros_internals::*; } + #[doc(hidden)] + pub use crate::maybestd; + #[doc(hidden)] pub use serde::{ self, @@ -107,4 +107,28 @@ pub mod dev { }; // #[doc(hidden)] // pub use serde_repr; + #[doc(hidden)] + pub use ipld_macros_internals::dev::typenum; + #[doc(hidden)] + pub use ipld_macros_internals::dev::typenum_macro; +} + +/// +#[cfg(not(feature = "std"))] +#[doc(hidden)] +pub mod maybestd { + extern crate alloc; + + pub use alloc::{boxed, collections, rc, vec::Vec}; + pub use core::{borrow, cell, cmp, convert, fmt, hash, iter, marker, ops, str, sync}; + pub use core2::{error, io}; +} +#[cfg(feature = "std")] +#[doc(hidden)] +pub mod maybestd { + pub use core2::{error, io}; + pub use std::{ + borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, ops, rc, str, + sync, vec::Vec, + }; } diff --git a/src/multicodec.rs b/src/multicodec.rs index aa660fb..0f8d438 100644 --- a/src/multicodec.rs +++ b/src/multicodec.rs @@ -111,7 +111,7 @@ mod multicodec { } #[doc(hidden)] - pub fn read_from_seed( + pub fn read_with_seed( &mut self, seed: SelectorSeed<'_, Ctx, T>, reader: R, @@ -124,7 +124,7 @@ mod multicodec { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$ty>::read_from_seed(seed, reader), + Self::$variant(_) => <$ty>::read_with_seed(seed, reader), )* } } diff --git a/src/multihash.rs b/src/multihash.rs index b3cb493..0fb62c8 100644 --- a/src/multihash.rs +++ b/src/multihash.rs @@ -1,13 +1,15 @@ use crate::dev::*; +use macros::derive_more::From; use multihash::Hasher; macro_rules! impl_multihasher { (@multihash $( $(#[$meta:meta])* - $variant:ident ($const:ident: $code:expr) -> $ty:ty [$size:expr], + $variant:ident ($const:ident: $name:literal: $code:expr) -> $ty:ty [$size:expr], )*) => { /// A generic [multihash]()-er enum. - #[derive(Debug)] + #[derive(Debug, From)] + #[non_exhaustive] pub enum Multihash { $( $(#[$meta])* @@ -30,6 +32,15 @@ macro_rules! impl_multihasher { }?) } + /// + #[inline] + pub const fn is_supported() -> bool { + match C { + $($code => true,)* + _ => false, + } + } + /// #[inline] pub const fn code(&self) -> u64 { @@ -38,7 +49,15 @@ macro_rules! impl_multihasher { } } - /// The underlying size of the digest. + /// + #[inline] + pub const fn name(&self) -> &'static str { + match self { + $(Self::$variant(_) => $name,)* + } + } + + /// The underlying size of the generated digest. #[inline] pub const fn size(&self) -> u8 { match self { @@ -47,7 +66,7 @@ macro_rules! impl_multihasher { } /// - pub fn finalize(&mut self) -> Result { + pub fn try_finalize(&mut self) -> Result { let mh = DefaultMultihash::wrap(self.code(), multihash::Hasher::finalize(self))?; self.reset(); Ok(mh) @@ -55,16 +74,19 @@ macro_rules! impl_multihasher { } impl multihash::Hasher for Multihash { + #[inline] fn update(&mut self, input: &[u8]) { match self { $(Self::$variant(hasher) => hasher.update(input),)* } } + #[inline] fn finalize(&mut self) -> &[u8] { match self { $(Self::$variant(hasher) => hasher.finalize(),)* } } + #[inline] fn reset(&mut self) { match self { $(Self::$variant(hasher) => hasher.reset(),)* @@ -72,6 +94,87 @@ macro_rules! impl_multihasher { } } + impl std::io::Write for Multihash { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.update(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } + } + + // #[cfg(feature = "digest")] + // mod _digest { + // use super::*; + // use digest::{Digest, OutputSizeUser, FixedOutputReset, generic_array::{typenum::U64, GenericArray}}; + // + // impl OutputSizeUser for Multihash { + // type OutputSize = GenericArray; + // } + // + // impl Multihash { + // const OUTPUT_SIZE: usize = U64::USIZE; + // + // fn finalize_to_digest(&mut self, digest: &mut Output) { + // digest.as_mut_slice() + // } + // } + // + // impl Digest for Multihash { + // fn new() -> Self { + // unimplemented!() + // } + // fn new_with_prefix(data: impl AsRef<[u8]>) -> Self { + // let mut new = Self::new(); + // new.update(data); + // new + // } + // fn update(&mut self, data: impl AsRef<[u8]>) { + // multihash::Hasher::update(self, data.as_ref()) + // } + // fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self { + // (&mut self).update(data); + // self + // } + // fn finalize(mut self) -> Output { + // let mut slice = Output::::default(); + // let bytes = multihash::Hasher::finalize(&mut self); + // Ok(From::from()) + // } + // fn finalize_into(mut self, out: &mut Output) { + // unimplemented!() + // } + // fn finalize_reset(&mut self) -> Output + // where + // Self: FixedOutputReset, + // { + // unimplemented!() + // } + // fn finalize_into_reset(&mut self, out: &mut Output) + // where + // Self: FixedOutputReset, + // { + // unimplemented!() + // } + // fn reset(&mut self) + // where + // Self: Reset, + // { + // multihash::Hasher::reset(self) + // } + // fn output_size() -> usize { + // Self::OUTPUT_SIZE + // } + // fn digest(data: impl AsRef<[u8]>) -> Output { + // let mut mh = Self::new(); + // mh.update(data); + // mh.finalize() + // } + // } + // }; + impl TryFrom for Multihash { type Error = Error; fn try_from(multihash_code: u64) -> Result { @@ -86,33 +189,48 @@ macro_rules! impl_multihasher { impl_multihasher! {@multihash /// - Sha2_256 (SHA2_256: 0x12) -> multihash::Sha2_256 [32], + Sha2_256 (SHA2_256: "sha2-256": 0x12) + -> multihash::Sha2_256 [32], /// - Sha2_512 (SHA2_512: 0x13) -> multihash::Sha2_512 [64], + Sha2_512 (SHA2_512: "sha2-512": 0x13) + -> multihash::Sha2_512 [64], /// - Sha3_224 (SHA3_224: 0x17) -> multihash::Sha3_224 [28], + Sha3_224 (SHA3_224: "sha3-224": 0x17) + -> multihash::Sha3_224 [28], /// - Sha3_256 (SHA3_256: 0x16) -> multihash::Sha3_256 [32], + Sha3_256 (SHA3_256: "sha3-256": 0x16) + -> multihash::Sha3_256 [32], /// - Sha3_384 (SHA3_384: 0x15) -> multihash::Sha3_384 [48], + Sha3_384 (SHA3_384: "sha3-384": 0x15) + -> multihash::Sha3_384 [48], /// - Sha3_512 (SHA3_512: 0x14) -> multihash::Sha3_512 [64], + Sha3_512 (SHA3_512: "sha3-512": 0x14) + -> multihash::Sha3_512 [64], /// - Keccak224 (KECCAK_224: 0x1a) -> multihash::Keccak224 [28], + Keccak224 (KECCAK_224: "keccak-224": 0x1a) + -> multihash::Keccak224 [28], /// - Keccak256 (KECCAK_256: 0x1b) -> multihash::Keccak256 [32], + Keccak256 (KECCAK_256: "keccak-256": 0x1b) + -> multihash::Keccak256 [32], /// - Keccak384 (KECCAK_384: 0x1c) -> multihash::Keccak384 [48], + Keccak384 (KECCAK_384: "keccak-384": 0x1c) + -> multihash::Keccak384 [48], /// - Keccak512 (KECCAK_512: 0x1d) -> multihash::Keccak512 [64], + Keccak512 (KECCAK_512: "keccak-512": 0x1d) + -> multihash::Keccak512 [64], /// - Blake2b256 (BLAKE2B_256: 0xb220) -> multihash::Blake2bHasher::<32> [32], + Blake2b256 (BLAKE2B_256: "blake2b-256": 0xb220) + -> multihash::Blake2bHasher::<32> [32], /// - Blake2b512 (BLAKE2B_512: 0xb240) -> multihash::Blake2bHasher::<64> [64], + Blake2b512 (BLAKE2B_512: "blake2b-512": 0xb240) + -> multihash::Blake2bHasher::<64> [64], /// - Blake2s128 (BLAKE2S_128: 0xb250) -> multihash::Blake2sHasher::<16> [16], + Blake2s128 (BLAKE2S_128: "blake2s-128": 0xb250) + -> multihash::Blake2sHasher::<16> [16], /// - Blake2s256 (BLAKE2S_256: 0xb260) -> multihash::Blake2sHasher::<32> [32], + Blake2s256 (BLAKE2S_256: "blake2s-256": 0xb260) + -> multihash::Blake2sHasher::<32> [32], /// - Blake3_256 (BLAKE3_256: 0x1e) -> multihash::Blake3Hasher::<32> [32], + Blake3_256 (BLAKE3_256: "blake3": 0x1e) + -> multihash::Blake3Hasher::<32> [32], } diff --git a/src/representation.rs b/src/representation/mod.rs similarity index 70% rename from src/representation.rs rename to src/representation/mod.rs index 55ca228..4e93cd1 100644 --- a/src/representation.rs +++ b/src/representation/mod.rs @@ -9,83 +9,91 @@ //! type from/to bytes, as well query and mutate a type, while specifically //! defining for the type it's `Context` requirements for these operations. +mod strategies; + use crate::dev::*; use downcast_rs::{impl_downcast, Downcast}; +use macros::derive_more::From; +use maybestd::{fmt, str::FromStr}; + +pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKind}; -pub use kind::Kind; +#[doc(hidden)] +pub use strategies::*; +#[cfg(feature = "old")] mod kind { - use bitflags::bitflags; - - bitflags! { - /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. - /// - pub struct Kind: u16 { - // data model kinds - - /// - const Null = 0b0000_0000_0000_0001; - /// - const Bool = 0b0000_0000_0000_0010; - /// - const Int = 0b0000_0000_0000_0100; - /// - const Float = 0b0000_0000_0000_1000; - /// - const String = 0b0000_0000_0001_0000; - /// - const Bytes = 0b0000_0000_0010_0000; - /// - const List = 0b0000_0000_0100_0000; - /// - const Map = 0b0000_0000_1000_0000; - /// - const Link = 0b0000_0001_0000_0000; - - // schema kinds - - /// - const Struct = 0b0000_0010_0000_0000; - /// - const Enum = 0b0000_0100_0000_0000; - /// - const Union = 0b0000_1000_0000_0000; - - // any - - /// - const Any = Self::Null.bits - | Self::Bool.bits - | Self::Int.bits - | Self::Float.bits - | Self::String.bits - | Self::Bytes.bits - | Self::List.bits - | Self::Map.bits - | Self::Link.bits; - } - } + // use bitflags::bitflags; + + // bitflags! { + // /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. + // /// + // pub struct Kind: u16 { + // // data model kinds + + // /// + // const Null = 0b0000_0000_0000_0001; + // /// + // const Bool = 0b0000_0000_0000_0010; + // /// + // const Int = 0b0000_0000_0000_0100; + // /// + // const Float = 0b0000_0000_0000_1000; + // /// + // const String = 0b0000_0000_0001_0000; + // /// + // const Bytes = 0b0000_0000_0010_0000; + // /// + // const List = 0b0000_0000_0100_0000; + // /// + // const Map = 0b0000_0000_1000_0000; + // /// + // const Link = 0b0000_0001_0000_0000; + + // // schema kinds + + // /// + // const Struct = 0b0000_0010_0000_0000; + // /// + // const Enum = 0b0000_0100_0000_0000; + // /// + // const Union = 0b0000_1000_0000_0000; + + // // any + + // /// + // const Any = Self::Null.bits + // | Self::Bool.bits + // | Self::Int.bits + // | Self::Float.bits + // | Self::String.bits + // | Self::Bytes.bits + // | Self::List.bits + // | Self::Map.bits + // | Self::Link.bits; + // } + // } - impl Kind { - /// Const function for determining equality between [`Kind`]s. - pub const fn eq(&self, other: &Self) -> bool { - match (*self, *other) { - (Self::Null, Self::Null) - | (Self::Bool, Self::Bool) - | (Self::Int, Self::Int) - | (Self::Float, Self::Float) - | (Self::String, Self::String) - | (Self::Bytes, Self::Bytes) - | (Self::List, Self::List) - | (Self::Map, Self::Map) - | (Self::Link, Self::Link) - | (Self::Struct, Self::Struct) - | (Self::Enum, Self::Enum) - | (Self::Union, Self::Union) => true, - _ => false, - } - } - } + // impl Kind { + // /// Const function for determining equality between [`Kind`]s. + // pub const fn eq(&self, other: &Self) -> bool { + // match (*self, *other) { + // (Self::Null, Self::Null) + // | (Self::Bool, Self::Bool) + // | (Self::Int, Self::Int) + // | (Self::Float, Self::Float) + // | (Self::String, Self::String) + // | (Self::Bytes, Self::Bytes) + // | (Self::List, Self::List) + // | (Self::Map, Self::Map) + // | (Self::Link, Self::Link) + // | (Self::Struct, Self::Struct) + // | (Self::Enum, Self::Enum) + // | (Self::Union, Self::Union) => true, + // _ => false, + // } + // } + // } // /// // #[derive(Copy, Clone, Debug)] @@ -156,6 +164,18 @@ mod kind { // Byteprefix(&'static [Field<&'static [u8; 1]>]), // } +// trait IsAny {} +// impl IsAny<{ Kind::Any.bits() }> for Kind {} +// impl IsAny<{ Kind::Null.bits() }> for Kind {} +// impl IsAny<{ Kind::Bool.bits() }> for Kind {} +// impl IsAny<{ Kind::Int.bits() }> for Kind {} +// impl IsAny<{ Kind::Float.bits() }> for Kind {} +// impl IsAny<{ Kind::String.bits() }> for Kind {} +// impl IsAny<{ Kind::Bytes.bits() }> for Kind {} +// impl IsAny<{ Kind::List.bits() }> for Kind {} +// impl IsAny<{ Kind::Map.bits() }> for Kind {} +// impl IsAny<{ Kind::Link.bits() }> for Kind {} + /// /// /// Some types have in-memory representations distinct from their IPLD representations: @@ -191,6 +211,16 @@ mod kind { /// - TODO: ? impl DeserializeSeed for selector? /// - TODO: ? Representation::visitor(selector: &Selector) pub trait Representation: Sized { + // /// Marker type for exact `u32` value of the type's [`Representation::DATA_MODEL_KIND`], needed for internal blanket implementations of various traits. + // #[doc(hidden)] + // type DATA_MODEL_KIND: TypedKind; + // /// Marker type for exact `u32` value of the type's [`Representation::SCHEMA_KIND`], needed for internal blanket implementations of various traits. + // #[doc(hidden)] + // type SCHEMA_KIND: TypedKind; + // /// Marker type for exact `u32` value of the type's [`Representation::REPR_KIND`], needed for internal blanket implementations of various traits. + // #[doc(hidden)] + // type REPR_KIND: TypedKind; + // TODO: use this seed in Representation::deserialize by default // type Seed<'de, const C: u64>: Default + DeserializeSeed<'de, Value = Self>; @@ -204,7 +234,7 @@ pub trait Representation: Sized { /// The IPLD [Data Model Kind](https://ipld.io/docs/data-model/kinds/) of /// the type, which would inform a user of its access patterns. - const DATA_MODEL_KIND: Kind; + const DATA_MODEL_KIND: Kind; // Self::DATA_MODEL_KIND::KIND /// The IPLD [Schema /// Kind](https://ipld.io/docs/schemas/features/typekinds/#schema-kinds) of @@ -212,16 +242,24 @@ pub trait Representation: Sized { const SCHEMA_KIND: Kind = Self::DATA_MODEL_KIND; /// The IPLD [Representation Kind]() of the type, which would inform a user of how the type is represented when encoded. - const REPR_KIND: Kind = Self::DATA_MODEL_KIND; + const REPR_KIND: Kind = Self::DATA_MODEL_KIND; // K - /// - const IS_LINK: bool = Self::DATA_MODEL_KIND.eq(&Kind::Link); + // const IS_ADL: bool = false; + + /// Marker for types that can have any representation *and* should be + /// ignored entirely during selection/deserialization. + #[doc(hidden)] + const __IGNORED: bool = false; /// + /// todo deprecate + const IS_LINK: bool = Self::DATA_MODEL_KIND.is_link(); + + /// todo deprecate const HAS_LINKS: bool = Self::IS_LINK; - // /// The type's `Select`able field names and their IPLD Schema kinds, if a recursive type. - // const FIELDS: Fields = Fields::None; + /// The type's `Select`able static field names and their IPLD Schema kinds. + const FIELDS: &'static [(Field<'static>, Kind)] = &[]; /// /// for unions, this ?should delegate to the variant's type name' @@ -245,17 +283,32 @@ pub trait Representation: Sized { Self::REPR_KIND } + /// + fn is_link(&self) -> bool { + Self::IS_LINK + } + /// fn has_links(&self) -> bool { Self::HAS_LINKS } + /// + fn as_field(&self) -> Option> { + None + } + + fn to_selected_node(&self) -> SelectedNode { + unimplemented!() + } + /// Replacement method for [`serde::Serialize::serialize`] that allows us - /// switch serialization behaviour based on the provided [`CodecExt`]. + /// switch serialization behaviour based on the provided [`Codec`]. /// /// Defaults to the type's underlying [`serde::Serialize::serialize`] /// implementation. /// TODO: remove the default impl, then remove the trait bounds + /// TODO: rename to encode? as in, just encode this type (up to links) #[inline] #[doc(hidden)] fn serialize(&self, serializer: S) -> Result @@ -272,6 +325,7 @@ pub trait Representation: Sized { /// Defaults to the type's underlying [`serde::Deserialize::deserialize`] /// implementation. /// TODO: remove the default impl, then remove the trait bounds + /// TODO: rename to decode? as in, just decode this type (up to links) #[inline] #[doc(hidden)] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result @@ -374,6 +428,17 @@ pub trait Representation: Sized { // fn links(c: Codec, reader: &mut R, ) } +/// +pub trait StringRepresentation +where + Self: Representation + Clone + fmt::Display + FromStr + Ord, +{ +} +impl StringRepresentation for T where + Self: Representation + Clone + fmt::Display + FromStr + Ord +{ +} + /// /// TODO: possibly look at erased-serde to complete this "hack" pub(crate) trait ErasedRepresentation: Downcast { @@ -426,7 +491,7 @@ where } /// -// #[derive(Debug)] +#[derive(From)] pub struct AnyRepresentation { erased: Box, // is_partial: bool, @@ -470,6 +535,8 @@ impl AnyRepresentation { // } } + // pub fn roundtrip(self) + // /// // #[inline] // pub fn cast_between(self) -> Result @@ -491,6 +558,11 @@ impl From for AnyRepresentation { } } +// /// +// #[doc(hidden)] +// pub trait IsKind {} +// impl IsTrue for () where T: Representation {} + // mod type_eq { // #[doc(hidden)] // /// @@ -544,6 +616,28 @@ impl From for AnyRepresentation { // type Representation = Self; // } +// #[doc(hidden)] +// mod typeeq { +// pub trait TypeEq { +// const EQ: bool = EQ; // impls!( Self: TypeEq ) +// } + +// // // Default implementation. +// impl TypeEq for T {} + +// // Specialization for `T == U`. +// impl TypeEq for T {} + +// #[doc(hidden)] +// pub const fn type_eq() -> bool +// // where +// // T: TypeEq, +// { +// // impls!( Self: TypeEq ) +// >::EQ +// } +// } + /* /// Helper trait. `VALUE` is false, except for the specialization of the @@ -598,3 +692,22 @@ pub(crate) fn type_cast_mut(inner: .unwrap() } */ + +/// Helper fn for constraining and safely transmuting a generic selection output +pub(crate) fn type_cast_selection( + inner: F, +) -> Result, E> +where + F: FnOnce() -> Result, E>, +{ + // if !type_eq::() { + // unreachable!("should only do this for types known to be identical") + // } + + let mut inner = inner()?; + let outer = (&mut inner as &mut dyn std::any::Any) + .downcast_mut::>() + .unwrap() + .take(); + Ok(outer) +} diff --git a/src/selectors/context.rs b/src/selectors/context.rs index 9cdb995..382cdca 100644 --- a/src/selectors/context.rs +++ b/src/selectors/context.rs @@ -10,10 +10,10 @@ mod ipfs; use crate::dev::*; -use std::{ - collections::HashMap, - io::{Cursor, Read, Write}, -}; +use maybestd::io::{empty, Cursor, Empty, Read, Sink, Write}; +use std::collections::HashMap; + +trait BlockWriter: Write {} /// Trait for providing blocks and additional logic required for selection. pub trait Context: Sized { @@ -28,6 +28,16 @@ pub trait Context: Sized { /// fn block_reader(&mut self, cid: &Cid) -> Result; + /// + fn block_writer(&mut self, cid_to_replace: Option<&Cid>) -> Result { + unimplemented!() + } + + // /// + // fn flush_writer(&mut self, cid_to_replace: Option<&Cid>, block: ) -> Result { + + // } + // // fn decoder<'de, 'a: 'de>(&mut self) -> Box + 'a> { // unimplemented!() @@ -99,6 +109,15 @@ impl<'a, C: Context + 'a> Context for &'a mut C { } } +impl Context for () { + type Reader = Empty; + type Writer = Sink; + + fn block_reader(&mut self, _: &Cid) -> Result { + Ok(empty()) + } +} + /// #[derive(Clone, Debug, Default)] pub struct MemoryContext { @@ -115,7 +134,7 @@ impl MemoryContext { multihash_code: u64, block: Vec, ) -> Result { - let cid = Cid::new(version, multicodec_code, multihash_code, block.as_ref())?; + let cid = Cid::new(version, multicodec_code, multihash_code, block.as_slice())?; self.blocks.insert(cid, block); Ok(cid) } diff --git a/src/selectors/mod.rs b/src/selectors/mod.rs index 1d07b7d..e8ef162 100644 --- a/src/selectors/mod.rs +++ b/src/selectors/mod.rs @@ -22,11 +22,11 @@ pub use selectors::*; pub use state::*; use crate::dev::*; -use macros::derive_more::From; -use serde::de::DeserializeSeed; +use macros::derive_more::{Display, From}; use std::{ cell::RefCell, path::{Path, PathBuf}, + str::FromStr, vec::IntoIter, }; @@ -48,10 +48,28 @@ pub trait Select: Representation { /// /// /// TODO: update this interface, since SelectorSeed is doing the work and it should be refactored a bit (borrow state, ) - fn select(params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error>; + fn select(params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { + let Params { + selector, + mut state, + callback, + } = params; + + let default_selector = Selector::DEFAULT; + let seed = SelectorSeed::from_parts( + &selector.unwrap_or(&default_selector), + &mut state, + callback, + ctx, + ); + + let cid = &seed.state.current_block; + let block = seed.ctx.block_reader(cid)?; + cid.multicodec()?.read_with_seed(seed, block) + } #[doc(hidden)] - fn __select_from_deserializer<'a, 'de, const C: u64, D>( + fn __select_de<'a, 'de, const C: u64, D>( seed: SelectorSeed<'a, Ctx, Self>, deserializer: D, ) -> Result<(), D::Error> @@ -64,9 +82,9 @@ pub trait Select: Representation { } #[doc(hidden)] - fn __select_from_seq<'a, 'de, const C: u64, A>( + fn __select_seq<'a, 'de, const C: u64, A>( seed: SelectorSeed<'a, Ctx, Self>, - mut seq: A, + mut seq: A, // should be ListIterator ) -> Result, A::Error> where A: SeqAccess<'de>, @@ -78,9 +96,9 @@ pub trait Select: Representation { } #[doc(hidden)] - fn __select_from_map<'a, 'de, const C: u64, A>( + fn __select_map<'a, 'de, const C: u64, A>( seed: SelectorSeed<'a, Ctx, Self>, - mut map: A, + mut map: A, // should be MapIterator, is_key: bool, ) -> Result, A::Error> where @@ -96,11 +114,72 @@ pub trait Select: Representation { // } } + // #[doc(hidden)] + // fn __select_list<'a, 'de, const C: u64, I, T>( + // seed: SelectorSeed<'a, Ctx, Self>, + // // mut seq: A, // should be ListIterator + // mut iter: I, + // ) -> Result, Error> + // where + // // A: SeqAccess<'de>, + // I: ListIterator, + // T: Select, + // { + // unimplemented!() + // // seq.next_element_seed(CodecSeed::from(seed)) + // // Err(Error::Custom("unimplemented")) + // // TODO: default impl should use GAT for CodedSeed + // // seq.next_element_seed(Self::Seed::<'a, 'de, C>::from(seed)) + // } + + // #[doc(hidden)] + // fn __select_map<'a, 'de, const C: u64, I, K, V>( + // seed: SelectorSeed<'a, Ctx, Self>, + // // mut map: A, // should be MapIterator, + // // is_key: bool, + // mut iter: I, + // ) -> Result, Error> + // where + // // A: MapAccess<'de>, + // I: MapIterator, + // K: StringRepresentation, + // V: Representation, + // { + // unimplemented!() + // // Err(Error::Custom("unimplemented")) + // // TODO: default impl should use GAT for CodedSeed + // // let seed = Self::Seed::<'a, 'de, C>::from(seed); + // // if is_key { + // // map.next_key_seed(seed) + // // } else { + // // Ok(Some(map.next_value_seed(seed)?)) + // // } + // } + /// Selects against the dag, loading more blocks from `Ctx` if required. /// /// TODO #[doc(hidden)] - fn select_in(&self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { + fn select_in(&self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { + let Params { + selector, + mut state, + callback, + } = params; + + let default_selector = Selector::DEFAULT; + let seed = SelectorSeed::from_parts( + &selector.unwrap_or(&default_selector), + &mut state, + callback, + ctx, + ); + + self.__select_in(seed) + } + + #[doc(hidden)] + fn __select_in<'a>(&self, seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { unimplemented!() } @@ -184,28 +263,28 @@ mod params { C: Context, T: Representation, { - pub(crate) cid: Option, pub(crate) selector: Option<&'a Selector>, - pub(crate) max_path_depth: Option, - pub(crate) max_link_depth: Option, + pub(crate) state: State, + // pub(crate) max_path_depth: Option, + // pub(crate) max_link_depth: Option, pub(crate) callback: Callback<'a, C, T>, } - impl<'a, C, T> Default for Params<'a, C, T> - where - C: Context, - T: Representation, - { - fn default() -> Self { - Self { - cid: None, - selector: None, - max_path_depth: None, - max_link_depth: None, - callback: Default::default(), - } - } - } + // impl<'a, C, T> Default for Params<'a, C, T> + // where + // C: Context, + // T: Representation, + // { + // fn default() -> Self { + // Self { + // selector: None, + // state: Default::default(), + // // max_path_depth: None, + // // max_link_depth: None, + // callback: Default::default(), + // } + // } + // } impl<'a, C, T> Params<'a, C, T> where @@ -215,16 +294,20 @@ mod params { /// pub fn new_select(cid: Cid) -> Self { Self { - cid: Some(cid), - ..Self::default() + selector: None, + state: State { + current_block: cid, + ..Default::default() + }, + callback: Default::default(), } } - /// - pub fn with_root(mut self, cid: Cid) -> Self { - self.cid.replace(cid); - self - } + // /// + // pub fn with_root(mut self, cid: Cid) -> Self { + // self.state.current_block = cid; + // self + // } /// pub fn with_selector(mut self, selector: &'a Selector) -> Self { @@ -234,20 +317,20 @@ mod params { /// pub fn with_max_path_depth(mut self, max_path_depth: usize) -> Self { - self.max_path_depth.replace(max_path_depth); + self.state.max_path_depth.replace(max_path_depth); self } /// pub fn with_max_link_depth(mut self, max_link_depth: usize) -> Self { - self.max_link_depth.replace(max_link_depth); + self.state.max_link_depth.replace(max_link_depth); self } /// pub fn into_node_iter( self, - only_matched: bool, + only_results: bool, ctx: &mut C, ) -> Result, Error> where @@ -256,7 +339,7 @@ mod params { let vec = RefCell::new(Vec::new()); let params = Params { callback: Callback::SelectNode { - only_matched, + only_results, cb: Box::new(|node, _| { vec.borrow_mut().push(node); Ok(()) @@ -331,7 +414,7 @@ mod selection { impl NodeSelection { /// - pub fn new(path: &Path, node: T) -> Self + pub fn covered(path: &Path, node: T) -> Self where T: Into, { @@ -344,7 +427,7 @@ mod selection { } /// - pub fn new_match(path: &Path, node: T, label: Option<&str>) -> Self + pub fn result(path: &Path, node: T, label: Option<&str>) -> Self where T: Into, { @@ -364,6 +447,20 @@ mod selection { pub label: Option, } + impl From<(P, T, Option<&str>)> for DagSelection + where + P: Into, + T: Representation + 'static, + { + fn from((path, dag, label): (P, T, Option<&str>)) -> Self { + Self { + path: path.into(), + dag: dag.into(), + label: label.map(|s| s.to_string()), + } + } + } + impl DagSelection { /// pub fn new(path: &Path, dag: T, label: Option<&str>) -> Self @@ -527,6 +624,7 @@ mod selection { } } + // TODO: Vec? impl From> for SelectedNode { fn from(_: List) -> Self { Self::List @@ -557,29 +655,33 @@ mod selection { } } - impl From for SelectedNode { - fn from(val: Any) -> Self { - match val { - Any::Null(_) => Self::Null, - Any::Bool(inner) => Self::Bool(inner), - Any::Int(inner) => Self::Int64(inner), - Any::Float(inner) => Self::Float64(inner), - Any::String(inner) => Self::String(inner), - Any::Bytes(inner) => Self::Bytes(inner), - Any::List(_) => Self::List, - Any::Map(_) => Self::Map, - Any::Link(link) => Self::Link(*link.as_ref().cid()), - } - } - } + // impl From for SelectedNode { + // fn from(val: Any) -> Self { + // match val { + // Any::Null(_) => Self::Null, + // Any::Bool(inner) => Self::Bool(inner), + // Any::Int(inner) => Self::Int64(inner), + // Any::Float(inner) => Self::Float64(inner), + // Any::String(inner) => Self::String(inner), + // Any::Bytes(inner) => Self::Bytes(inner), + // Any::List(_) => Self::List, + // Any::Map(_) => Self::Map, + // Any::Link(link) => Self::Link(*link.as_ref().cid()), + // } + // } + // } } mod field { use super::*; + use std::borrow::Cow; /// Wrapper type for types that can be used as dag keys or indices. - pub(crate) enum Field<'a> { - Key(&'a str), + #[doc(hidden)] + #[derive(Clone, Debug, Display, From)] + // #[from(forward)] + pub enum Field<'a> { + Key(Cow<'a, str>), // CidKey(&'a Cid), Index(usize), } @@ -587,40 +689,123 @@ mod field { impl<'a> Field<'a> { pub fn append_to_path(&self, path: &mut PathBuf) { match self { - Self::Key(s) => path.push(s), + Self::Key(s) => path.push(s.as_ref()), // Self::CidKey(c) => path.push(c.to_string()), Self::Index(idx) => path.push(idx.to_string()), } } - } - impl<'a> AsRef for Field<'a> { - fn as_ref(&self) -> &str { + pub fn into_owned<'b>(&'a self) -> Field<'b> { match self { - Self::Key(s) => s, - _ => unreachable!(), + Self::Key(s) => Field::Key(s.clone().into_owned().into()), + Self::Index(idx) => Field::Index(*idx), } } - } - impl<'a> AsRef for Field<'a> { - fn as_ref(&self) -> &usize { + pub(crate) fn as_key(&self) -> Option<&str> { match self { - Self::Index(idx) => idx, - _ => unreachable!(), + Self::Key(s) => Some(s.as_ref()), + Self::Index(_) => None, + } + } + + pub(crate) fn as_usize(&self) -> Option { + match self { + Self::Index(idx) => Some(*idx), + Self::Key(_) => None, + } + } + + pub fn is_key(&self, s: &str) -> bool { + match self { + Self::Key(f) => f.eq(s), + _ => false, + } + } + + pub fn is_idx(&self, input: usize) -> bool { + match self { + Self::Index(idx) => input.eq(idx), + _ => false, } } } + // impl AsRef> for &str { + // fn as_ref(&self) -> + // } + + // impl AsRef for Field<'_> { + // fn as_ref(&self) -> &str { + // match self { + // Self::Key(s) => s, + // _ => unreachable!(), + // } + // } + // } + + // impl AsRef for Field<'_> { + // fn as_ref(&self) -> &usize { + // match self { + // Self::Index(idx) => idx, + // _ => unreachable!(), + // } + // } + // } + impl<'a> From<&'a str> for Field<'a> { fn from(inner: &'a str) -> Self { - Self::Key(inner) + Self::Key(inner.into()) + } + } + + // impl From for Field<'_> { + // fn from(inner: usize) -> Self { + // Self::Index(inner) + // } + // } + + // impl From for Field<'_> { + // fn from(inner: isize) -> Self { + // Self::Index(inner as usize) + // } + // } + + // impl<'a> TryInto<&'a str> for &Field<'a> { + // type Error = Error; + // fn try_into(self) -> Result<&'a str, Self::Error> { + // match self { + // Self::Key(inner) + // // _ => Err(Error::) + // } + // } + // } + + impl TryInto for &Field<'_> { + type Error = Error; + fn try_into(self) -> Result { + match self { + Field::Index(idx) => Ok(*idx as i64), + Field::Key(s) => Int::from_str(s).map_err(|err| Error::Decoder(err.into())), + } + } + } + + impl Into for Field<'_> { + fn into(self) -> String { + match self { + Self::Index(idx) => idx.to_string(), + Self::Key(s) => s.to_string(), + } } } - impl<'a> From for Field<'a> { - fn from(inner: usize) -> Self { - Self::Index(inner) + impl<'a> Into> for &Field<'a> { + fn into(self) -> Cow<'a, str> { + match self { + Field::Key(s) => s.clone(), + Field::Index(idx) => Cow::from(idx.to_string()), + } } } } @@ -705,19 +890,25 @@ mod tests { schema! { #[ipld_attr(internal)] - #[derive(Debug)] + #[derive(Clone, Debug)] type Nullish null; } schema! { #[ipld_attr(internal)] - #[derive(Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq)] type Test struct { field1 Int, field2 String, }; } + // schema! { + // #[ipld_attr(internal)] + // // pub type ExploreUnion null; + // pub type ExploreUnion2 [nullable Selector]; + // } + #[test] fn it_works() { let t = Test { diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index 12eb6de..cbcd00a 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -2,10 +2,40 @@ use super::*; use crate::dev::{macros::derive_more::From, *}; use std::{fmt, marker::PhantomData}; +/// The selection mode of the selector, which determines what gets visited, +/// matched, sent and returned. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[doc(hidden)] +pub enum SelectionMode { + /// Selection will invoke the provided callback on all traversed [`Node`]s. + CoverNode, + + /// Selection will invoke the provided callback on all matched [`Node`]s. + MatchNode, + + /// Selection will invoke the provided callback on all matched [`Dag`]s. + MatchDag, + // /// Selection updates matching dags with the output of a callback. + // /// Optionally flushes changes after each callback. + // Patch, +} + /// A helper type for guided decoding of a dag, using a selector to direct /// and/or ignore fields or entire blocks, and a linked context to fetch more /// blocks. -/// TODO: rename to SelectorSeed +/// +/// todo: sharing logic, parameterizing over DM_KIND and REPR_KIND +/// - the Visitor impl: +/// - is called by the REPR of the type +/// e.g. the block encodes a list, map, etc +/// - creates an iterator based on the REPR of the type +/// e.g. Map creates MapIterator from MapAccess +/// e.g. StringpairsMap creates a MapIterator from a string +/// - calls SelectorSeed:: method based on DM_KIND of the type +/// e.g. List* calls match, explore_list_* +/// e.g. +/// ? - ergo, for ADLs: +/// ? - map the input selector to another tailored for the underlying types pub struct SelectorSeed<'a, Ctx, T = Any> { pub(crate) selector: &'a Selector, pub(crate) state: &'a mut State, @@ -13,6 +43,8 @@ pub struct SelectorSeed<'a, Ctx, T = Any> { pub(crate) ctx: &'a mut Ctx, } +pub type EmptySeed = SelectorSeed<'static, (), T>; + /// A marked [`SelectorSeed`] that's aware of the codec of the block it's /// currenly selecting against. /// @@ -22,63 +54,156 @@ pub struct SelectorSeed<'a, Ctx, T = Any> { /// ? 3. Link needs to take some seed, uncode it, then use inner to call SelectorSeed::select for the next block #[doc(hidden)] #[derive(Debug)] -pub struct CodecSeed(pub(crate) S, PhantomData); +pub struct CodecSeed(pub(crate) S, PhantomData); -impl CodecSeed { - pub const D: bool = D; - pub const fn is_select() -> bool { - !D +impl CodecSeed { + // pub const RK: u32 = RK; + // pub const fn is_select() -> bool { + // (!RK) + // } + // pub const fn repr_kind() -> Kind { + // T::REPR_KIND + // } + // pub const fn schema_kind() -> Kind { + // T::SCHEMA_KIND + // } + + const fn schema_kind() -> Kind + where + T: Representation, + { + if T::SCHEMA_KIND.bits() == Kind::Int.bits() { + Int::SCHEMA_KIND + } else { + T::SCHEMA_KIND + } + // match (T::SCHEMA_KIND, T::REPR_KIND) { + // Kind::Int => Int::SCHEMA_KIND, + // kinds => kinds, + // } } } -impl<'a, const C: u64, Ctx, T> CodecSeed, T> { - /// - #[inline] - pub(crate) fn from_parts( - selector: &'a Selector, - state: &'a mut State, - callback: Callback<'a, Ctx, T>, - ctx: &'a mut Ctx, - ) -> Self { - Self( - SelectorSeed { - selector, - state, - callback, - ctx, - // visitor, - // _t: PhantomData, - }, - PhantomData, - ) - } +/// Blanket impl for all `CodecSeed`s that implement `Visitor` for a given `T`. +/// Doing this allows us to focus selection implementations on what to do when +/// visiting a particular representation. +/// +impl<'a, 'de, const C: u64, const RK: u32, S, T> DeserializeSeed<'de> for CodecSeed +where + Self: Visitor<'de> + IpldVisitorExt<'de>, + // Ctx: Context, + // T: Select, + T: Representation, +{ + type Value = >::Value; - /// #[inline] - #[doc(hidden)] - pub(crate) fn into_parts( - self, - ) -> ( - &'a Selector, - &'a mut State, - Callback<'a, Ctx, T>, - &'a mut Ctx, - ) { - (self.0.selector, self.0.state, self.0.callback, self.0.ctx) + fn deserialize(self, deserializer: De) -> Result + where + De: Deserializer<'de>, + { + use Kind as K; + + match (Self::schema_kind(), T::REPR_KIND) { + _ if T::__IGNORED => deserializer.deserialize_ignored_any(self), + (_, K::Null) => deserializer.deserialize_unit(self), + (_, K::Bool) => deserializer.deserialize_bool(self), + (K::Int8, K::Int) => deserializer.deserialize_i8(self), + (K::Int16, K::Int) => deserializer.deserialize_i16(self), + (K::Int32, K::Int) => deserializer.deserialize_i32(self), + (K::Int64, K::Int) => deserializer.deserialize_i64(self), + (K::Int128, K::Int) => deserializer.deserialize_i128(self), + (K::Uint8, K::Int) => deserializer.deserialize_u8(self), + (K::Uint16, K::Int) => deserializer.deserialize_u16(self), + (K::Uint32, K::Int) => deserializer.deserialize_u32(self), + (K::Uint64, K::Int) => deserializer.deserialize_u64(self), + (K::Uint128, K::Int) => deserializer.deserialize_u128(self), + (K::Float32, K::Float) => deserializer.deserialize_f32(self), + (K::Float64, K::Float) => deserializer.deserialize_f64(self), + (_, K::String) => deserializer.deserialize_str(self), + (_, K::Bytes) => { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_bytes(deserializer, self); + } + deserializer.deserialize_bytes(self) + } + (_, K::List) => deserializer.deserialize_seq(self), + (_, K::Map) => deserializer.deserialize_map(self), + (_, K::Link) => { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_cid(deserializer, self); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::deserialize_cid(deserializer, self); + } + deserializer.deserialize_any(self) + } + _ => { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_any(deserializer, self); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::deserialize_any(deserializer, self); + } + deserializer.deserialize_any(self) + } + } } } -impl<'de, const C: u64, T> CodecSeed, T> -// where -// Self: Visitor<'de>, -{ - #[inline] - #[doc(hidden)] - pub fn empty() -> Self { - CodecSeed(PhantomData, PhantomData) - } +impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed, T> { + // /// + // #[inline] + // pub(crate) fn from_parts( + // selector: &'a Selector, + // state: &'a mut State, + // callback: Callback<'a, Ctx, T>, + // ctx: &'a mut Ctx, + // ) -> Self { + // Self( + // SelectorSeed { + // selector, + // state, + // callback, + // ctx, + // // visitor, + // // _t: PhantomData, + // }, + // PhantomData, + // ) + // } + + // /// + // #[inline] + // #[doc(hidden)] + // pub(crate) fn into_parts( + // self, + // ) -> ( + // &'a Selector, + // &'a mut State, + // Callback<'a, Ctx, T>, + // &'a mut Ctx, + // ) { + // (self.0.selector, self.0.state, self.0.callback, self.0.ctx) + // } } +// impl<'de, const C: u64, T> CodecSeed, T> +// // where +// // Self: Visitor<'de>, +// { +// #[inline] +// #[doc(hidden)] +// pub fn empty() -> Self { +// CodecSeed(PhantomData, PhantomData) +// } +// } +// // impl<'a, const C: u64, Ctx, T> CodecSeed> { // fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { // Self(inner) @@ -89,18 +214,18 @@ impl<'de, const C: u64, T> CodecSeed, T> // Self(inner) // } // } -impl<'a, const C: u64, Ctx, T> From> - for CodecSeed, T> -{ - fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { - Self(inner, PhantomData) - } -} -impl From> for CodecSeed, T> { - fn from(inner: PhantomData) -> Self { - Self(inner, PhantomData) - } -} +// impl<'a, const C: u64, Ctx, T> From> +// for CodecSeed, T> +// { +// fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { +// Self(inner, PhantomData) +// } +// } +// impl From> for CodecSeed, T> { +// fn from(inner: PhantomData) -> Self { +// Self(inner, PhantomData) +// } +// } // impl<'a, const C: u64, Ctx, T> Into> for SelectorSeed<'a, Ctx, T> { // fn into(self) -> CodecSeed { // CodecSeed(self) @@ -112,16 +237,10 @@ impl From> for CodecSeed // } // } -// impl CodecSeed { -// pub fn into_inner(self) -> T { -// self.0 -// } -// } - /// #[doc(hidden)] -pub type CodedSelectorSeed<'a, const C: u64, const D: bool, Ctx, T> = - CodecSeed, T>; +pub type CodedSelectorSeed<'a, const C: u64, const RK: u32, Ctx, T> = + CodecSeed, T>; // /// Replacement trait for [`serde::de::DeserializeSeed`], that allows us to // /// switch deserialization behaviour based on the current block's [`Codec`]. @@ -136,10 +255,10 @@ pub type CodedSelectorSeed<'a, const C: u64, const D: bool, Ctx, T> = // pub trait CodecDeserializeSeed<'de> { // type Value; // // pub trait CodecDeserializeSeed<'de>: DeserializeSeed<'de, Value = ()> { -// fn deserialize(self, deserializer: D) -> Result +// fn deserialize(self, deserializer: RK) -> Result // where // // CodecSeed: DeserializeSeed<'de, Value = ()>, -// D: Deserializer<'de>; +// RK: Deserializer<'de>; // // { // // // CodecSeed::(self).deserialize(deserializer) // // DeserializeSeed::<'_>::deserialize(self, deserializer) @@ -165,11 +284,11 @@ pub type CodedSelectorSeed<'a, const C: u64, const D: bool, Ctx, T> = // // { // // type Value = T; // // -// // fn deserialize(self, deserializer: D) -> Result +// // fn deserialize(self, deserializer: RK) -> Result // // where -// // D: Deserializer<'de>, +// // RK: Deserializer<'de>, // // { -// // ::deserialize::(deserializer) +// // ::deserialize::(deserializer) // // } // // } // // @@ -177,11 +296,11 @@ pub type CodedSelectorSeed<'a, const C: u64, const D: bool, Ctx, T> = // // // where // // // CodecSeed: DeserializeSeed<'de, Value = ()>, // // { -// // const D: bool = false; +// // const RK: u32 = false; // // type Value = (); // // fn deserialize(self, deserializer: De) -> Result<(), De::Error> // // where -// // // CodecSeed as CodecDeserializeSeed<'de>>::D }, Self>: +// // // CodecSeed as CodecDeserializeSeed<'de>>::RK }, Self>: // // // DeserializeSeed<'de, Value = ()>, // // De: Deserializer<'de>, // // { @@ -203,226 +322,7 @@ where } } -// TODO: impl this for every Selectable T, defining: -// TODO: 1) how to create Self from T's own visitor -// TODO: 2) defining which deserializer method to call -// default impl<'a: 'de, 'de, Ctx, T> DeserializeSeed<'de> for SelectorSeed<'a, Ctx, T, T> -// where -// Ctx: Context, -// T: Representation, -// { -// type Value = Option; -// -// #[inline] -// fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// Err(D::Error::custom("unimplemented")) -// } -// } -// -// TODO: impl this for every Selectable T, defining: -// TODO: 1) what to do when visited based on the current selector -// TODO: 2) how to create Self as a seed for the next type to deserialize -// impl<'de, Ctx, T> IpldVisitorExt<'de> for SelectorSeed -// where -// Ctx: Context, -// T: Representation, -// // V: Visitor<'de>, -// { -// type Value = T; -// -// fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// unimplemented!() -// } -// } -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// pub trait FromContext { -// fn from(ctx: &Ctx) -> &Self; -// } -// -// impl FromContext for () { -// fn from(_ctx: &Ctx) -> &Self { -// &NULL_CONTEXT -// } -// } -// -// impl FromContext for Ctx -// where -// Ctx: Context, -// S: ISelector, -// { -// fn from(ctx: &Ctx) -> &Self { -// ctx -// } -// } -// -// /// An execution context for `Representation`s to `Read`/`Write` themselves from/to bytes by signalling `State` changes to the `Context`. -// #[async_trait] -// pub trait Context: Sized { -// type Error: Into; -// -// // /// Provides ... -// // fn codec(&self) -> Codec; -// -// // /// `Read`s the `Representation` using the provided `Context`. -// // async fn decode(&self) -> Result -// // where -// // T: Representation, -// // { -// // T::decode(self).await -// // } -// // -// // /// -// // async fn encode(&self, value: T) -> Result, Self::Error> -// // where -// // T: Representation -// // { -// // value.encode(self).await?; -// // Ok(None) -// // } -// -// // /// -// // async fn read_with_ctx(&self) -> Result -// // where -// // Ctx: Command, -// // NewCtx: Handler, -// // NewCo: Codec, -// // T: Representation, -// // Self: IntoHandler, -// // { -// // self.into_handler().read().await -// // } -// // -// // /// -// // async fn write_with_ctx(&self, value: T) -> Result, -// // Self::Error>; -// -// // /// Ask the `Context` how much of the type to `Resolve`. -// // async fn resolve_range(&self) -> ResolveRange; -// -// // /// -// // async fn resolve_block(&self, cid: &Cid) -> Result<(), Error>; -// -// // /// -// // async fn flush_block(&self) -> Result; -// -// // /// Attempts to apply the current `Command`, triggering optional -// // /// side-effects within `Context`, allowing it to drive the -// // /// `Representation` operation. -// // /// -// // /// This is done by implementing `Handler` for your `Context`(s) for each -// // /// `Command` your IPLD types require. -// // async fn apply(&self, command: Ctx) -> Ctx::Result -// // where -// // Co: 'async_trait, -// // R: 'async_trait, -// // W: 'async_trait, -// // Ctx: Command + Send, -// // H: Handler + Send + Sync, -// // Self: IntoHandler, -// // { -// // self.into_handler().handle(command).await -// // } -// } -// -///// Handles a `Context` `Command`. -//#[async_trait] -//pub trait Handler: Context -//where -// Co: Codec, -// R: Read, -// W: Write, -//{ -// type Command: Command; -// -// /// -// async fn handle(&self, command: Self::Command) -> ::Result; -//} -// -///// Converts a `Context` into a `Handler` that can apply a `Command`. -//pub trait IntoHandler: Context -//where -// Co: Codec, -// R: Read, -// W: Write, -// Ctx: Command, -// H: Handler, -//{ -// fn into_handler(&self) -> &H; -//} -// -///// Blanket conversion for a given `Context` that can already `Handler` a -///// given `Command`. -//impl IntoHandler for H -//where -// Co: Codec, -// R: Read, -// W: Write, -// Ctx: Command, -// H: Handler, -//{ -// fn into_handler(&self) -> &H { -// self -// } -//} -// -// impl CodecExt for Ctx -// where -// Ctx: Codec + Context<>, R, W>, -// R: Read, -// W: Write, -// T: Representation>, R, W>, -// { -// async fn read(reader: &mut R) -> Result::Error> -// where -// R: Read + Seek + Unpin + Send, -// T: 'async_trait; -// -// /// -// async fn write(t: &T, writer: &mut W) -> Result<(), ::Error> -// where -// W: Write + Seek + Unpin + Send, -// T: Sync; -// -// /// -// async fn read_offsets(reader: &mut R) -> Result<(u8, usize, u8), ::Error> -// where -// R: Read + Seek + Unpin + Send, -// T: 'async_trait; -// -// /// -// async fn write_offsets( -// t: &T, -// writer: &mut W, -// ) -> Result<(u8, usize, u8), ::Error> -// where -// W: Write + Seek + Unpin + Send, -// T: Sync; -// } - +// TODO: be lazier: provide a mode method that lets us skip any dag-deserialization work, while also letting us just call what we want without a lot of branching impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, @@ -440,19 +340,27 @@ where // } // } + // pub fn empty() -> EmptySeed { + // static DEFAULT_SELECTOR: Selector = Selector::DEFAULT; + // SelectorSeed { + // selector: DEFAULT_SELECTOR, + // } + // } + /// #[inline] pub const fn mode(&self) -> SelectionMode { match &self.callback { - Callback::SelectNode { .. } => SelectionMode::SelectNode, - Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::SelectDag, + Callback::SelectNode { .. } if self.selector.is_matcher() => SelectionMode::MatchNode, + Callback::SelectNode { .. } => SelectionMode::CoverNode, + Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::MatchDag, // Self::Patch { .. } => SelectionMode::Patch, } } /// #[inline] - pub const fn is_node(&self) -> bool { + pub const fn is_node_select(&self) -> bool { match self.callback { Callback::SelectNode { .. } => true, _ => false, @@ -461,7 +369,7 @@ where /// #[inline] - pub const fn is_dag(&self) -> bool { + pub const fn is_dag_select(&self) -> bool { match self.callback { Callback::SelectDag { .. } | Callback::MatchDag { .. } => true, _ => false, @@ -481,23 +389,30 @@ where state, callback, ctx, - // visitor, - // _t: PhantomData, } } /// - #[inline] - #[doc(hidden)] - pub(crate) fn into_parts( - self, - ) -> ( - &'a Selector, - &'a mut State, - Callback<'a, Ctx, T>, - &'a mut Ctx, - ) { - (self.selector, self.state, self.callback, self.ctx) + pub fn wrap(self, conv: F) -> SelectorSeed<'a, Ctx, U> + where + Ctx: 'a, + U: Representation + 'static, + T: 'static, + // T: From + 'static, + F: Fn(U) -> T + Clone + 'a, + { + let Self { + selector, + state, + callback, + ctx, + } = self; + SelectorSeed { + selector, + state, + callback: callback.wrap::(conv), + ctx, + } } } @@ -508,145 +423,107 @@ where T: Representation, { /// - #[doc(hidden)] - #[inline] - pub fn select(params: Params<'_, Ctx, T>, mut ctx: &mut Ctx) -> Result<(), Error> - where - Ctx: 'a, - T: Select, - { - let Params { - cid, - selector, - max_path_depth, - max_link_depth, - callback, - } = params; - let mut state = State { - max_path_depth, - max_link_depth, - ..Default::default() - }; - - let root_cid = cid.ok_or_else(|| { - Error::InvalidSelectionParams("selection must start against some cid") - })?; - let block = ctx.block_reader(&root_cid)?; - let default_selector = Selector::DEFAULT; - let seed = SelectorSeed { - selector: &selector.unwrap_or(&default_selector), - state: &mut state, - callback, - ctx: &mut ctx, - }; - - root_cid.multicodec()?.read_from_seed(seed, block)?; - Ok(()) - } - - /// - pub(crate) fn select_node(&mut self, node: SelectedNode) -> Result<(), Error> { - self.callback - .select_node(NodeSelection::new(self.state.path(), node), self.ctx) - } - - /// - pub(crate) fn select_matched_node( - &mut self, - node: SelectedNode, - label: Option<&str>, - ) -> Result<(), Error> { - self.callback.select_node( - NodeSelection::new_match(self.state.path(), node, label), - self.ctx, - ) + pub fn select_node(&mut self, node: SelectedNode) -> Result<(), Error> { + if let Some(matcher) = self.selector.as_matcher() { + self.callback.select_node( + self.state.path(), + node, + true, + matcher.label.as_deref(), + self.ctx, + ) + } else { + self.callback + .select_node(self.state.path(), node, false, None, self.ctx) + } } /// - pub(crate) fn select_matched_dag(&mut self, dag: T, label: Option<&str>) -> Result<(), Error> + pub fn select_dag(&mut self, dag: T) -> Result<(), Error> where T: Representation + 'static, { + let matcher = self.selector.try_as_matcher()?; self.callback - .select_dag(DagSelection::new(self.state.path(), dag, label), self.ctx) + .select_dag((self.state.path(), dag, matcher.label.as_deref()), self.ctx) } - #[inline] - pub(crate) fn field_select_seed<'b, U>( - selector: &'b Selector, - state: &'b mut State, - callback: &mut Callback<'a, Ctx, T>, - ctx: &'b mut Ctx, - field: Field<'b>, + /// + fn to_field_select_seed<'b, U>( + &'b mut self, + field: &Field<'b>, match_cb: Option + 'b>>, + // match_cb: Option<&'b mut dyn MatchDagOp>, // match_cb: Option ) -> Result, Error> where - 'a: 'b, + // 'a: 'b, + // Ctx: 'a, U: Representation, // F: FnOnce(U, Ctx) -> Result<(), Error>, { - let next = selector - .next(Some(&field)) - .ok_or_else(|| Error::missing_next_selector(selector))?; - let callback = match (match_cb, callback) { - // - (None, Callback::SelectNode { cb, only_matched }) => Callback::SelectNode { - cb: cb.clone(), - only_matched: *only_matched, - }, - // - (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, - // matching the field - (Some(field_cb), _) => Callback::MatchDag { cb: field_cb }, - _ => unreachable!(), - }; + let selector = self.selector.try_next(Some(field))?; + self.state.descend::(&field)?; + Ok(SelectorSeed { + selector, + state: self.state, + callback: self.callback.wrap_match::(match_cb), + ctx: self.ctx, + }) + } - state.descend::(field)?; - Ok(SelectorSeed::from_parts(next, state, callback, ctx)) + /// Execute the next [`Selector`] against the next element of the + /// [`ListIterator`]. + pub fn select_index<'b, const C: u64, U>( + &'b mut self, + index: usize, + match_cb: Option + 'b>>, + // match_cb: Option<&'b mut dyn MatchDagOp>, + iter: &mut impl ListIterator, + ) -> Result + where + U: Select, + { + let res = iter.next_seed::({ + let field = index.into(); + self.state.descend::(&field)?; + SelectorSeed { + selector: self.selector.try_next(Some(&field))?, + state: self.state, + callback: self.callback.wrap_match::(match_cb), + ctx: self.ctx, + } + })?; + self.state.ascend::()?; + + Ok(res) } - // pub(crate) fn select_field<'b, 'de, U, D>( - // &'b mut self, - // field: Field<'b>, - // match_cb: Option + 'b>>, - // deserializer: D, - // ) -> Result<(), D::Error> - // where - // 'a: 'b, - // U: Representation + Select, - // D: Deserializer<'de>, - // { - // let next = self - // .selector - // .next(Some(&field)) - // .ok_or_else(|| Error::missing_next_selector(self.selector)) - // .map_err(D::Error::custom)?; - // let callback = match (match_cb, &self.callback) { - // // - // (None, Callback::SelectNode { cb, only_matched }) => Callback::SelectNode { - // cb: cb.clone(), - // only_matched: *only_matched, - // }, - // // - // (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, - // // matching the field - // (Some(field_cb), _) => Callback::MatchDag { cb: field_cb }, - // _ => unreachable!(), - // }; - // self.state.descend::(field).map_err(D::Error::custom)?; - // - // let seed = SelectorSeed { - // selector: next, - // state: &mut self.state, - // callback, - // ctx: &mut self.ctx, - // }; - // - // U::__select_from(seed, deserializer).map_err(D::Error::custom)?; - // self.state.ascend::().map_err(D::Error::custom)?; - // Ok(()) - // } + /// + pub fn select_field<'b, const C: u64, K, V>( + &'b mut self, + // key: &K, + match_cb: Option + 'b>>, + iter: &mut impl MapIterator, + ) -> Result<(), Error> + where + K: StringRepresentation, + V: Select, + { + iter.next_value_seed::({ + let field = iter.field(); + self.state.descend::(&field)?; + SelectorSeed { + selector: self.selector.try_next(Some(&field))?, + state: self.state, + callback: self.callback.wrap_match::(match_cb), + ctx: self.ctx, + } + })?; + self.state.ascend::()?; + + Ok(()) + } } // patch methods @@ -717,55 +594,28 @@ where /// IPLD types. #[macro_export] macro_rules! impl_selector_seed_serde { - // visitor for SelectorSeed - - // // impl Visitor for SelectorSeed - // (@selector_seed_visitor - // { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ty - // { $($visit_fns:tt)* } - // ) => { - // impl<'a, 'de, Ctx, $($generics)*> $crate::dev::Visitor<'de> for $crate::dev::SelectorSeed<'a, Ctx, $ty> - // where - // Ctx: $crate::dev::Context, - // $($bounds)* - // { - // type Value = (); - // - // $($visit_fns)* - // } - // }; - // // impl IpldVisitorExt for SelectorSeed - // (@selector_seed_visitor_ext - // { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ty - // { $($visit_fns:tt)* } - // ) => { - // impl<'a, 'de, Ctx, $($generics)*> $crate::dev::IpldVisitorExt<'de> for $crate::dev::SelectorSeed<'a, Ctx, $ty> - // where - // Ctx: $crate::dev::Context, - // $($bounds)* - // { - // $($visit_fns)* - // } - // }; - // visitor for CodedSeed // impl Visitor for CodedSeed (@codec_seed_visitor { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty + $ty:ident $(< + // match one or more lifetimes separated by a comma + $( $ty_generics:ident ),+ + >)? { $($visit_fns:tt)* } ) => { const _: () = { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = false; + const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> Visitor<'de> for - CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> + CodecSeed<_C, _RK, + SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + $ty $(<$($ty_generics),+>)? + > where Ctx: Context, $($bounds)* @@ -779,10 +629,10 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = true; + // const _RK: u32 = true; // impl<'a, 'de, const _C: u64, $($generics)*> // Visitor<'de> for - // CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> // where // $($generics)* // { @@ -791,20 +641,60 @@ macro_rules! impl_selector_seed_serde { // } }; }; + // impl Visitor for CodedSeed by REPR_KIND + (@codec_seed_visitor_rk $rk:ident + { $($generics:tt)* } { $($bounds:tt)* } + $ty:ident + // $(< + // // match one or more lifetimes separated by a comma + // $( $ty_generics:ident ),+ + // >)? + { $($visit_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); + const _RK: u32 = Kind::$rk.bits(); + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + Visitor<'de> for + CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> + where + // T: Representation + // T: Select, + // Assert::<{ $ty::REPR_KIND.eq(Kind::$rk) }>: IsTrue, + Ctx: Context, + $($bounds)* + { + type Value = (); + $($visit_fns)* + } + }; + + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } + }; + // impl IpldVisitorExt for CodedSeed (@codec_seed_visitor_ext { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty + $ty:ident $(< + // match one or more lifetimes separated by a comma + $( $ty_generics:ident ),+ + >)? { $($visit_fns:tt)* } ) => { const _: () = { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = false; + const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> IpldVisitorExt<'de> for - CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> + CodecSeed<_C, _RK, + SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + $ty $(<$($ty_generics),+>)? + > where Ctx: Context, $($bounds)* @@ -817,10 +707,10 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = true; + // const _RK: u32 = true; // impl<'a, 'de, const _C: u64, $($generics)*> // IpldVisitorExt<'de> for - // CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> // where // $($generics)* // { @@ -841,7 +731,7 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = false; + // const _RK: u32 = false; // impl<'_a, 'de, Ctx, $($generics)*> // CodecDeserializeSeed<'de> for // SelectorSeed<'_a, Ctx, $ty> @@ -851,27 +741,25 @@ macro_rules! impl_selector_seed_serde { // { // type Value = (); // $($deseed_fn)* - // // CodecSeed::(self).deserialize(deserializer) + // // CodecSeed::(self).deserialize(deserializer) // } - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - DeserializeSeed<'de> for - CodecSeed<_C, _D, SelectorSeed<'_a, Ctx, $ty>, $ty> - where - Ctx: Context, - // Self: Visitor<'de>, - { - // type Value = >::Value; - type Value = (); - $($deseed_fn)* - } + // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // DeserializeSeed<'de> for + // CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> + // where + // Ctx: Context, + // { + // type Value = (); + // $($deseed_fn)* + // } }; const _: () = { #[allow(unused_imports)] use $crate::dev::*; - const _D: bool = true; + // const _RK: u32 = true; // impl<'a, 'de, $($generics)*> // $crate::dev::CodecDeserializeSeed<'de> for // std::marker::PhantomData<$ty> @@ -882,7 +770,7 @@ macro_rules! impl_selector_seed_serde { // impl<'de, const _C: u64 $($generics)*> // $crate::dev::DeserializeSeed<'de> for - // $crate::dev::CodecSeed<_C, _D, std::marker::PhantomData<$ty>> + // $crate::dev::CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> // where // Self: $crate::dev::Visitor<'de>, // { @@ -933,6 +821,7 @@ macro_rules! impl_selector_seed_serde { $ty:ty ) => { const _: () = { + #[allow(unused_imports)] use $crate::dev::*; impl Select for $ty @@ -940,57 +829,58 @@ macro_rules! impl_selector_seed_serde { Ctx: Context, $($bounds)* { - #[inline] - fn select( - params: Params<'_, Ctx, Self>, - ctx: &mut Ctx, - ) -> Result<(), Error> { - SelectorSeed::<'_, Ctx, Self>::select(params, ctx) - } - - #[doc(hidden)] - fn __select_from_deserializer<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = CodecSeed::::from(seed); - seed.deserialize(deserializer) - } - - #[doc(hidden)] - fn __select_from_seq<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - mut seq: A, - ) -> Result, A::Error> - where - A: SeqAccess<'de>, - { - let seed = CodecSeed::::from(seed); - seq.next_element_seed(seed) - } - - #[doc(hidden)] - fn __select_from_map<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - mut map: A, - is_key: bool, - ) -> Result, A::Error> - where - A: MapAccess<'de>, - { - let seed = CodecSeed::::from(seed); - if is_key { - map.next_key_seed(seed) - } else { - Ok(Some(map.next_value_seed(seed)?)) - } - } + // #[inline] + // fn select( + // params: Params<'_, Ctx, Self>, + // ctx: &mut Ctx, + // ) -> Result<(), Error> { + // SelectorSeed::<'_, Ctx, Self>::select(params, ctx) + // } + + // #[doc(hidden)] + // fn __select_de<'a, 'de, const C: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // let seed = CodecSeed::::from(seed); + // seed.deserialize(deserializer) + // } + + // #[doc(hidden)] + // fn __select_seq<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // mut seq: A, + // ) -> Result, A::Error> + // where + // A: SeqAccess<'de>, + // { + // let seed = CodecSeed::::from(seed); + // seq.next_element_seed(seed) + // } + + // #[doc(hidden)] + // fn __select_map<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // mut map: A, + // is_key: bool, + // ) -> Result, A::Error> + // where + // A: MapAccess<'de>, + // { + // let seed = CodecSeed::::from(seed); + // if is_key { + // map.next_key_seed(seed) + // } else { + // Ok(Some(map.next_value_seed(seed)?)) + // } + // } } }; }; + /* (@seed_from_params $params:ident $ctx:ident) => {{ let Params { cid, @@ -1018,9 +908,78 @@ macro_rules! impl_selector_seed_serde { ctx: &mut $ctx, } }}; + */ // newtype impls + (@select_newtype + { $($generics:tt)* } { $($bounds:tt)* } + $ty:ty { $constructor:expr => $inner_ty:ty } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + impl Select for $ty + where + Ctx: Context, + $($bounds)* + { + #[doc(hidden)] + #[inline] + fn __select<'a, 'de, const C: u64>( + seed: SelectorSeed<'a, Ctx, Self>, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = seed.wrap::<$inner_ty, _>($constructor); + <$inner_ty>::__select::(seed, deserializer) + } + + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = seed.wrap::<$inner_ty, _>($constructor); + <$inner_ty>::__select_de::(seed, deserializer) + } + + #[doc(hidden)] + #[inline] + fn __select_seq<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + seq: A, + ) -> Result, A::Error> + where + A: SeqAccess<'de>, + { + let seed = seed.wrap::<$inner_ty, _>($constructor); + <$inner_ty>::__select_seq::(seed, seq) + } + + #[doc(hidden)] + #[inline] + fn __select_map<'a, 'de, const C: u64, A>( + seed: SelectorSeed<'a, Ctx, Self>, + map: A, + is_key: bool, + ) -> Result, A::Error> + where + A: MapAccess<'de>, + { + let seed = seed.wrap::<$inner_ty, _>($constructor); + <$inner_ty>::__select_map::(seed, map, is_key) + } + } + }; + }; + + // TODO: instead of transmuting cb in DeSeed, transmute it in Select (@selector_seed_codec_deseed_newtype { $($generics:tt)* } { $($bounds:tt)* } // TODO: this should probably by a ty @@ -1029,17 +988,12 @@ macro_rules! impl_selector_seed_serde { $crate::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed { $($generics)* } { $($bounds)* } $ty { - // #[inline] - // fn deserialize(self, deserializer: D) -> Result - // where - // D: Deserializer<'de>, - // { #[inline] fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { - if _D { + if _RK { unimplemented!() } else { let inner_seed = macros::impl_selector_seed_serde! { @@ -1068,9 +1022,8 @@ macro_rules! impl_selector_seed_serde { (@selector_seed_wrap $seed:ident { $constructor:expr => $inner_ty:ty }) => {{ use $crate::dev::{DagSelection, Callback::*}; - let (selector, state, callback, ctx) = $seed.0.into_parts(); + let SelectorSeed { selector, state, callback, ctx } = $seed.0; let callback = match callback { - SelectNode { cb, only_matched } => SelectNode { cb, only_matched }, SelectDag { mut cb } => SelectDag { cb: Box::new(move |selection, ctx| { let inner_dag = selection.dag.downcast::<$inner_ty>()?; @@ -1078,9 +1031,10 @@ macro_rules! impl_selector_seed_serde { cb(DagSelection { dag: dag.into(), ..selection }, ctx) }), }, + cb => cb.clone(), _ => unreachable!(), }; - Self::from(SelectorSeed::from_parts(selector, state, callback, ctx)) + Self::from(SelectorSeed { selector, state, callback, ctx }) }}; // (@empty $seed:ident $constructor:expr => $inner_ty:tt) => { unimplemented!() }; @@ -1229,7 +1183,7 @@ where pub struct SeqIterDecoder { pub seq: A, - pub end: bool, + pub end: u32, _t: PhantomData<(C, T, U)>, } diff --git a/src/selectors/selectors.rs b/src/selectors/selectors.rs index 650e594..1368eb2 100644 --- a/src/selectors/selectors.rs +++ b/src/selectors/selectors.rs @@ -1,8 +1,8 @@ use crate::dev::*; use macros::derive_more::{AsMut, AsRef, From, TryInto}; -use std::{ +use maybestd::{ fmt, - path::{Path, PathBuf}, + ops::{Bound, Range, RangeBounds, RangeFrom, RangeInclusive}, rc::Rc, str::FromStr, }; @@ -18,43 +18,46 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From, TryInto)] pub type SelectorEnvelope union { + /// | Selector "selector" - } representation keyed; + } representation keyed } schema! { + /// #[ipld_attr(internal)] #[derive(Clone, Debug, From, TryInto)] // #[from(forward)] #[try_into(owned, ref, ref_mut)] pub type Selector union { + /// | Matcher "." - + /// #[ipld_attr(wrapper = "Rc")] | ExploreAll "a" - + /// | ExploreFields "f" - + /// #[ipld_attr(wrapper = "Rc")] | ExploreIndex "i" - + /// #[ipld_attr(wrapper = "Rc")] | ExploreRange "r" - + /// #[ipld_attr(wrapper = "Rc")] | ExploreRecursive "R" - - // #[ipld_attr(wrapper = "Rc")] + /// + #[ipld_attr(wrapper = "Rc")] | ExploreUnion "|" - - // #[ipld_attr(wrapper = "Rc")] - // | ExploreConditional "&" - + /// + #[ipld_attr(wrapper = "Rc")] + | ExploreConditional "&" + /// | ExploreRecursiveEdge "@" - + /// #[ipld_attr(wrapper = "Rc")] | ExploreInterpretAs "~" - } representation keyed; + } representation keyed } schema! { @@ -64,8 +67,8 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, Default, From)] pub type ExploreAll struct { - pub next Selector (rename ">"), - }; + next Selector (rename ">") + } } schema! { @@ -79,19 +82,19 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From)] pub type ExploreFields struct { - // pub fields {String:Selector} (rename "f>"), - }; + // fields {String:Selector} (rename "f>"), + } } schema! { /// ExploreIndex traverses a specific index in a list, and applies a next /// selector to the reached node. #[ipld_attr(internal)] - #[derive(Clone, Debug, From)] + #[derive(Clone, Debug)] pub type ExploreIndex struct { - pub index Int (rename "i"), - pub next Selector (rename ">"), - }; + index Int (rename "i") + next Selector (rename ">") + } } schema! { @@ -100,10 +103,10 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug)] pub type ExploreRange struct { - pub start Int (rename "^"), - pub end Int (rename "$"), - pub next Selector (rename ">"), - }; + start Int (rename "^") + end Int (rename "$") + next Selector (rename ">") + } } schema! { @@ -150,11 +153,13 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug)] pub type ExploreRecursive struct { - pub sequence Selector (rename ":>"), - pub limit RecursionLimit (rename "l"), + /// + pub sequence Selector (rename ":>") + /// + pub limit RecursionLimit (rename "l") /// if a node matches, we won't match it nor explore it's children - pub stopAt optional Condition (rename "!"), - }; + pub stopAt optional Condition (rename "!") + } } schema! { @@ -162,22 +167,24 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From)] pub type RecursionLimit union { + /// | RecursionLimit_None "none" + /// | RecursionLimit_Depth "depth" - } representation keyed; + } representation keyed } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type RecursionLimit_None struct {}; + pub type RecursionLimit_None struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug, From)] #[from(forward)] - pub type RecursionLimit_Depth int; + pub type RecursionLimit_Depth int } schema! { @@ -192,7 +199,7 @@ schema! { /// enclosing ExploreRecursive is an error. #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type ExploreRecursiveEdge struct {}; + pub type ExploreRecursiveEdge struct {} } schema! { @@ -204,7 +211,7 @@ schema! { /// simultaneously continuing to explore deeper parts of the tree with /// another selector, for example. #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, From)] pub type ExploreUnion null; // pub type ExploreUnion [Selector]; } @@ -217,9 +224,9 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From)] pub type ExploreConditional struct { - pub condition Condition (rename "&"), - pub next Selector (rename ">"), - }; + condition Condition (rename "&") + next Selector (rename ">") + } } schema! { @@ -231,9 +238,9 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From)] pub type ExploreInterpretAs struct { - pub r#as String, - pub next Selector (rename ">"), - }; + r#as String + next Selector (rename ">") + } } schema! { @@ -244,9 +251,9 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, Default)] pub type Slice struct { - pub from Int (rename "["), - pub to Int (rename "]"), - }; + from Int (rename "[") + to Int (rename "]") + } } schema! { @@ -264,13 +271,13 @@ schema! { #[derive(Clone, Debug, Default, From)] pub type Matcher struct { /// match is true based on position alone if this is not set. - pub onlyIf optional Condition, + pub onlyIf optional Condition /// labels can be used to match multiple different structures in one selection. - pub label optional String, + pub label optional String /// if set, only the subset of the node specified by the slice is matched. - pub subset optional Slice, + pub subset optional Slice - }; + } } schema! { @@ -287,6 +294,7 @@ schema! { #[ipld_attr(internal)] #[derive(Clone, Debug, From)] pub type Condition union { + /// | Condition_HasField "hasField" /// # will need to contain a kinded union, lol. these conditions are gonna get deep.) | Condition_HasValue "=" @@ -297,60 +305,64 @@ schema! { | Condition_HasKind "%" /// will need this so we can use it in recursions to say "stop at CID QmFoo". | Condition_IsLink "/" + /// | Condition_GreaterThan "greaterThan" + /// | Condition_LessThan "lessThan" + /// | Condition_And "and" + /// | Condition_Or "or" - } representation keyed; + } representation keyed } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_HasField struct {}; + pub type Condition_HasField struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_HasValue struct {}; + pub type Condition_HasValue struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_HasKind struct {}; + pub type Condition_HasKind struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_IsLink struct {}; + pub type Condition_IsLink struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_GreaterThan struct {}; + pub type Condition_GreaterThan struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_LessThan struct {}; + pub type Condition_LessThan struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_And struct {}; + pub type Condition_And struct {} } schema! { /// #[ipld_attr(internal)] #[derive(Clone, Debug)] - pub type Condition_Or struct {}; + pub type Condition_Or struct {} } /// Sealed marker trait for types that can be used as `Selector`s. @@ -392,12 +404,15 @@ mod private { } macro_rules! impl_variant { - ($variant:ident $selector_ty:ty | { $is:ident, $as:ident, $try_into:ident }) => { + ($variant:ident $selector_ty:ty | + { $is:ident, $as:ident, $try_as:ident, $try_into:ident }) => { impl_variant!(@is $is -> $variant $selector_ty); impl_variant!(@as $as -> $variant $selector_ty); + impl_variant!(@try_as $try_as -> $variant $selector_ty); // impl_variant!(@try_into $try_into -> $variant $selector_ty); }; - (@wrapped $variant:ident $selector_ty:ty | { $is:ident, $as:ident, $try_into:ident }) => { + (@wrapped $variant:ident $selector_ty:ty | + { $is:ident, $as:ident, $try_as:ident, $try_into:ident }) => { impl_variant!(@is $is -> $variant $selector_ty); impl_variant!(@as $as -> $variant $selector_ty); // impl_variant!(@try_into $try_into -> $variant Rc<$selector_ty>); @@ -421,6 +436,15 @@ macro_rules! impl_variant { } } }; + (@try_as $fn:ident -> $variant:ident $selector_ty:ty) => { + #[inline] + pub fn $fn(&self) -> Result<&$selector_ty, Error> { + match self { + Self::$variant(inner) => Ok(inner), + _ => Err(Error::SelectorAssertionFailure), + } + } + }; // (@try_into $fn:ident -> $variant:ident $selector_ty:ty) => { // #[inline] // pub fn $fn(&self) -> Result<&$selector_ty, Error> { @@ -470,49 +494,63 @@ impl Selector { subset: None, }); + /// + pub const fn code(&self) -> char { + match self { + Self::Matcher(_) => Matcher::CODE, + Self::ExploreAll(_) => ExploreAll::CODE, + Self::ExploreFields(_) => ExploreFields::CODE, + Self::ExploreIndex(_) => ExploreIndex::CODE, + Self::ExploreRange(_) => ExploreRange::CODE, + Self::ExploreRecursive(_) => ExploreRecursive::CODE, + Self::ExploreUnion(_) => ExploreUnion::CODE, + Self::ExploreConditional(_) => ExploreConditional::CODE, + Self::ExploreRecursiveEdge(_) => ExploreRecursiveEdge::CODE, + Self::ExploreInterpretAs(_) => ExploreInterpretAs::CODE, + } + } + /// Attempts to produce the next selector to apply, given an optional field /// (key or index). - pub fn next<'a, K>(&self, field: Option) -> Option<&Selector> - where - K: AsRef + AsRef, - { + /// TODO: matcher is infinite; need to distinguish link boundaries + pub fn try_next<'a>(&self, field: Option<&Field<'_>>) -> Result<&Selector, Error> { match (self, field) { - (Self::Matcher(_), _) => Some(self), - (Self::ExploreAll(inner), _) => Some(&inner.next), - (Self::ExploreFields { .. }, _) => todo!(), + (Self::Matcher(_), _) => Ok(self), + (Self::ExploreAll(inner), _) => Ok(&inner.next), // TODO assert that provided field/index matches what the selector defines, otherwise return None - (Self::ExploreIndex(inner), Some(f)) - if inner.index as usize == *(f.as_ref() as &usize) => - { - Some(&inner.next) + (Self::ExploreFields { .. }, Some(f)) => todo!(), + (Self::ExploreIndex(inner), Some(f)) if f.is_idx(inner.index as usize) => { + Ok(&inner.next) } (Self::ExploreRange(inner), Some(f)) - if (inner.start as usize..inner.end as usize).contains(f.as_ref()) => + if f.as_usize() + .filter(|idx| inner.to_range().contains(idx)) + .is_some() => { - Some(&inner.next) + Ok(&inner.next) } - (Self::ExploreRecursive(inner), _) => Some(&inner.sequence), - (Self::ExploreRecursiveEdge(_), _) => None, + (Self::ExploreRecursive(inner), _) => Ok(&inner.sequence), + (Self::ExploreRecursiveEdge(_), _) => todo!(), (Self::ExploreUnion { .. }, _) => todo!(), - (Self::ExploreInterpretAs(inner), _) => Some(&inner.next), - _ => None, + (Self::ExploreInterpretAs(inner), _) => Ok(&inner.next), + _ => Err(Error::missing_next_selector(&self)), } } impl_variant!(Matcher Matcher | - {is_matcher, as_matcher, try_into_matcher}); + {is_matcher, as_matcher, try_as_matcher, try_into_matcher}); impl_variant!(@wrapped ExploreAll ExploreAll | - {is_explore_all, as_explore_all, try_into_explore_all}); - // impl_variant!(ExploreFields ExploreFields | - // {is_explore_fields, as_explore_fields, try_into_explore_fields}); + {is_explore_all, as_explore_all, try_as_explore_all, try_into_explore_all}); + impl_variant!(ExploreFields ExploreFields | + {is_explore_fields, as_explore_fields, try_as_explore_fields, try_into_explore_fields}); impl_variant!(@wrapped ExploreIndex ExploreIndex | - {is_explore_index, as_explore_index, try_into_explore_index}); + {is_explore_index, as_explore_index, try_as_explore_index, try_into_explore_index}); impl_variant!(@wrapped ExploreRange ExploreRange | - {is_explore_range, as_explore_range, try_into_explore_range}); + {is_explore_range, as_explore_range, try_as_explore_range, try_into_explore_range}); // impl_variant!(ExploreRecursive ExploreRecursive | // {is_explore_recursive, as_explore_recursive, try_into_explore_recursive}); - // impl_variant!(ExploreUnion ExploreUnion | - // {is_explore_union, as_explore_union, try_into_explore_union}); + impl_variant!(ExploreUnion ExploreUnion | + {is_explore_union, as_explore_union, try_as_explore_union, try_into_explore_union}); // impl_variant!(ExploreConditional ExploreConditional | // {is_explore_conditional, as_explore_conditional, try_into_explore_conditional); // impl_variant!(ExploreInterpretAs ExploreInterpretAs | @@ -543,30 +581,185 @@ impl FromStr for Selector { } } -/* Slice */ +impl Matcher { + /// + pub const CODE: char = '.'; +} -impl From> for Slice { - fn from(range: std::ops::Range) -> Self { - Self { - from: range.start, - to: range.end, - } +/* ExploreAll */ + +impl ExploreAll { + /// + pub const CODE: char = 'a'; + + /// + pub const fn to_range(&self) -> RangeFrom { + 0usize.. } } -impl From for std::ops::Range { - fn from(slice: Slice) -> std::ops::Range { - std::ops::Range:: { - start: slice.from, - end: slice.to, - } +impl RangeBounds for ExploreAll { + fn start_bound(&self) -> Bound<&Int> { + Bound::Included(&0) + } + fn end_bound(&self) -> Bound<&Int> { + Bound::Unbounded } } /* ExploreFields */ impl ExploreFields { + /// + pub const CODE: char = 'f'; + + /// pub fn contains_key(&self, key: &str) -> bool { unimplemented!() } } + +/* ExploreIndex */ + +impl ExploreIndex { + /// + pub const CODE: char = 'i'; + + /// + pub const fn index(&self) -> Int { + self.index + } + + /// + pub const fn to_range(&self) -> RangeInclusive { + self.index as usize..=self.index as usize + } +} + +impl RangeBounds for ExploreIndex { + fn start_bound(&self) -> Bound<&Int> { + Bound::Included(&self.index) + } + fn end_bound(&self) -> Bound<&Int> { + Bound::Included(&self.index) + } +} + +/* ExploreRange */ + +impl ExploreRange { + /// + pub const CODE: char = 'r'; + + /// + pub const fn start(&self) -> Int { + self.start + } + + /// + pub const fn end(&self) -> Int { + self.end + } + + /// + pub const fn to_range(&self) -> Range { + self.start as usize..self.end as usize + } +} + +impl RangeBounds for ExploreRange { + fn start_bound(&self) -> Bound<&Int> { + Bound::Included(&self.start) + } + fn end_bound(&self) -> Bound<&Int> { + Bound::Excluded(&self.end) + } +} + +/* ExploreRecursive */ + +impl ExploreRecursive { + /// + pub const CODE: char = 'R'; +} + +/* ExploreUnion */ + +impl ExploreUnion { + /// + pub const CODE: char = '|'; + + /// Validates that the first [`Selector`] is a matcher. + pub fn matches_first(&self) -> bool { + // self.0[0].is_matcher() + unimplemented!() + } + + /// Asserts that the first [`Selector`] is a matcher. + pub fn assert_matches_first(&self) -> Result<(), Error> { + if self.matches_first() { + Ok(()) + } else { + // Err(Error::unsupported_selector::(self.0[0])) + unimplemented!() + } + } + + /// Validates that all selectors to perform . + pub fn all_disjoint(&self) -> bool { + // self.0.iter().all(|s| s.code() == code) + unimplemented!() + } + + // pub fn to_ranges(&self) -> impl Iterator> { + // unimplemented!() + // } +} + +/* ExploreConditional */ + +impl ExploreConditional { + /// + pub const CODE: char = '&'; +} + +/* ExploreRecursiveEdge */ + +impl ExploreRecursiveEdge { + /// + pub const CODE: char = '@'; +} + +/* ExploreInterpretAs */ + +impl ExploreInterpretAs { + /// + pub const CODE: char = '~'; +} + +/* Slice */ + +impl Slice { + /// + pub const fn to_range(&self) -> Range { + self.from as usize..self.to as usize + } +} + +impl RangeBounds for Slice { + fn start_bound(&self) -> Bound<&Int> { + Bound::Included(&self.from) + } + fn end_bound(&self) -> Bound<&Int> { + Bound::Excluded(&self.to) + } +} + +impl From> for Slice { + fn from(range: Range) -> Self { + Self { + from: range.start, + to: range.end, + } + } +} diff --git a/src/selectors/state.rs b/src/selectors/state.rs index 1ac19d9..0bc2743 100644 --- a/src/selectors/state.rs +++ b/src/selectors/state.rs @@ -201,6 +201,281 @@ mod callbacks { (**self).clone_box() } } + + /// + #[doc(hidden)] + pub enum Callback<'a, C, T> { + SelectNode { + cb: Box + 'a>, + only_results: bool, + }, + SelectDag { + // TODO: does this need to be cloneable? it is either called on U, or wrapped + cb: Box + 'a>, + }, + MatchDag { + cb: Box + 'a>, + }, // Patch { + // /// current dag we're selecting against + // /// if none, then load and store while patching + // current: &'a mut T, + // flush: bool, + // // op to perform on matching dags, allowing update-inplace + // // op: Box + 'a>, + // // op: PatchFn, + // } + } + + impl<'a, C, T> fmt::Debug for Callback<'a, C, T> + where + C: Context, + T: Representation, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::SelectNode { only_results, .. } => f + .debug_struct("SelectionParams::SelectNode") + .field("source", &T::NAME) + .field("only_results", only_results) + .finish(), + Self::SelectDag { .. } => f + .debug_struct("SelectionParams::SelectDag") + .field("source", &T::NAME) + .finish(), + Self::MatchDag { .. } => f + .debug_struct("SelectionParams::MatchDag") + .field("source", &T::NAME) + .finish(), + // Self::Patch { current, flush, .. } => f + // .debug_struct("SelectionParams::Patch") + // .field("current", ¤t) + // .field("flush", &flush) + // .finish(), + } + } + } + + impl<'a, C, T> Clone for Callback<'a, C, T> + where + C: Context + 'a, + T: Representation + 'a, + { + fn clone(&self) -> Self { + match self { + Self::SelectNode { cb, only_results } => Self::SelectNode { + cb: cb.clone(), + only_results: *only_results, + }, + Self::SelectDag { cb } => Self::SelectDag { cb: cb.clone() }, + Self::MatchDag { cb } => Self::MatchDag { cb: cb.clone() }, + } + } + } + + impl<'a, C, T> Default for Callback<'a, C, T> + where + C: Context, + T: Representation, + { + /// Defaults to a no-op function for selecting nodes. + fn default() -> Self { + Self::SelectNode { + cb: Box::new(|_, _| Ok(())), + only_results: true, + } + } + } + + // impl<'a, C, T, Cb> Into> for Cb + // where + // C: Context, + // T: Representation, + // Cb: SelectNodeOp + 'a, + // { + // fn into(self) -> SelectionCallback<'a, C, T> { + // Self::SelectNode { + // cb: Box::new(self), + // only_results: false, + // } + // } + // } + + impl<'a, C, T> Callback<'a, C, T> + where + C: Context, + T: Representation, + { + // Return a callback that will be called on `U`, providing the original + // callback with `T`. + pub(crate) fn wrap(self, conv: F) -> Callback<'a, C, U> + where + C: 'a, + U: Representation + 'static, + T: 'static, + // T: From + 'static, + F: Fn(U) -> T + Clone + 'a, + { + match self { + Self::SelectNode { cb, only_results } => Callback::SelectNode { cb, only_results }, + Self::SelectDag { mut cb } => { + let cb = Box::new(move |selection: DagSelection, ctx: &mut C| { + let inner_dag = selection.dag.downcast::()?; + let dag = conv(inner_dag).into(); + cb(DagSelection { dag, ..selection }, ctx) + }); + Callback::SelectDag { cb } + } + Self::MatchDag { mut cb } => { + let cb = Box::new(move |dag: U, ctx: &mut C| cb(conv(dag), ctx)); + Callback::MatchDag { cb } + } // _ => unimplemented!(), + } + } + + // TODO: implement a clone method, delegate to that in some branches + pub(crate) fn wrap_match<'b, U>( + &'b mut self, + match_cb: Option + 'b>>, + ) -> Callback<'b, C, U> + where + 'a: 'b, + { + match (match_cb, self) { + // matching the field + (Some(match_cb), _) => Callback::MatchDag { cb: match_cb }, + // + (None, Callback::SelectNode { cb, only_results }) => Callback::SelectNode { + cb: cb.clone(), + only_results: *only_results, + }, + // + (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, + _ => unreachable!(), + } + } + + /* + // #[inline] + // pub(crate) fn select_node(&self, node: SelectedNode) -> Result<(), Error> { + // self.sender()?.send_node(node) + // } + // + // #[inline] + // pub(crate) fn select_dag(&self, dag: SelectedDag) -> Result<(), Error> { + // self.sender()?.send_dag(dag) + // } + // + // #[inline] + // fn sender(&self) -> Result<&SelectionSender, Error> { + // let sender = match self { + // Self::Select { sender, .. } => sender.as_ref(), + // _ => None, + // }; + // + // sender.ok_or_else(|| Error::InvalidSelectionMode("`SelectionParams` missing a channel")) + // } + // + // /// transmutes the select params current source and target + // pub(crate) fn to_select<'b, V, W>(&mut self) -> SelectionParams<'b, C, V, W> + // where + // 'a: 'b, + // C: 'b, + // { + // match self { + // Self::Select { cb, mode, .. } => SelectionParams::Select { + // cb: cb.clone(), + // mode: *mode, + // _t: PhantomData, + // }, + // _ => unreachable!(), + // } + // } + + // /// + // pub const fn mode(&self) -> SelectionMode { + // match self { + // Self::SelectNode { .. } => SelectionMode::SelectNode, + // Self::SelectDag { .. } | Self::MatchDag { .. } => SelectionMode::SelectDag, + // // Self::Patch { .. } => SelectionMode::Patch, + // } + // } + + // /// + // pub const fn is_node(&self) -> bool { + // match self { + // Self::SelectNode { .. } => true, + // _ => false, + // } + // } + + // /// + // pub const fn is_dag(&self) -> bool { + // match self { + // Self::SelectDag { .. } | Self::MatchDag { .. } => true, + // _ => false, + // } + // } + */ + + pub(crate) fn select_node( + &mut self, + path: &Path, + selected_node: SelectedNode, + is_result: bool, + label: Option<&str>, + ctx: &mut C, + ) -> Result<(), Error> { + match self { + Self::SelectNode { cb, .. } if is_result => { + cb(NodeSelection::result(path, selected_node, label), ctx) + } + Self::SelectNode { cb, only_results } if !*only_results => { + cb(NodeSelection::covered(path, selected_node), ctx) + } + Self::SelectNode { .. } => Ok(()), + Self::SelectDag { .. } => Ok(()), + _ => unreachable!(), + } + } + + pub(crate) fn select_dag(&mut self, dag: D, ctx: &mut C) -> Result<(), Error> + where + D: Into, + { + match self { + Self::SelectDag { cb } => cb(dag.into(), ctx), + Self::SelectNode { .. } => Ok(()), + _ => unreachable!(), + } + } + + // // TODO: is this valid? + // pub(super) fn cast<'b, S>(self) -> SelectionCallback<'b, C, S> + // where + // 'a: 'b, + // C: 'b, + // S: Representation + 'static, + // T: From + 'static, + // { + // match self { + // Self::SelectNode { cb, only_results } => { + // SelectionCallback::SelectNode { cb, only_results } + // } + // Self::SelectDag { mut cb } => SelectionCallback::SelectDag { + // cb: Box::new(move |selection, ctx| { + // cb( + // DagSelection { + // dag: selection.dag.cast_between::()?, + // ..selection + // }, + // ctx, + // ) + // }), + // }, + // _ => unreachable!(), + // } + // } + } } /* @@ -239,230 +514,16 @@ where // type SelectFn = fn(U, &mut C) -> Result<(), Error>; // type PatchFn = fn(U, &mut C) -> Result<(), Error>; -/// The selection mode of the selector, which determines what gets visited, -/// matched, sent and returned. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[doc(hidden)] -pub enum SelectionMode { - /// Selection will invoke the provided callback on all traversed [`Node`]s. - SelectNode, - - /// Selection will invoke the provided callback on all matched [`Dag`]s. - SelectDag, - // /// - // MatchDag, - // /// Selection updates matching dags with the output of a callback. - // /// Optionally flushes changes after each callback. - // Patch, -} - -/// -#[doc(hidden)] -pub enum Callback<'a, C, T> { - SelectNode { - cb: Box + 'a>, - only_matched: bool, - }, - SelectDag { - // TODO: does this need to be cloneable? it is either called on U, or wrapped - cb: Box + 'a>, - }, - MatchDag { - cb: Box + 'a>, - }, // Patch { - // /// current dag we're selecting against - // /// if none, then load and store while patching - // current: &'a mut T, - // flush: bool, - // // op to perform on matching dags, allowing update-inplace - // // op: Box + 'a>, - // // op: PatchFn, - // } -} - -impl<'a, C, T> fmt::Debug for Callback<'a, C, T> -where - C: Context, - T: Representation, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::SelectNode { only_matched, .. } => f - .debug_struct("SelectionParams::SelectNode") - .field("source", &T::NAME) - .field("only_matched", only_matched) - .finish(), - Self::SelectDag { .. } => f - .debug_struct("SelectionParams::SelectDag") - .field("source", &T::NAME) - .finish(), - Self::MatchDag { .. } => f - .debug_struct("SelectionParams::MatchDag") - .field("source", &T::NAME) - .finish(), - // Self::Patch { current, flush, .. } => f - // .debug_struct("SelectionParams::Patch") - // .field("current", ¤t) - // .field("flush", &flush) - // .finish(), - } - } -} - -impl<'a, C, T> Default for Callback<'a, C, T> -where - C: Context, - T: Representation, -{ - /// Defaults to a no-op function for selecting nodes. - fn default() -> Self { - Self::SelectNode { - cb: Box::new(|_, _| Ok(())), - only_matched: true, - } - } -} - -// impl<'a, C, T, Cb> Into> for Cb -// where -// C: Context, -// T: Representation, -// Cb: SelectNodeOp + 'a, -// { -// fn into(self) -> SelectionCallback<'a, C, T> { -// Self::SelectNode { -// cb: Box::new(self), -// only_matched: false, -// } -// } -// } - -impl<'a, C, T> Callback<'a, C, T> -where - C: Context, - T: Representation, -{ - // #[inline] - // pub(crate) fn select_node(&self, node: SelectedNode) -> Result<(), Error> { - // self.sender()?.send_node(node) - // } - // - // #[inline] - // pub(crate) fn select_dag(&self, dag: SelectedDag) -> Result<(), Error> { - // self.sender()?.send_dag(dag) - // } - // - // #[inline] - // fn sender(&self) -> Result<&SelectionSender, Error> { - // let sender = match self { - // Self::Select { sender, .. } => sender.as_ref(), - // _ => None, - // }; - // - // sender.ok_or_else(|| Error::InvalidSelectionMode("`SelectionParams` missing a channel")) - // } - // - // /// transmutes the select params current source and target - // pub(crate) fn to_select<'b, V, W>(&mut self) -> SelectionParams<'b, C, V, W> - // where - // 'a: 'b, - // C: 'b, - // { - // match self { - // Self::Select { cb, mode, .. } => SelectionParams::Select { - // cb: cb.clone(), - // mode: *mode, - // _t: PhantomData, - // }, - // _ => unreachable!(), - // } - // } - - // /// - // pub const fn mode(&self) -> SelectionMode { - // match self { - // Self::SelectNode { .. } => SelectionMode::SelectNode, - // Self::SelectDag { .. } | Self::MatchDag { .. } => SelectionMode::SelectDag, - // // Self::Patch { .. } => SelectionMode::Patch, - // } - // } - - // /// - // pub const fn is_node(&self) -> bool { - // match self { - // Self::SelectNode { .. } => true, - // _ => false, - // } - // } - - // /// - // pub const fn is_dag(&self) -> bool { - // match self { - // Self::SelectDag { .. } | Self::MatchDag { .. } => true, - // _ => false, - // } - // } - - pub(super) fn select_node( - &mut self, - selected_node: NodeSelection, - ctx: &mut C, - ) -> Result<(), Error> { - match self { - Self::SelectNode { cb, only_matched } - if !*only_matched || selected_node.matched && *only_matched => - { - cb(selected_node, ctx) - } - Self::SelectNode { .. } => Ok(()), - _ => unreachable!(), - } - } - - pub(super) fn select_dag(&mut self, dag: DagSelection, ctx: &mut C) -> Result<(), Error> { - match self { - Self::SelectDag { cb } => cb(dag, ctx), - _ => unreachable!(), - } - } - - // // TODO: is this valid? - // pub(super) fn cast<'b, S>(self) -> SelectionCallback<'b, C, S> - // where - // 'a: 'b, - // C: 'b, - // S: Representation + 'static, - // T: From + 'static, - // { - // match self { - // Self::SelectNode { cb, only_matched } => { - // SelectionCallback::SelectNode { cb, only_matched } - // } - // Self::SelectDag { mut cb } => SelectionCallback::SelectDag { - // cb: Box::new(move |selection, ctx| { - // cb( - // DagSelection { - // dag: selection.dag.cast_between::()?, - // ..selection - // }, - // ctx, - // ) - // }), - // }, - // _ => unreachable!(), - // } - // } -} - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// -/// TODO: just rename this to state -#[derive(AsRef, AsMut, Debug, Default)] +#[derive(AsRef, AsMut, Clone, Debug, Default)] +#[doc(hidden)] pub(crate) struct State { // selector: Selector, // mode: SelectionMode, + pub(crate) current_block: Cid, #[as_ref] #[as_mut] pub(crate) path: PathBuf, @@ -516,7 +577,7 @@ impl State { pub(crate) fn descend( &mut self, // next_selector: Selector, - next_path: Field<'_>, + next_path: &Field<'_>, ) -> Result<(), Error> { if self.path_depth >= self.max_path_depth() { return Err(Error::SelectorDepth( @@ -532,9 +593,15 @@ impl State { } next_path.append_to_path(&mut self.path); - self.path_depth += 1; + self.path_depth = self + .path_depth + .checked_add(1) + .ok_or_else(|| Error::SelectorDepth("exceeds root path depth", self.path_depth))?; if T::IS_LINK { - self.link_depth += 1; + self.link_depth = self + .link_depth + .checked_sub(1) + .ok_or_else(|| Error::SelectorDepth("exceeds root link depth", self.link_depth))?; } Ok(()) diff --git a/tests/codec-fixtures.rs b/tests/codec-fixtures.rs index e118070..09cd900 100644 --- a/tests/codec-fixtures.rs +++ b/tests/codec-fixtures.rs @@ -229,11 +229,12 @@ impl Fixture { ) .expect("should not fail to add block"); - assert_eq!(&self.cid, &cid, "generated Cid should equal fixture Cid"); + assert_eq!(&self.cid, &cid, "generated Cid should match fixture Cid"); ctx } fn run(&mut self) { + // TODO: create copy types, test those too let did_run = match self.r#type() { FixtureType::Null => self.run_for::(), FixtureType::Bool => self.run_for::(), @@ -267,7 +268,7 @@ impl Fixture { .expect(&self.format_err::("should not fail to encode dag")); let new_cid = self .cid - .derive_new(block.as_ref()) + .derive_new(block.as_slice()) .expect(&"should not fail to generate a Cid for a block of bytes"); if self.codec.name() == "dag-json" { From 74776342ac06a8b8f210d0b187993660ad546c4d Mon Sep 17 00:00:00 2001 From: sunny-g Date: Sun, 9 Oct 2022 18:58:31 -0500 Subject: [PATCH 3/9] more minor updates --- Cargo.toml | 4 +- macros-internals/src/schema/mod.rs | 91 +++++++++++-------- src/cid.rs | 60 +++++------- src/data_model/link.rs | 141 +++++++---------------------- src/data_model/primitive.rs | 12 +-- src/lib.rs | 3 +- src/representation/mod.rs | 92 ------------------- src/selectors/mod.rs | 44 ++++++++- src/selectors/seed.rs | 51 ++++++----- 9 files changed, 182 insertions(+), 316 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 797071b..1614fd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ path = "src/lib.rs" [dependencies] # core -bytes = { version = "1.2", features = ["serde"] } +bytes = "1.2" cid = { version = "0.8", features = ["alloc", "serde-codec"] } # erased-serde = { version = "0.3", features = ["std"] } # ipfs = { git = "https://github.com/ipfs-rust/rust-ipfs", branch = "master", optional = true } @@ -34,8 +34,6 @@ serde_json = { version = "1.0", optional = true, features = ["float_roundtrip"] # misc anyhow = "1.0" -bitflags = "1.3" -cfg-if = "1" # const-str = "0.3" # const_format = "0.2" core2 = { version = "0.4", optional = true } diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index 381b16c..7fc56d3 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -193,14 +193,15 @@ pub mod kind { + BitAnd + BitAnd + BitAnd - + BitAnd, + + BitAnd + + BitAnd, { const KIND: SchemaKind; - const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); - const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); + // const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); + // const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); - const IS_SCHEMA: bool = SchemaKind::Schema.contains(Self::KIND) || Self::IS_TYPED_NUM; - const IS_TYPED_NUM: bool = SchemaKind::TypedNum.contains(Self::KIND) && !Self::IS_VARIOUS; + // const IS_SCHEMA: bool = SchemaKind::Schema.contains(Self::KIND) || Self::IS_TYPED_NUM; + // const IS_TYPED_NUM: bool = SchemaKind::TypedNum.contains(Self::KIND) && !Self::IS_VARIOUS; const IS_VARIOUS: bool = !is_unary::(); } @@ -215,7 +216,8 @@ pub mod kind { + BitAnd + BitAnd + BitAnd - + BitAnd, + + BitAnd + + BitAnd, // And: IsEqual, { const KIND: SchemaKind = SchemaKind::from_bits_truncate(T::U32); @@ -246,6 +248,7 @@ pub mod kind { pub struct SchemaKind: u32 { $(const $name = $b;)* + /// Marker flag for scalar data model kinds. const Scalar = Self::Null.bits | Self::Bool.bits | Self::Int.bits @@ -253,15 +256,23 @@ pub mod kind { | Self::String.bits | Self::Bytes.bits | Self::Link.bits; + + /// Marker flag for scalar data model kinds. const Recursive = Self::List.bits | Self::Map.bits; + + /// Marker flag for any and all valid data model kinds. const Any = Self::Scalar.bits | Self::Recursive.bits; + + /// Marker flag for any data model or schema kind. const Schema = Self::Any.bits | Self::Struct.bits | Self::Enum.bits | Self::Union.bits | Self::Copy.bits | Self::Advanced.bits; - const TypedNum = Self::Int8.bits + + /// Marker flag for lib-specific schema types for integers. + const TypedInt = Self::Int8.bits | Self::Int16.bits | Self::Int32.bits | Self::Int64.bits @@ -270,12 +281,15 @@ pub mod kind { | Self::Uint16.bits | Self::Uint32.bits | Self::Uint64.bits - | Self::Uint128.bits - | Self::Float32.bits - | Self::Float64.bits; + | Self::Uint128.bits; + + /// Marker flag for lib-specific schema types for + /// floating-point numbers. + const TypedFloat = Self::Float32.bits | Self::Float64.bits; } } + /// [`typenum`] types representing known [`SchemaKind`]s. pub mod type_kinds { $(pub type $name = tyuint!($b);)* @@ -283,10 +297,11 @@ pub mod kind { pub type Recursive = op!(List | Map); pub type Any = op!(Scalar | Recursive); pub type Schema = op!(Any | Struct | Enum | Union | Copy | Advanced); - pub type TypedNum = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128 | Float32 | Float64); + pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); + pub type TypedFloat = op!(Float32 | Float64); #[doc(hidden)] - pub type All = op!(Any | Schema | TypedNum); + pub type All = op!(Any | Schema | TypedInt | TypedFloat); } }; @@ -297,34 +312,34 @@ pub mod kind { } def_kind! { - Null = 0b0000_0000_0000_0001; - Bool = 0b0000_0000_0000_0010; - Int = 0b0000_0000_0000_0100; - Float = 0b0000_0000_0000_1000; - String = 0b0000_0000_0001_0000; - Bytes = 0b0000_0000_0010_0000; - List = 0b0000_0000_0100_0000; - Map = 0b0000_0000_1000_0000; - Link = 0b0000_0001_0000_0000; + Null = 0b0001; + Bool = 0b0010; + Int = 0b0100; + Float = 0b1000; + String = 0b0001_0000; + Bytes = 0b0010_0000; + List = 0b0100_0000; + Map = 0b1000_0000; + Link = 0b0001_0000_0000; // - Struct = 0b0000_0010_0000_0000; - Enum = 0b0000_0100_0000_0000; - Union = 0b0000_1000_0000_0000; - Copy = 0b0001_0000_0000_0000; - Advanced = 0b0010_0000_0000_0000; + Struct = 0b0010_0000_0000; + Enum = 0b0100_0000_0000; + Union = 0b1000_0000_0000; + Copy = 0b0001_0000_0000_0000; + Advanced = 0b0010_0000_0000_0000; // - Int8 = 0b0100_0000_0000_0000; - Int16 = 0b1000_0000_0000_0000; - Int32 = 0b0000_0001_0000_0000_0000_0000; - Int64 = 0b0000_0010_0000_0000_0000_0000; - Int128 = 0b0000_0100_0000_0000_0000_0000; - Uint8 = 0b0000_1000_0000_0000_0000_0000; - Uint16 = 0b0001_0000_0000_0000_0000_0000; - Uint32 = 0b0010_0000_0000_0000_0000_0000; - Uint64 = 0b0100_0000_0000_0000_0000_0000; - Uint128 = 0b1000_0000_0000_0000_0000_0000; - Float32 = 0b0000_0001_0000_0000_0000_0000_0000_0000; - Float64 = 0b0000_0010_0000_0000_0000_0000_0000_0000; + Int8 = 0b0100_0000_0000_0000; + Int16 = 0b1000_0000_0000_0000; + Int32 = 0b0001_0000_0000_0000_0000; + Int64 = 0b0010_0000_0000_0000_0000; + Int128 = 0b0100_0000_0000_0000_0000; + Uint8 = 0b1000_0000_0000_0000_0000; + Uint16 = 0b0001_0000_0000_0000_0000_0000; + Uint32 = 0b0010_0000_0000_0000_0000_0000; + Uint64 = 0b0100_0000_0000_0000_0000_0000; + Uint128 = 0b1000_0000_0000_0000_0000_0000; + Float32 = 0b0001_0000_0000_0000_0000_0000_0000; + Float64 = 0b0010_0000_0000_0000_0000_0000_0000; } impl SchemaKind { diff --git a/src/cid.rs b/src/cid.rs index f69b898..b9482c9 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -154,22 +154,16 @@ impl Representation for Cid { where S: Serializer, { - cfg_if::cfg_if! { - if #[cfg(feature = "dag-json")] { - if C == DagJson::CODE { - return DagJson::serialize_cid(self, serializer); - } - } + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::serialize_cid(self, serializer); } - cfg_if::cfg_if! { - if #[cfg(feature = "dag-cbor")] { - if C == DagCbor::CODE { - return DagCbor::serialize_cid(self, serializer); - } - } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::serialize_cid(self, serializer); } - Serialize::serialize(self, serializer) + Serialize::serialize(&self.inner, serializer) } /// @@ -183,11 +177,7 @@ impl Representation for Cid { type Value = Cid; #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "a Cid containing a multihash no longer than {} bytes", - Cid::SIZE - ) + write!(f, "a Cid containing a Multihash of max {} bytes", Cid::SIZE) } } impl<'de> IpldVisitorExt<'de> for CidVisitor { @@ -349,24 +339,24 @@ impl fmt::Display for Cid { } } -/// Defaults to the `Serialize` impl of `CidGeneric`. -impl Serialize for Cid { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.inner.serialize(serializer) - } -} +// /// Defaults to the `Serialize` impl of `CidGeneric`. +// impl Serialize for Cid { +// fn serialize(&self, serializer: S) -> Result +// where +// S: Serializer, +// { +// self.inner.serialize(serializer) +// } +// } -impl<'de> Deserialize<'de> for Cid { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Self::from(DefaultCid::deserialize(deserializer)?)) - } -} +// impl<'de> Deserialize<'de> for Cid { +// fn deserialize(deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// Ok(Self::from(DefaultCid::deserialize(deserializer)?)) +// } +// } /// A generator of [`Cid`]s. #[derive(Debug)] diff --git a/src/data_model/link.rs b/src/data_model/link.rs index 5109a20..3435596 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -19,7 +19,14 @@ pub enum Link { /// #[from(ignore)] - Inner { cid: Cid, t: T, dirty: bool }, + Inner { + /// + cid: Cid, + /// + t: T, + /// + dirty: bool, + }, } impl Link { @@ -106,9 +113,7 @@ impl Representation for Link { where D: Deserializer<'de>, { - Ok(Self::Cid(Representation::deserialize::( - deserializer, - )?)) + Ok(Self::Cid(Cid::deserialize::(deserializer)?)) } } @@ -133,33 +138,6 @@ impl_selector_seed_serde! { @codec_seed_visitor_ext } }} -// impl_selector_seed_serde! { @selector_seed_codec_deseed -// { T: Select + 'static } { } Link -// { -// #[inline] -// fn deserialize(self, deserializer: D) -> Result<(), D::Error> -// where -// D: Deserializer<'de>, -// { -// cfg_if::cfg_if! { -// if #[cfg(feature = "dag-json")] { -// if _C == DagJson::CODE { -// return DagJson::deserialize_cid(deserializer, self); -// } -// } -// } -// cfg_if::cfg_if!{ -// if #[cfg(feature = "dag-cbor")] { -// if _C == DagCbor::CODE { -// return DagCbor::deserialize_cid(deserializer, self); -// } -// } -// } -// -// Deserialize::deserialize(deserializer) -// } -// }} - impl_selector_seed_serde! { @selector_seed_select { T: Select + 'static } { } Link } @@ -185,95 +163,44 @@ where } } -// impl<'a, 'de, C, T> Visitor<'de> for ContextSeed<'a, C, Link> -// where -// C: Context, -// T: Representation + 'static, -// for<'b> ContextSeed<'b, C, T>: DeserializeSeed<'de, Value = ()>, -// { -// type Value = (); -// -// #[inline] -// fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// write!(formatter, "{}", Link::::NAME) -// } -// } - -// impl<'a, 'de, C, T> IpldVisitorExt<'de> for ContextSeed<'a, C, Link> -// where -// C: Context, -// T: Representation + 'static, -// for<'b> ContextSeed<'b, C, T>: DeserializeSeed<'de, Value = ()>, -// { -// // TODO: -// } +impl Into for Link { + fn into(self) -> Cid { + match self { + Self::Cid(cid) => cid, + Self::Inner { cid, .. } => cid, + } + } +} -// impl<'a, 'de, C, T> DeserializeSeed<'de> for ContextSeed<'a, C, Link> +// // TODO: dirty links? +// impl Serialize for Link // where -// C: Context, -// T: Representation + 'static, -// for<'b> ContextSeed<'b, C, T>: DeserializeSeed<'de, Value = ()>, +// T: Representation, // { -// type Value = (); -// -// #[inline] -// fn deserialize(self, deserializer: D) -> Result +// fn serialize(&self, serializer: S) -> Result // where -// D: Deserializer<'de>, +// S: Serializer, // { -// deserializer.deserialize_link(self) +// // ::serialize_link(serializer, self.cid()) +// // (&mut &mut &mut Encoder(serializer)).serialize_link(self.cid()) +// // self.cid().serialize(serializer) +// Serialize::serialize(self.cid(), serializer) // } // } -// impl<'a, 'de, C, T> Select for Link +// impl<'de, T> Deserialize<'de> for Link // where -// C: Context, -// T: Representation + Send + Sync + 'static, -// // ContextSeed<'a, C, T>: DeserializeSeed<'de, Value = ()>, +// T: Representation, // { -// fn select(params: SelectionParams<'_, C, Self>, ctx: &mut C) -> Result<(), Error> { -// unimplemented!() +// fn deserialize(deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// // Ok(Self::Cid(Cid::deserialize(deserializer)?)) +// Ok(Self::Cid(Deserialize::deserialize(deserializer)?)) // } // } -impl Into for Link { - fn into(self) -> Cid { - match self { - Self::Cid(cid) => cid, - Self::Inner { cid, .. } => cid, - } - } -} - -// TODO: dirty links? -impl Serialize for Link -where - T: Representation, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - // ::serialize_link(serializer, self.cid()) - // (&mut &mut &mut Encoder(serializer)).serialize_link(self.cid()) - // self.cid().serialize(serializer) - Serialize::serialize(self.cid(), serializer) - } -} - -impl<'de, T> Deserialize<'de> for Link -where - T: Representation, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // Ok(Self::Cid(Cid::deserialize(deserializer)?)) - Ok(Self::Cid(Deserialize::deserialize(deserializer)?)) - } -} - //////////////////////////////////////////////////////////////////////////////// // additional implementations //////////////////////////////////////////////////////////////////////////////// diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index d0fe89f..e234996 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -155,7 +155,7 @@ mod bool { // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // write!(f, "{}, a boolean type", Bool::NAME) // } - + // // #[inline] // fn visit_bool(self, v : bool) -> Result // where @@ -169,16 +169,6 @@ mod bool { // } // }} - // impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Bool { - // #[inline] - // fn deserialize(self, deserializer: D) -> Result - // where - // D: Deserializer<'de>, - // { - // deserializer.deserialize_bool(self) - // } - // }} - impl_selector_seed_serde! { @selector_seed_select {} {} Bool } } diff --git a/src/lib.rs b/src/lib.rs index c881600..617113d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,7 +58,7 @@ mod specs { // selectors pub use crate::selectors::{Context, Params, Select, Selector}; - pub use ipld_macros::selector; + // pub use ipld_macros::selector; } /// All the exports and re-exports necessary for using `ipld`. @@ -88,7 +88,6 @@ pub mod dev { pub mod macros { pub use crate::impl_selector_seed_serde; // pub use const_format::*; - pub use cfg_if::cfg_if; pub use ipld_macros_internals::*; } diff --git a/src/representation/mod.rs b/src/representation/mod.rs index 4e93cd1..b7fea5f 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -21,98 +21,6 @@ pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKin #[doc(hidden)] pub use strategies::*; -#[cfg(feature = "old")] -mod kind { - // use bitflags::bitflags; - - // bitflags! { - // /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. - // /// - // pub struct Kind: u16 { - // // data model kinds - - // /// - // const Null = 0b0000_0000_0000_0001; - // /// - // const Bool = 0b0000_0000_0000_0010; - // /// - // const Int = 0b0000_0000_0000_0100; - // /// - // const Float = 0b0000_0000_0000_1000; - // /// - // const String = 0b0000_0000_0001_0000; - // /// - // const Bytes = 0b0000_0000_0010_0000; - // /// - // const List = 0b0000_0000_0100_0000; - // /// - // const Map = 0b0000_0000_1000_0000; - // /// - // const Link = 0b0000_0001_0000_0000; - - // // schema kinds - - // /// - // const Struct = 0b0000_0010_0000_0000; - // /// - // const Enum = 0b0000_0100_0000_0000; - // /// - // const Union = 0b0000_1000_0000_0000; - - // // any - - // /// - // const Any = Self::Null.bits - // | Self::Bool.bits - // | Self::Int.bits - // | Self::Float.bits - // | Self::String.bits - // | Self::Bytes.bits - // | Self::List.bits - // | Self::Map.bits - // | Self::Link.bits; - // } - // } - - // impl Kind { - // /// Const function for determining equality between [`Kind`]s. - // pub const fn eq(&self, other: &Self) -> bool { - // match (*self, *other) { - // (Self::Null, Self::Null) - // | (Self::Bool, Self::Bool) - // | (Self::Int, Self::Int) - // | (Self::Float, Self::Float) - // | (Self::String, Self::String) - // | (Self::Bytes, Self::Bytes) - // | (Self::List, Self::List) - // | (Self::Map, Self::Map) - // | (Self::Link, Self::Link) - // | (Self::Struct, Self::Struct) - // | (Self::Enum, Self::Enum) - // | (Self::Union, Self::Union) => true, - // _ => false, - // } - // } - // } - - // /// - // #[derive(Copy, Clone, Debug)] - // pub enum SchemaKind { - // Null = Kind::Null.bits as isize, - // Bool = Kind::Bool.bits as isize, - // Int = Kind::Int.bits as isize, - // Float = Kind::Float.bits as isize, - // String = Kind::String.bits as isize, - // Bytes = Kind::Bytes.bits as isize, - // List = Kind::List.bits as isize, - // Map = Kind::Map.bits as isize, - // Link = Kind::Link.bits as isize, - // Struct = Kind::Struct.bits as isize, - // Enum = Kind::Enum.bits as isize, - // Union = Kind::Union.bits as isize, - // } -} - // /// // #[derive(Debug, Eq, Hash, PartialEq)] // pub struct Field { diff --git a/src/selectors/mod.rs b/src/selectors/mod.rs index e8ef162..615ef0e 100644 --- a/src/selectors/mod.rs +++ b/src/selectors/mod.rs @@ -495,6 +495,41 @@ mod selection { // } // } + // schema! { + // #[ipld_attr(internal)] + // type List = Null + // } + + // schema! { + // #[ipld_attr(internal)] + // type Map = Null + // } + + // schema! { + // #[ipld_attr(internal)] + // pub type SelectedNode2 union { + // | Null "null" + // | Bool "bool" + // | Int8 "int8" + // | Int16 "int16" + // | Int32 "int32" + // | Int64 "int64" + // | Int128 "int" + // | Uint8 "uint8" + // | Uint16 "uint16" + // | Uint32 "uint32" + // | Uint64 "uint64" + // | Uint128 "uint128" + // | Float32 "float32" + // | Float64 "float64" + // | String "string" + // | Bytes "bytes" + // | List "list" + // | Map "map" + // | Link "link" + // } representation keyed + // } + /// #[derive(Clone, Debug, From, Deserialize, Serialize)] // #[from(forward)] @@ -576,6 +611,7 @@ mod selection { Map, /// + #[serde(skip)] // TODO #[serde(rename = "link")] Link(Cid), } @@ -625,14 +661,14 @@ mod selection { } // TODO: Vec? - impl From> for SelectedNode { - fn from(_: List) -> Self { + impl From> for SelectedNode { + fn from(_: crate::dev::List) -> Self { Self::List } } - impl From> for SelectedNode { - fn from(_: Map) -> Self { + impl From> for SelectedNode { + fn from(_: crate::dev::Map) -> Self { Self::Map } } diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index cbcd00a..170ee6f 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -54,9 +54,9 @@ pub type EmptySeed = SelectorSeed<'static, (), T>; /// ? 3. Link needs to take some seed, uncode it, then use inner to call SelectorSeed::select for the next block #[doc(hidden)] #[derive(Debug)] -pub struct CodecSeed(pub(crate) S, PhantomData); +pub struct CodecSeed(pub(crate) S, PhantomData); -impl CodecSeed { +impl CodecSeed { // pub const RK: u32 = RK; // pub const fn is_select() -> bool { // (!RK) @@ -72,15 +72,13 @@ impl CodecSeed { where T: Representation, { - if T::SCHEMA_KIND.bits() == Kind::Int.bits() { + if Kind::TypedInt.contains(T::SCHEMA_KIND) { Int::SCHEMA_KIND + } else if Kind::TypedFloat.contains(T::SCHEMA_KIND) { + Float::SCHEMA_KIND } else { T::SCHEMA_KIND } - // match (T::SCHEMA_KIND, T::REPR_KIND) { - // Kind::Int => Int::SCHEMA_KIND, - // kinds => kinds, - // } } } @@ -88,11 +86,12 @@ impl CodecSeed { /// Doing this allows us to focus selection implementations on what to do when /// visiting a particular representation. /// -impl<'a, 'de, const C: u64, const RK: u32, S, T> DeserializeSeed<'de> for CodecSeed +impl<'a, 'de, const C: u64, S, T> DeserializeSeed<'de> for CodecSeed where Self: Visitor<'de> + IpldVisitorExt<'de>, // Ctx: Context, // T: Select, + S: SeedType, T: Representation, { type Value = >::Value; @@ -156,7 +155,18 @@ where } } -impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed, T> { +#[doc(hidden)] +pub trait SeedType { + const CAN_SELECT: bool; +} +impl SeedType for PhantomData { + const CAN_SELECT: bool = false; +} +impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { + const CAN_SELECT: bool = true; +} + +impl<'a, const C: u64, Ctx, T> CodecSeed, T> { // /// // #[inline] // pub(crate) fn from_parts( @@ -204,7 +214,7 @@ impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed CodecSeed> { +// impl<'a, const C: u64, Ctx, T> CodecSeed> { // fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { // Self(inner) // } @@ -237,10 +247,10 @@ impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed = - CodecSeed, T>; +// /// +// #[doc(hidden)] +// pub type CodedSelectorSeed<'a, const C: u64, Ctx, T> = +// CodecSeed, T>; // /// Replacement trait for [`serde::de::DeserializeSeed`], that allows us to // /// switch deserialization behaviour based on the current block's [`Codec`]. @@ -340,13 +350,6 @@ where // } // } - // pub fn empty() -> EmptySeed { - // static DEFAULT_SELECTOR: Selector = Selector::DEFAULT; - // SelectorSeed { - // selector: DEFAULT_SELECTOR, - // } - // } - /// #[inline] pub const fn mode(&self) -> SelectionMode { @@ -612,7 +615,7 @@ macro_rules! impl_selector_seed_serde { const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> Visitor<'de> for - CodecSeed<_C, _RK, + CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, $ty $(<$($ty_generics),+>)? > @@ -659,7 +662,7 @@ macro_rules! impl_selector_seed_serde { const _RK: u32 = Kind::$rk.bits(); impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> Visitor<'de> for - CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> + CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty> where // T: Representation // T: Select, @@ -691,7 +694,7 @@ macro_rules! impl_selector_seed_serde { const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> IpldVisitorExt<'de> for - CodecSeed<_C, _RK, + CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, $ty $(<$($ty_generics),+>)? > From 6c6c16e001f04a303fd4617f83251bdde7f9433e Mon Sep 17 00:00:00 2001 From: sunny-g Date: Mon, 10 Oct 2022 11:35:16 -0500 Subject: [PATCH 4/9] use typenum as ReprKind for blanket Visitor impls for reprs --- macros-internals/src/lib.rs | 12 +- macros-internals/src/schema/expand.rs | 221 +----- macros-internals/src/schema/mod.rs | 108 +-- macros-internals/src/schema/struct/expand.rs | 5 +- macros-internals/src/schema/union/expand.rs | 7 +- .../src/schema/union/expand_kinded.rs | 65 +- src/cid.rs | 2 + src/data_model/any.rs | 16 +- src/data_model/compat.rs | 15 +- src/data_model/link.rs | 41 +- src/data_model/list.rs | 111 +-- src/data_model/map.rs | 105 +-- src/data_model/primitive.rs | 309 +++++---- src/lib.rs | 8 +- src/representation/mod.rs | 25 +- src/selectors/seed.rs | 630 ++++-------------- 16 files changed, 606 insertions(+), 1074 deletions(-) diff --git a/macros-internals/src/lib.rs b/macros-internals/src/lib.rs index b57a5b2..1bb505f 100644 --- a/macros-internals/src/lib.rs +++ b/macros-internals/src/lib.rs @@ -1,11 +1,3 @@ -pub extern crate derive_more; -#[macro_use] -pub extern crate typenum; -#[macro_use] -pub extern crate typenum_macro; -// #[macro_use] -// pub extern crate static_assertions; - pub mod common; pub mod schema; pub mod selector; @@ -21,4 +13,8 @@ pub mod dev { pub use crate::schema::{expand::*, parse::*, *}; pub use crate::selector::*; pub use crate::*; + + pub use derive_more; + pub use typenum; + pub use typenum_macro; } diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index 7575a58..66deedb 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -305,9 +305,11 @@ macro_rules! derive_newtype { $crate::dev::impl_repr( $meta, quote::quote! { + type ReprKind = <#$inner_ty as Representation>::ReprKind; + const DATA_MODEL_KIND: Kind = <#$inner_ty>::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = <#$inner_ty>::SCHEMA_KIND; - const REPR_KIND: Kind = <#$inner_ty>::REPR_KIND; + // const REPR_KIND: Kind = <#$inner_ty>::REPR_KIND; const IS_LINK: bool = <#$inner_ty>::IS_LINK; const HAS_LINKS: bool = <#$inner_ty>::HAS_LINKS; @@ -337,8 +339,8 @@ macro_rules! derive_newtype { let lib = &$meta.lib; let name = &$meta.name; quote::quote! { - #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty - } + // #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty + // } #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_select {} {} #name } @@ -378,115 +380,6 @@ macro_rules! derive_newtype { }}; } -// /// -// pub(crate) fn impl_serialize(meta: &SchemaMeta, body: TokenStream) -> TokenStream { -// let name = &meta.name; -// quote! { -// #[automatically_derived] -// impl Serialize for #name { -// fn serialize(&self, serializer: S) -> Result -// where -// S: Serializer, -// { -// #body -// } -// } -// } -// } -// -// // TODO: for each visitor method, incorporate try_from... -// // - define TryFromType -// // - `impl Visitor for ReprVisitor` -// // - method bodies expanded (should only refer to Self::Value, not #name) -// // - in `impl Visitor for ReprVisitor`, replacing method bodies -// // - call each equiv method on > -// // - handle result with try_from().map_err() call -// pub(crate) fn impl_visitor( -// meta: &SchemaMeta, -// expecting: &'static str, -// body: TokenStream, -// ) -> (Ident, TokenStream) { -// let name = &meta.name; -// let visitor = meta.visitor_name(); -// -// // TODO? if try_from, add: -// // - def ReprVisitor -// // - def TryFromType -// // - `impl Visitor for ReprVisitor` -// // - body -// // - `impl Visitor for ReprVisitor` -// // - body replaced w/ try_from call -// // TODO? else: -// // - def ReprVisitor -// // - `impl Visitor for ReprVisitor` -// // -// // body = if let Some(try_from_name) = &meta.try_from { -// // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); -// // let methods = expand_try_from_visitor_methods(body, try_from_ident); -// // quote! { -// // use ::std::convert::TryFrom; -// // // let t = #try_from_ident::deserialize(deserializer)?; -// // // Ok(#name::try_from(t).map_err(D::Error::custom)?) -// // } -// // } else { -// // quote! { -// // type Value = #name; -// // #body -// // } -// // }; -// -// let visitor_def = quote! { -// struct #visitor; -// #[automatically_derived] -// impl<'de> Visitor<'de> for #visitor { -// type Value = #name; -// fn expecting(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { -// fmt.write_str(#expecting) -// } -// #body -// } -// }; -// (visitor, visitor_def) -// } -// -// pub(crate) fn impl_visitor_ext(meta: &SchemaMeta, body: Option) -> TokenStream { -// let visitor = meta.visitor_name(); -// quote! { -// #[automatically_derived] -// impl<'de> IpldVisitorExt<'de> for #visitor { -// #body -// } -// } -// } -// -// pub(crate) fn impl_deserialize(meta: &SchemaMeta, mut body: TokenStream) -> TokenStream { -// let name = &meta.name; -// // let lib = &meta.ipld_schema_lib; -// // body = if let Some(try_from_name) = &meta.try_from { -// // let try_from_ident = Ident::new(&try_from_name.value(), Span::call_site()); -// // // let methods = expand_try_from_visitor_methods(body, try_from_ident); -// // quote! { -// // use ::std::convert::TryFrom; -// // let t = #try_from_ident::deserialize(deserializer)?; -// // Ok(#name::try_from(t).map_err(D::Error::custom)?) -// // } -// // } else { -// // body -// // }; -// -// quote! { -// #[automatically_derived] -// impl<'de> Deserialize<'de> for #name { -// fn deserialize(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// #body -// } -// } -// } -// } - pub(crate) fn impl_repr(meta: &SchemaMeta, consts_and_simple_methods: TokenStream) -> TokenStream { let lib = &meta.lib; let name = &meta.name; @@ -503,110 +396,6 @@ pub(crate) fn impl_repr(meta: &SchemaMeta, consts_and_simple_methods: TokenStrea } } -/* -pub(crate) fn impl_context_seed_visitor( - meta: &SchemaMeta, - expecting: &'static str, - mut body: TokenStream, -) -> TokenStream { - let name = &meta.name; - let generics = meta.generics_tokens(); - - quote! { - #[automatically_derived] - impl<'a, 'de, #generics> Visitor<'de> for ContextSeed<'a, C, #name> - where - C: Context - U: Representation, - { - type Value = (); - - fn expecting(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str(#expecting) - } - - #body - } - } -} - -pub(crate) fn impl_context_seed_deseed(meta: &SchemaMeta, mut body: TokenStream) -> TokenStream { - let name = &meta.name; - let generics = meta.generics_tokens(); - - quote! { - #[automatically_derived] - impl<'a, 'de, #generics> DeserializeSeed<'de> for ContextSeed<'a, C, #name> - where - C: Context - U: Representation, - ContextSeed<'a, C, #name>: Visitor<'de, Value = ()>, - { - type Value = (); - - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - #body - } - } - } -} - -pub(crate) fn impl_select( - meta: &SchemaMeta, - // match_impl: TokenStream, - select_impl: TokenStream, -) -> TokenStream { - let name = &meta.name; - let generics = meta.generics_tokens(); - quote! { - #[automatically_derived] - impl Select for #name { - // fn r#match( - // // selector: &Selector, - // // state: &mut SelectorState, - // // params: SelectionParams<'_, Ctx, Self>, - // // ctx: &mut Ctx, - // seed: ContextSeed<'_, Ctx, Self>, - // ) -> Result, Error> { - // #match_impl - // } - - /// Produces a stream of [`Selection`]s. - fn select(params: SelectionParams<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { - #select_impl - } - } - } -} - - */ - -// -// pub(crate) fn impl_de_seed_for( -// meta: &SchemaMeta, -// selector: Ident, -// body: TokenStream, -// ) -> TokenStream { -// let name = &meta.name; -// // let lib = &meta.ipld_schema_lib; -// quote! { -// #[automatically_derived] -// impl<'de> DeserializeSeed<'de> for SelectorSeed<'de, #selector, #name> { -// type Value = #name; -// fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// #body -// } -// } -// } -// } - // pub(crate) fn impl_primtive_de_seed(meta: &SchemaMeta) -> TokenStream { // let name = &meta.name; // let lib = &meta.ipld_schema_lib; diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index 7fc56d3..62b8d92 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -67,14 +67,6 @@ impl SchemaMeta { quote!(#path) } - /// Returns the `Ident` of the `Visitor` generated for this type. - pub fn visitor_name(&self) -> Ident { - Ident::new( - &format!("_{}Visitor", &self.name.to_string()), - Span::call_site(), - ) - } - pub fn generics_tokens(&self) -> TokenStream { self.generics .as_ref() @@ -136,65 +128,30 @@ impl ReprDefinition { } } +// #[macro_use] pub mod kind { - use super::*; - use std::ops::BitAnd; + // use super::*; + use std::ops::{BitAnd, BitOr}; use type_kinds::*; use typenum::*; - use typenum_macro::tyuint; - - // /// - // #[derive(Debug, PartialEq, Eq, Hash)] - // pub enum SchemaKind { - // Null, - // Bool, - // Int, // same as Int128 - // Int8, - // Int16, - // Int32, - // Int64, - // Int128, - // Uint8, - // Uint16, - // Uint32, - // Uint64, - // Uint128, - // Float, // same as Float64 - // Float32, - // Float64, - // Bytes, - // String, - // List, - // Map, - // Link, - // Struct, - // Enum, - // Union, - // Copy, - // } - - // /// - // pub trait TypedKind { - // const KIND: SchemaKind = SchemaKind::from::(); - // const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); - // const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); - // const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); - // const IS_SCHEMA: bool = SchemaKind::Any.contains(Self::KIND); - // } + use typenum_macro::*; + /// + /// TODO: BitAnd/BitOr dont work without fully-qualified syntax pub trait TypedKind where Self: NonZero + Unsigned - + IsLessOrEqual // replace with And: IsEqual, - + BitAnd - + BitAnd + // + IsLessOrEqual // TODO: replace with And: IsEqual, + // + BitAnd + // + BitAnd + BitAnd + BitAnd + BitAnd + BitAnd - + BitAnd - + BitAnd, + // + BitAnd + // + BitAnd + + BitOr, { const KIND: SchemaKind; // const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); @@ -209,15 +166,16 @@ pub mod kind { where T: NonZero + Unsigned - + IsLessOrEqual - + BitAnd - + BitAnd + // + IsLessOrEqual + // + BitAnd + // + BitAnd + BitAnd + BitAnd + BitAnd + BitAnd - + BitAnd - + BitAnd, + // + BitAnd + // + BitAnd + + BitOr, // And: IsEqual, { const KIND: SchemaKind = SchemaKind::from_bits_truncate(T::U32); @@ -237,16 +195,16 @@ pub mod kind { // { // } - macro_rules! def_kind { - ($( - $name:ident = $b:expr; - )*) => { + macro_rules! def_kind { ( + $($name:ident = $b:expr;)*) => { bitflags::bitflags! { /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. /// #[repr(transparent)] pub struct SchemaKind: u32 { - $(const $name = $b;)* + $( + const $name = $b; + )* /// Marker flag for scalar data model kinds. const Scalar = Self::Null.bits @@ -290,25 +248,29 @@ pub mod kind { } /// [`typenum`] types representing known [`SchemaKind`]s. + // #[macro_use] pub mod type_kinds { + use super::*; + // use typenum; + // use $crate::dev::typenum_macro; + $(pub type $name = tyuint!($b);)* + // pub type Optional = typenum::op!(Null | T); + pub type Scalar = op!(Null | Bool | Int | Float | String | Bytes | Link); pub type Recursive = op!(List | Map); pub type Any = op!(Scalar | Recursive); pub type Schema = op!(Any | Struct | Enum | Union | Copy | Advanced); - pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); - pub type TypedFloat = op!(Float32 | Float64); + // pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); + // pub type TypedFloat = op!(Float32 | Float64); + // #[doc(hidden)] + // pub type All = op!(Any | Schema | TypedInt | TypedFloat); #[doc(hidden)] - pub type All = op!(Any | Schema | TypedInt | TypedFloat); + pub type Empty = U0; } - }; - // (@custom $name:ident $($kind:ident,)*) => { - // pub type $name = $crate::typenum::op!($($kind | )*); - // impl Sealed for $name {} - // } } def_kind! { diff --git a/macros-internals/src/schema/struct/expand.rs b/macros-internals/src/schema/struct/expand.rs index 477fbeb..fbc70a9 100644 --- a/macros-internals/src/schema/struct/expand.rs +++ b/macros-internals/src/schema/struct/expand.rs @@ -132,9 +132,12 @@ pub(super) fn impl_repr<'a, D: Deref>( let repr_body = expand::impl_repr( meta, quote! { + type ReprKind = type_kinds::#repr_kind; + + const SCHEMA: &'static str = ""; const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Struct; - const REPR_KIND: Kind = Kind::#repr_kind; + // const REPR_KIND: Kind = Kind::#repr_kind; // const FIELDS: Fields = Fields::Struct(&[#(#fields,)*]); }, ); diff --git a/macros-internals/src/schema/union/expand.rs b/macros-internals/src/schema/union/expand.rs index 2552720..aad6efe 100644 --- a/macros-internals/src/schema/union/expand.rs +++ b/macros-internals/src/schema/union/expand.rs @@ -76,9 +76,12 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { expand::impl_repr( meta, quote! { - const DATA_MODEL_KIND: Kind = unimplemented!(); + type ReprKind = type_kinds::Map; + + const SCHEMA: &'static str = ""; + const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Union; - const REPR_KIND: Kind = unimplemented!(); + // const REPR_KIND: Kind = unimplemented!(); // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); #[inline] diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index 0537755..1fee06f 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -39,9 +39,12 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { expand::impl_repr( meta, quote! { + type ReprKind = #repr_kind; + + const SCHEMA: &'static str = ""; const DATA_MODEL_KIND: Kind = #dm_kind; const SCHEMA_KIND: Kind = Kind::Union; - const REPR_KIND: Kind = #repr_kind; + // const REPR_KIND: Kind = #repr_kind; // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); #[inline] @@ -121,24 +124,24 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { // } // } - #lib::dev::macros::impl_selector_seed_serde! { - @codec_seed_visitor {} {} #name - { - #[inline] - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "A `{}`", <#name as Representation>::NAME) - } + // #lib::dev::macros::impl_selector_seed_serde! { + // @codec_seed_visitor {} {} #name + // { + // #[inline] + // fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // write!(f, "A `{}`", <#name as Representation>::NAME) + // } - #(#non_link_visitors)* - }} - #lib::dev::macros::impl_selector_seed_serde! { - @codec_seed_visitor_ext {} {} #name - { - #(#link_visitors)* - }} - #lib::dev::macros::impl_selector_seed_serde! { - @selector_seed_codec_deseed @any {} {} #name - } + // #(#non_link_visitors)* + // }} + // #lib::dev::macros::impl_selector_seed_serde! { + // @codec_seed_visitor_ext {} {} #name + // { + // #(#link_visitors)* + // }} + // #lib::dev::macros::impl_selector_seed_serde! { + // @selector_seed_codec_deseed @any {} {} #name + // } #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_select {} {} #name } @@ -158,10 +161,13 @@ impl KindedUnionReprDefinition { } fn repr_kind(&self) -> TokenStream { - self.iter() - .map(|f| f.ty(false)) - .map(|ty| quote!(<#ty as Representation>::REPR_KIND)) - .fold(quote!(Kind::empty()), |ts, kind| quote!(#ts.union(#kind))) + self + .iter() + .map(|f| f.repr_kind()) + .fold( + quote!(type_kinds::Empty), + |ts, kind| quote!(typenum::Or<#ts, #kind>), + ) } } @@ -187,6 +193,21 @@ impl UnionKindedField { } } + fn repr_kind(&self) -> TokenStream { + match self.key { + SchemaKind::Null => quote!(type_kinds::Null), + SchemaKind::Bool => quote!(type_kinds::Bool), + SchemaKind::Int => quote!(type_kinds::Int), + SchemaKind::Float => quote!(type_kinds::Float), + SchemaKind::String => quote!(type_kinds::String), + SchemaKind::Bytes => quote!(type_kinds::Bytes), + SchemaKind::List => quote!(type_kinds::List), + SchemaKind::Map => quote!(type_kinds::Map), + SchemaKind::Link => quote!(type_kinds::Link), + _ => unreachable!(), + } + } + fn ty(&self, with_wrapper: bool) -> TokenStream { let generics = &self.generics; let ty = match self.key { diff --git a/src/cid.rs b/src/cid.rs index b9482c9..b8c8220 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -144,6 +144,8 @@ impl Cid { } impl Representation for Cid { + type ReprKind = type_kinds::Link; + const NAME: &'static str = "Cid"; const SCHEMA: &'static str = "type Cid &Any"; const DATA_MODEL_KIND: Kind = Kind::Link; diff --git a/src/data_model/any.rs b/src/data_model/any.rs index 34d28fe..e3423aa 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -1,6 +1,9 @@ use crate::dev::*; -use macros::derive_more::{From, IsVariant, TryInto, Unwrap}; -use maybestd::rc::Rc; +use macros::{ + derive_more::{From, IsVariant, TryInto, Unwrap}, + impl_selector_seed_serde, +}; +use maybestd::{fmt, rc::Rc}; use std::path::Path; // /// @@ -42,6 +45,15 @@ schema! { } representation kinded; } +// impl_selector_seed_serde! { @codec_seed_visitor_rk Any +// {} { T: 'static } +// { +// #[inline] +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// write!(f, "{}, a boolean type", Bool::NAME) +// } +// }} + /// TODO: convert these to a Node trait, that all types implement impl Any { /// LookupByString looks up a child object in this node and returns it. diff --git a/src/data_model/compat.rs b/src/data_model/compat.rs index 58a1907..f03950a 100644 --- a/src/data_model/compat.rs +++ b/src/data_model/compat.rs @@ -5,11 +5,13 @@ mod ignored { use super::*; impl Representation for IgnoredAny { + type ReprKind = type_kinds::Any; + const NAME: &'static str = "IgnoredAny"; const SCHEMA: &'static str = "type IgnoredAny = Any"; const DATA_MODEL_KIND: Kind = Kind::Null; const SCHEMA_KIND: Kind = Kind::Any; - const REPR_KIND: Kind = Kind::Any; + // const REPR_KIND: Kind = Kind::Any; const __IGNORED: bool = true; #[doc(hidden)] @@ -37,11 +39,16 @@ mod option { where T: Representation, { + type ReprKind = T::ReprKind; + // type ReprKind = type_kinds::Optional<::ReprKind>; + // type ReprKind = typenum::op!(type_kinds::Null | T::ReprKind); + // type ReprKind = typenum::Or; + const NAME: &'static str = concat!("Optional", stringify!(T::NAME)); const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - const REPR_KIND: Kind = T::REPR_KIND; + // const REPR_KIND: Kind = T::REPR_KIND; const IS_LINK: bool = T::IS_LINK; const HAS_LINKS: bool = T::HAS_LINKS; @@ -133,11 +140,13 @@ mod wrapper { where T: Representation, { + type ReprKind = ::ReprKind; + const NAME: &'static str = T::NAME; const SCHEMA: &'static str = T::SCHEMA; const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - const REPR_KIND: Kind = T::REPR_KIND; + // const REPR_KIND: Kind = T::REPR_KIND; const IS_LINK: bool = T::IS_LINK; const HAS_LINKS: bool = T::HAS_LINKS; diff --git a/src/data_model/link.rs b/src/data_model/link.rs index 3435596..8790cd3 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -74,6 +74,8 @@ impl Link { } impl Representation for Link { + type ReprKind = type_kinds::Link; + const NAME: &'static str = "Link"; const SCHEMA: &'static str = concat!("type Link &", stringify!(T::NAME)); const DATA_MODEL_KIND: Kind = Kind::Link; @@ -117,24 +119,33 @@ impl Representation for Link { } } -impl_selector_seed_serde! { @codec_seed_visitor - { T: Select + 'static } { } Link -{ - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A link to a `{}`", T::NAME) - } -}} +// impl_selector_seed_serde! { @codec_seed_visitor +// { T: Select + 'static } { } Link +// { +// #[inline] +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// write!(f, "A link to a `{}`", T::NAME) +// } +// }} -impl_selector_seed_serde! { @codec_seed_visitor_ext - { T: Select + 'static } { } Link +// impl_selector_seed_serde! { @codec_seed_visitor_ext +// { T: Select + 'static } { } Link +// { +// #[inline] +// fn visit_cid(self, cid: Cid) -> Result +// where +// E: de::Error, +// { +// self.0.select_link::<_C>(cid).map_err(E::custom) +// } +// }} + +impl_selector_seed_serde! { @codec_seed_visitor_rk Link + {} { T: 'static } { #[inline] - fn visit_cid(self, cid: Cid) -> Result - where - E: de::Error, - { - self.0.select_link::<_C>(cid).map_err(E::custom) + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}, a boolean type", Bool::NAME) } }} diff --git a/src/data_model/list.rs b/src/data_model/list.rs index ad9526f..2788a34 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -14,11 +14,13 @@ pub use iterators::*; pub type List = Vec; impl Representation for List { + type ReprKind = type_kinds::List; + const NAME: &'static str = "List"; const SCHEMA: &'static str = concat!("type List [", stringify!(T::NAME), "]"); const DATA_MODEL_KIND: Kind = Kind::List; const SCHEMA_KIND: Kind = Kind::List; - const REPR_KIND: Kind = Kind::List; + // const REPR_KIND: Kind = Kind::List; const HAS_LINKS: bool = T::HAS_LINKS; fn has_links(&self) -> bool { @@ -74,61 +76,70 @@ impl Representation for List { } } -impl_selector_seed_serde! { @codec_seed_visitor - { T: Select + 'static } {} List +// impl_selector_seed_serde! { @codec_seed_visitor +// { T: Select + 'static } {} List +// { +// #[inline] +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// write!(f, "A list of `{}`", T::NAME) +// } + +// #[inline] +// fn visit_seq(self, seq: A) -> Result +// where +// A: SeqAccess<'de>, +// { +// if let Some(s) = self.0.selector.as_explore_union() { +// if s.matches_first() { +// let list = >::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; +// return list.__select_in(self.0).map_err(A::Error::custom); +// } else { +// // todo: support multiple non-overlapping ranges +// } +// } + +// let iter = SerdeListIterator::<'de, _>::from(seq); +// match self.0.selector { +// Selector::Matcher(_) => { +// self.0.match_list::<_C, T, _, _, _, _, _>( +// iter, +// |iter| { +// let len = <_ as ListIterator>::size_hint(iter).unwrap_or(8); +// RefCell::new(List::::with_capacity(len)) +// }, +// |dag| Box::new(|child, _| Ok(dag.borrow_mut().push(child))), +// RefCell::into_inner, +// ).map_err(A::Error::custom) +// }, +// Selector::ExploreIndex(s) => self.0 +// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) +// .map_err(A::Error::custom), +// Selector::ExploreRange(s) => self.0 +// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) +// .map_err(A::Error::custom), +// Selector::ExploreAll(s) => self.0 +// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) +// .map_err(A::Error::custom), +// _ => Err(A::Error::custom(Error::unsupported_selector::>( +// self.0.selector, +// ))), +// } +// } +// }} + +// impl_selector_seed_serde! { @codec_seed_visitor_ext +// { T: Select + 'static } {} List {} +// } + +impl_selector_seed_serde! { @codec_seed_visitor_rk List + {} { T: 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A list of `{}`", T::NAME) - } - - #[inline] - fn visit_seq(self, seq: A) -> Result - where - A: SeqAccess<'de>, - { - if let Some(s) = self.0.selector.as_explore_union() { - if s.matches_first() { - let list = >::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; - return list.__select_in(self.0).map_err(A::Error::custom); - } else { - // todo: support multiple non-overlapping ranges - } - } - - let iter = SerdeListIterator::<'de, _>::from(seq); - match self.0.selector { - Selector::Matcher(_) => { - self.0.match_list::<_C, T, _, _, _, _, _>( - iter, - |iter| { - let len = <_ as ListIterator>::size_hint(iter).unwrap_or(8); - RefCell::new(List::::with_capacity(len)) - }, - |dag| Box::new(|child, _| Ok(dag.borrow_mut().push(child))), - RefCell::into_inner, - ).map_err(A::Error::custom) - }, - Selector::ExploreIndex(s) => self.0 - .explore_list_range::<_C, T, _, _>(iter, s.to_range()) - .map_err(A::Error::custom), - Selector::ExploreRange(s) => self.0 - .explore_list_range::<_C, T, _, _>(iter, s.to_range()) - .map_err(A::Error::custom), - Selector::ExploreAll(s) => self.0 - .explore_list_range::<_C, T, _, _>(iter, s.to_range()) - .map_err(A::Error::custom), - _ => Err(A::Error::custom(Error::unsupported_selector::>( - self.0.selector, - ))), - } + write!(f, "{}, a boolean type", Bool::NAME) } }} -impl_selector_seed_serde! { @codec_seed_visitor_ext - { T: Select + 'static } {} List {} -} - // impl_selector_seed_serde! { @selector_seed_codec_deseed // { T: Select + 'static } {} List // { diff --git a/src/data_model/map.rs b/src/data_model/map.rs index 817444e..ef8c570 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -16,6 +16,8 @@ where // K: AsRef> V: Representation, { + type ReprKind = type_kinds::Map; + const NAME: &'static str = "Map"; const SCHEMA: &'static str = concat!( "type Map {", @@ -95,59 +97,68 @@ where } } -impl_selector_seed_serde! { @codec_seed_visitor - { K: Select + StringRepresentation + 'static, - V: Select + 'static } - { } - Map +// impl_selector_seed_serde! { @codec_seed_visitor +// { K: Select + StringRepresentation + 'static, +// V: Select + 'static } +// { } +// Map +// { +// #[inline] +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// write!(f, "{}", Map::::NAME) +// } + +// #[inline] +// fn visit_map(self, map: A) -> Result +// where +// A: MapAccess<'de>, +// { +// if let Some(s) = self.0.selector.as_explore_union() { +// if s.matches_first() { +// let map = >::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; +// return map.__select_in(self.0).map_err(A::Error::custom); +// } +// } + +// let iter = SerdeMapIterator::<'de, _>::from(map); +// match self.0.selector { +// Selector::Matcher(_) => { +// self.0.match_map::<_C, K, V, _, _, _, _, _>( +// iter, +// |iter| RefCell::>::default(), +// |key, dag| Box::new(|child, _| { +// dag.borrow_mut().insert(key.clone(), child); +// Ok(()) +// }), +// RefCell::into_inner, +// ).map_err(A::Error::custom) +// }, +// Selector::ExploreFields(_) => self.0 +// .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), +// Selector::ExploreAll(_) => self.0 +// .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), +// _ => Err(A::Error::custom(Error::unsupported_selector::>( +// self.0.selector, +// ))), +// } +// } +// }} + +// impl_selector_seed_serde! { @codec_seed_visitor_ext +// { K: Select + StringRepresentation + 'static, +// V: Select + 'static } +// {} Map {} +// } + +impl_selector_seed_serde! { @codec_seed_visitor_rk Map + {} { T: 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", Map::::NAME) - } - - #[inline] - fn visit_map(self, map: A) -> Result - where - A: MapAccess<'de>, - { - if let Some(s) = self.0.selector.as_explore_union() { - if s.matches_first() { - let map = >::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; - return map.__select_in(self.0).map_err(A::Error::custom); - } - } - - let iter = SerdeMapIterator::<'de, _>::from(map); - match self.0.selector { - Selector::Matcher(_) => { - self.0.match_map::<_C, K, V, _, _, _, _, _>( - iter, - |iter| RefCell::>::default(), - |key, dag| Box::new(|child, _| { - dag.borrow_mut().insert(key.clone(), child); - Ok(()) - }), - RefCell::into_inner, - ).map_err(A::Error::custom) - }, - Selector::ExploreFields(_) => self.0 - .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), - Selector::ExploreAll(_) => self.0 - .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), - _ => Err(A::Error::custom(Error::unsupported_selector::>( - self.0.selector, - ))), - } + write!(f, "{}, a boolean type", Bool::NAME) } }} -impl_selector_seed_serde! { @codec_seed_visitor_ext - { K: Select + StringRepresentation + 'static, - V: Select + 'static } - {} Map {} -} - // impl_selector_seed_serde! { @selector_seed_codec_deseed // { K: Select + StringRepresentation + 'static, // V: Select + 'static } diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index e234996..a1a0ab1 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -24,6 +24,8 @@ mod null { pub struct Null; impl Representation for Null { + type ReprKind = type_kinds::Null; + const NAME: &'static str = "Null"; const SCHEMA: &'static str = "type Null null"; const DATA_MODEL_KIND: Kind = Kind::Null; @@ -46,37 +48,10 @@ mod null { } } - impl_selector_seed_serde! { @codec_seed_visitor {} {} Null { - #[inline] - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", Null::NAME) - } - - #[inline] - fn visit_none(self) -> Result - where - E: de::Error, - { - self.0.select_primitive::<_C>(Null).map_err(E::custom) - } - - #[inline] - fn visit_unit(self) -> Result - where - E: de::Error, - { - self.visit_none() - } - }} - - impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Null {} } - - // impl_selector_seed_serde! { @codec_seed_visitor_rk Null - // { T: From + 'static } {} T - // { + // impl_selector_seed_serde! { @codec_seed_visitor {} {} Null { // #[inline] // fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // write!(f, "{}, a nothing type", T::NAME) + // write!(f, "{}", Null::NAME) // } // #[inline] @@ -84,7 +59,7 @@ mod null { // where // E: de::Error, // { - // self.0.select_primitive::<_C>(T::from(Null)).map_err(E::custom) + // self.0.select_primitive::<_C>(Null).map_err(E::custom) // } // #[inline] @@ -96,6 +71,33 @@ mod null { // } // }} + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Null {} } + + impl_selector_seed_serde! { @codec_seed_visitor_rk Null + {} { T: From + 'static } + { + #[inline] + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}, a nothing type", T::NAME) + } + + #[inline] + fn visit_none(self) -> Result + where + E: de::Error, + { + self.0.select_primitive::<_C>(T::from(Null)).map_err(E::custom) + } + + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + self.visit_none() + } + }} + impl_selector_seed_serde! { @selector_seed_select {} {} Null } } @@ -106,6 +108,8 @@ mod bool { pub type Bool = bool; impl Representation for bool { + type ReprKind = type_kinds::Bool; + const NAME: &'static str = "Bool"; const SCHEMA: &'static str = "type Bool bool"; const DATA_MODEL_KIND: Kind = Kind::Bool; @@ -127,7 +131,30 @@ mod bool { } } - impl_selector_seed_serde! { @codec_seed_visitor {} {} Bool { + // impl_selector_seed_serde! { @codec_seed_visitor {} {} Bool { + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "{}, a boolean type", Bool::NAME) + // } + + // #[inline] + // fn visit_bool(self, v : bool) -> Result + // where + // E: de::Error, + // { + // if self.0.selector.is_explore_union() { + // v.__select_in(self.0).map_err(E::custom) + // } else { + // self.0.match_primitive::<_C>(v).map_err(E::custom) + // } + // } + // }} + + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bool {} } + + impl_selector_seed_serde! { @codec_seed_visitor_rk Bool + {} { T: From + 'static } + { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}, a boolean type", Bool::NAME) @@ -139,36 +166,13 @@ mod bool { E: de::Error, { if self.0.selector.is_explore_union() { - v.__select_in(self.0).map_err(E::custom) + T::from(v).__select_in(self.0).map_err(E::custom) } else { - self.0.match_primitive::<_C>(v).map_err(E::custom) + self.0.match_primitive::<_C>(T::from(v)).map_err(E::custom) } } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bool {} } - - // impl_selector_seed_serde! { @codec_seed_visitor_rk Bool - // { T: From } {} T - // { - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "{}, a boolean type", Bool::NAME) - // } - // - // #[inline] - // fn visit_bool(self, v : bool) -> Result - // where - // E: de::Error, - // { - // if self.0.selector.is_explore_union() { - // T::from(v).__select_in(self.0).map_err(E::custom) - // } else { - // self.0.match_primitive::<_C>(T::from(v)).map_err(E::custom) - // } - // } - // }} - impl_selector_seed_serde! { @selector_seed_select {} {} Bool } } @@ -178,7 +182,7 @@ mod num { /// Implements IPLD traits for native number types. macro_rules! impl_ipld_num { ( $ty:ident : $name:ident $kind:ident { - $deserialize_fn:ident + // $deserialize_fn:ident $visit_fn:ident @conv { $($other_ty:ty : $other_visit_fn:ident)* } } @@ -187,11 +191,13 @@ mod num { pub type $name = $ty; impl Representation for $ty { + type ReprKind = type_kinds::$name; + const NAME: &'static str = stringify!($name); const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); const DATA_MODEL_KIND: Kind = Kind::$kind; const SCHEMA_KIND: Kind = Kind::$name; - const REPR_KIND: Kind = Kind::$kind; + // const REPR_KIND: Kind = Kind::$kind; impl_ipld_num!(@field $kind $ty); @@ -212,34 +218,43 @@ mod num { } } - impl_selector_seed_serde! { @codec_seed_visitor {} {} $ty { + // impl_selector_seed_serde! { @codec_seed_visitor {} {} $ty { + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "{}, a fixed-length number type represented as a(n) {}", <$ty>::NAME, stringify!($ty)) + // } + + // #[inline] + // fn $visit_fn(self, v: $ty) -> Result + // where + // E: de::Error, + // { + // self.0.select_primitive::<_C>(v).map_err(E::custom) + // } + + // $( + // #[inline] + // fn $other_visit_fn(self, v: $other_ty) -> Result + // where + // E: de::Error, + // { + // let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; + // self.$visit_fn(n) + // } + // )* + // }} + + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } + + impl_selector_seed_serde! { @codec_seed_visitor_rk $name + {} { T: From<$ty> + 'static } + { #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a fixed-length number type represented as a(n) {}", <$ty>::NAME, stringify!($ty)) + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}, a nothing type", T::NAME) } - - #[inline] - fn $visit_fn(self, v: $ty) -> Result - where - E: de::Error, - { - self.0.select_primitive::<_C>(v).map_err(E::custom) - } - - $( - #[inline] - fn $other_visit_fn(self, v: $other_ty) -> Result - where - E: de::Error, - { - let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; - self.$visit_fn(n) - } - )* }} - impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } - impl_selector_seed_serde! { @selector_seed_select {} {} $ty } }; (@field Int $ty:ty) => { @@ -252,7 +267,7 @@ mod num { impl_ipld_num! ( i8 : Int8 Int { - deserialize_i8 + // deserialize_i8 visit_i8 @conv { i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -262,7 +277,7 @@ mod num { ); impl_ipld_num! ( i16 : Int16 Int { - deserialize_i16 + // deserialize_i16 visit_i16 @conv { i8:visit_i8 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -272,7 +287,7 @@ mod num { ); impl_ipld_num! ( i32 : Int32 Int { - deserialize_i32 + // deserialize_i32 visit_i32 @conv { i8:visit_i8 i16:visit_i16 i64:visit_i64 i128:visit_i128 @@ -282,7 +297,7 @@ mod num { ); impl_ipld_num! ( i64 : Int64 Int { - deserialize_i64 + // deserialize_i64 visit_i64 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i128:visit_i128 @@ -292,7 +307,7 @@ mod num { ); impl_ipld_num! ( i128 : Int128 Int { - deserialize_i128 + // deserialize_i128 visit_i128 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 @@ -302,7 +317,7 @@ mod num { ); impl_ipld_num! ( u8 : Uint8 Int { - deserialize_u8 + // deserialize_u8 visit_u8 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -312,7 +327,7 @@ mod num { ); impl_ipld_num! ( u16 : Uint16 Int { - deserialize_u16 + // deserialize_u16 visit_u16 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -322,7 +337,7 @@ mod num { ); impl_ipld_num! ( u32 : Uint32 Int { - deserialize_u32 + // deserialize_u32 visit_u32 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -332,7 +347,7 @@ mod num { ); impl_ipld_num! ( u64 : Uint64 Int { - deserialize_u64 + // deserialize_u64 visit_u64 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -342,7 +357,7 @@ mod num { ); impl_ipld_num! ( u128 : Uint128 Int { - deserialize_u128 + // deserialize_u128 visit_u128 @conv { i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 @@ -352,14 +367,14 @@ mod num { ); impl_ipld_num! ( f32 : Float32 Float { - deserialize_f32 + // deserialize_f32 visit_f32 @conv { f64:visit_f64 } } ); impl_ipld_num! ( f64 : Float64 Float { - deserialize_f64 + // deserialize_f64 visit_f64 @conv { f32:visit_f32 } } @@ -404,6 +419,8 @@ mod string { } impl Representation for IpldString { + type ReprKind = type_kinds::String; + const NAME: &'static str = "String"; const SCHEMA: &'static str = "type String string"; const DATA_MODEL_KIND: Kind = Kind::String; @@ -430,32 +447,41 @@ mod string { } // TODO: - impl_selector_seed_serde! { @codec_seed_visitor {} {} IpldString { - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "An IPLD string") - } + // impl_selector_seed_serde! { @codec_seed_visitor {} {} IpldString { + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "An IPLD string") + // } - #[inline] - fn visit_str(self, s: &str) -> Result - where - E: de::Error, - { - let v = IpldString::from(s); - self.0.select_primitive::<_C>(v).map_err(E::custom) - } + // #[inline] + // fn visit_str(self, s: &str) -> Result + // where + // E: de::Error, + // { + // let v = IpldString::from(s); + // self.0.select_primitive::<_C>(v).map_err(E::custom) + // } + + // #[inline] + // fn visit_string(self, s: String) -> Result + // where + // E: de::Error, + // { + // self.visit_str(s.as_ref()) + // } + // }} + + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} IpldString {} } + impl_selector_seed_serde! { @codec_seed_visitor_rk String + {} { T: From + 'static } + { #[inline] - fn visit_string(self, s: String) -> Result - where - E: de::Error, - { - self.visit_str(s.as_ref()) + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}, a nothing type", T::NAME) } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} IpldString {} } - impl_selector_seed_serde! { @selector_seed_select {} {} IpldString } impl From<&str> for IpldString { @@ -506,6 +532,8 @@ mod bytes { pub type Bytes = crate::dev::bytes::Bytes; impl Representation for Bytes { + type ReprKind = type_kinds::Bytes; + const NAME: &'static str = "Bytes"; const SCHEMA: &'static str = "type Bytes bytes"; const DATA_MODEL_KIND: Kind = Kind::Bytes; @@ -559,31 +587,40 @@ mod bytes { } } - impl_selector_seed_serde! { @codec_seed_visitor {} {} Bytes { - #[inline] - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "A slice of bytes") - } + // impl_selector_seed_serde! { @codec_seed_visitor {} {} Bytes { + // #[inline] + // fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(formatter, "A slice of bytes") + // } - #[inline] - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: de::Error, - { - self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) - } + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) + // } + + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) + // } + // }} + + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bytes {} } + impl_selector_seed_serde! { @codec_seed_visitor_rk Bytes + {} { T: From + 'static } + { #[inline] - fn visit_byte_buf(self, bytes: Vec) -> Result - where - E: de::Error, - { - self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}, a nothing type", T::NAME) } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bytes {} } - impl_selector_seed_serde! { @selector_seed_select {} {} Bytes } impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> @@ -626,9 +663,9 @@ mod bytes { } } -enum Assert {} -trait IsTrue {} -impl IsTrue for Assert {} +// enum Assert {} +// trait IsTrue {} +// impl IsTrue for Assert {} // impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed, T> // where diff --git a/src/lib.rs b/src/lib.rs index 617113d..7c3cb0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,8 @@ pub mod prelude { /// All exports from `ipld::prelude`, plus re-exports of first- and third-party /// dependencies to aid developers wanting to implement or extend `ipld` behaviour. pub mod dev { + #[doc(hidden)] + pub use crate::maybestd; pub use crate::{prelude::*, representation::*, selectors::*}; // dependency re-exports for macro convenience @@ -83,17 +85,13 @@ pub mod dev { pub use anyhow; #[doc(hidden)] pub use bytes; - // pub use erased_serde::{Deserializer as ErasedDeserializer, Serializer as ErasedSerializer}; /// Useful macros for aiding in providing bespoke IPLD support. pub mod macros { pub use crate::impl_selector_seed_serde; // pub use const_format::*; - pub use ipld_macros_internals::*; + pub use ipld_macros_internals::dev::*; } - #[doc(hidden)] - pub use crate::maybestd; - #[doc(hidden)] pub use serde::{ self, diff --git a/src/representation/mod.rs b/src/representation/mod.rs index b7fea5f..414f981 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -118,16 +118,25 @@ pub use strategies::*; /// - TODO: ? stateful visitor derived from selector + type? /// - TODO: ? impl DeserializeSeed for selector? /// - TODO: ? Representation::visitor(selector: &Selector) +// pub trait Representation: Sized { pub trait Representation: Sized { - // /// Marker type for exact `u32` value of the type's [`Representation::DATA_MODEL_KIND`], needed for internal blanket implementations of various traits. + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket + // /// implementations of various traits. // #[doc(hidden)] // type DATA_MODEL_KIND: TypedKind; - // /// Marker type for exact `u32` value of the type's [`Representation::SCHEMA_KIND`], needed for internal blanket implementations of various traits. + + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::SCHEMA_KIND`], needed for internal blanket + // /// implementations of various traits. // #[doc(hidden)] // type SCHEMA_KIND: TypedKind; - // /// Marker type for exact `u32` value of the type's [`Representation::REPR_KIND`], needed for internal blanket implementations of various traits. - // #[doc(hidden)] - // type REPR_KIND: TypedKind; + + /// Marker type for exact `u32` value of the type's + /// [`Representation::REPR_KIND`], needed for internal blanket + /// implementations of various traits. + #[doc(hidden)] + type ReprKind: TypedKind; // TODO: use this seed in Representation::deserialize by default // type Seed<'de, const C: u64>: Default + DeserializeSeed<'de, Value = Self>; @@ -137,8 +146,7 @@ pub trait Representation: Sized { /// The stringified IPLD type definition (or equivalent, if a native type /// not defined by IPLD). - /// TODO: we cant concat generic consts, only concrete ones - so refactor this to a function - const SCHEMA: &'static str = unimplemented!(); + const SCHEMA: &'static str; /// The IPLD [Data Model Kind](https://ipld.io/docs/data-model/kinds/) of /// the type, which would inform a user of its access patterns. @@ -150,7 +158,8 @@ pub trait Representation: Sized { const SCHEMA_KIND: Kind = Self::DATA_MODEL_KIND; /// The IPLD [Representation Kind]() of the type, which would inform a user of how the type is represented when encoded. - const REPR_KIND: Kind = Self::DATA_MODEL_KIND; // K + // const REPR_KIND: Kind = Self::DATA_MODEL_KIND; + const REPR_KIND: Kind = Self::ReprKind::KIND; // const IS_ADL: bool = false; diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index 170ee6f..cf58bf5 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -47,16 +47,17 @@ pub type EmptySeed = SelectorSeed<'static, (), T>; /// A marked [`SelectorSeed`] that's aware of the codec of the block it's /// currenly selecting against. -/// -/// TODO: a few issues to consider (going backwards): -/// ? 1. codec needs to receive a CodecDeserializeSeed (or otherwise CodedSeed, to associate the right const C) -/// ? 2. const C needs to carry down until we reach bytes/links -/// ? 3. Link needs to take some seed, uncode it, then use inner to call SelectorSeed::select for the next block #[doc(hidden)] #[derive(Debug)] -pub struct CodecSeed(pub(crate) S, PhantomData); +pub struct CodecSeed::ReprKind>( + pub(crate) S, + PhantomData<(T, RK)>, +) +where + T: Representation, + RK: TypedKind; -impl CodecSeed { +impl CodecSeed { // pub const RK: u32 = RK; // pub const fn is_select() -> bool { // (!RK) @@ -166,7 +167,10 @@ impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { const CAN_SELECT: bool = true; } -impl<'a, const C: u64, Ctx, T> CodecSeed, T> { +impl<'a, const C: u64, Ctx, T> CodecSeed, T> +where + T: Representation, +{ // /// // #[inline] // pub(crate) fn from_parts( @@ -599,55 +603,55 @@ where macro_rules! impl_selector_seed_serde { // visitor for CodedSeed - // impl Visitor for CodedSeed - (@codec_seed_visitor - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ident $(< - // match one or more lifetimes separated by a comma - $( $ty_generics:ident ),+ - >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - Visitor<'de> for - CodecSeed<_C, - SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - $ty $(<$($ty_generics),+>)? - > - where - Ctx: Context, - $($bounds)* - { - type Value = (); - $($visit_fns)* - } - }; - - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = true; - // impl<'a, 'de, const _C: u64, $($generics)*> - // Visitor<'de> for - // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> - // where - // $($generics)* - // { - // type Value = $ty; - // $($visit_fns)* - // } - }; - }; + // // impl Visitor for CodedSeed + // (@codec_seed_visitor + // { $($generics:tt)* } { $($bounds:tt)* } + // $ty:ident $(< + // // match one or more lifetimes separated by a comma + // $( $ty_generics:ident ),+ + // >)? + // { $($visit_fns:tt)* } + // ) => { + // const _: () = { + // #[allow(unused_imports)] + // use $crate::dev::*; + + // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); + // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // Visitor<'de> for + // CodecSeed<_C, + // SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + // $ty $(<$($ty_generics),+>)? + // > + // where + // Ctx: Context, + // $($bounds)* + // { + // type Value = (); + // $($visit_fns)* + // } + // }; + + // const _: () = { + // #[allow(unused_imports)] + // use $crate::dev::*; + + // // const _RK: u32 = true; + // // impl<'a, 'de, const _C: u64, $($generics)*> + // // Visitor<'de> for + // // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> + // // where + // // $($generics)* + // // { + // // type Value = $ty; + // // $($visit_fns)* + // // } + // }; + // }; // impl Visitor for CodedSeed by REPR_KIND (@codec_seed_visitor_rk $rk:ident { $($generics:tt)* } { $($bounds:tt)* } - $ty:ident + // $ty:ident // $(< // // match one or more lifetimes separated by a comma // $( $ty_generics:ident ),+ @@ -659,20 +663,29 @@ macro_rules! impl_selector_seed_serde { use $crate::dev::*; // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - const _RK: u32 = Kind::$rk.bits(); - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // const _RK: u32 = Kind::$rk.bits(); + impl<'_a, 'de, const _C: u64, T, Ctx, $($generics)*> Visitor<'de> for - CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty> + CodecSeed<_C, SelectorSeed<'_a, Ctx, T>, T, type_kinds::$rk> where - // T: Representation - // T: Select, - // Assert::<{ $ty::REPR_KIND.eq(Kind::$rk) }>: IsTrue, + T: Representation + Select, Ctx: Context, $($bounds)* { type Value = (); $($visit_fns)* } + + impl<'_a, 'de, const _C: u64, T, Ctx, $($generics)*> + IpldVisitorExt<'de> for + CodecSeed<_C, SelectorSeed<'_a, Ctx, T>, T, type_kinds::$rk> + where + T: Representation + Select, + Ctx: Context, + $($bounds)* + { + // $($visit_fns)* + } }; // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } @@ -691,19 +704,19 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - IpldVisitorExt<'de> for - CodecSeed<_C, - SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - $ty $(<$($ty_generics),+>)? - > - where - Ctx: Context, - $($bounds)* - { - $($visit_fns)* - } + // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); + // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // IpldVisitorExt<'de> for + // CodecSeed<_C, + // SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + // $ty $(<$($ty_generics),+>)? + // > + // where + // Ctx: Context, + // $($bounds)* + // { + // $($visit_fns)* + // } }; const _: () = { @@ -724,64 +737,64 @@ macro_rules! impl_selector_seed_serde { // CodecDeserializeSeed - // impl CodecDeserializeSeed for SelectorSeed - (@selector_seed_codec_deseed - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty - { $($deseed_fn:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = false; - // impl<'_a, 'de, Ctx, $($generics)*> - // CodecDeserializeSeed<'de> for - // SelectorSeed<'_a, Ctx, $ty> - // where - // Ctx: Context, - // $($bounds)* - // { - // type Value = (); - // $($deseed_fn)* - // // CodecSeed::(self).deserialize(deserializer) - // } - - // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - // DeserializeSeed<'de> for - // CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> - // where - // Ctx: Context, - // { - // type Value = (); - // $($deseed_fn)* - // } - }; - - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = true; - // impl<'a, 'de, $($generics)*> - // $crate::dev::CodecDeserializeSeed<'de> for - // std::marker::PhantomData<$ty> - // { - // type Value = $ty; - // $($deseed_fn)* - // } - - // impl<'de, const _C: u64 $($generics)*> - // $crate::dev::DeserializeSeed<'de> for - // $crate::dev::CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> - // where - // Self: $crate::dev::Visitor<'de>, - // { - // type Value = >::Value; - // $($deseed_fn)* - // } - }; - }; + // // impl CodecDeserializeSeed for SelectorSeed + // (@selector_seed_codec_deseed + // { $($generics:tt)* } { $($bounds:tt)* } + // $ty:ty + // { $($deseed_fn:tt)* } + // ) => { + // const _: () = { + // #[allow(unused_imports)] + // use $crate::dev::*; + + // // const _RK: u32 = false; + // // impl<'_a, 'de, Ctx, $($generics)*> + // // CodecDeserializeSeed<'de> for + // // SelectorSeed<'_a, Ctx, $ty> + // // where + // // Ctx: Context, + // // $($bounds)* + // // { + // // type Value = (); + // // $($deseed_fn)* + // // // CodecSeed::(self).deserialize(deserializer) + // // } + + // // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // // DeserializeSeed<'de> for + // // CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> + // // where + // // Ctx: Context, + // // { + // // type Value = (); + // // $($deseed_fn)* + // // } + // }; + + // const _: () = { + // #[allow(unused_imports)] + // use $crate::dev::*; + + // // const _RK: u32 = true; + // // impl<'a, 'de, $($generics)*> + // // $crate::dev::CodecDeserializeSeed<'de> for + // // std::marker::PhantomData<$ty> + // // { + // // type Value = $ty; + // // $($deseed_fn)* + // // } + + // // impl<'de, const _C: u64 $($generics)*> + // // $crate::dev::DeserializeSeed<'de> for + // // $crate::dev::CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> + // // where + // // Self: $crate::dev::Visitor<'de>, + // // { + // // type Value = >::Value; + // // $($deseed_fn)* + // // } + // }; + // }; // impl CodecDeserializeSeed for SelectorSeed, using deserialize_any (@selector_seed_codec_deseed @any { $($generics:tt)* } { $($bounds:tt)* } @@ -1136,358 +1149,3 @@ macro_rules! impl_selector_seed_serde { // } // }; } - -/* -/// Returns an iterator ... -pub fn seq_iter<'a: 'de, 'de, Ctx, A, T, U>( - selector: &'a Selector, - mut state: &'a mut SelectorState, - callback: Params<'_, C, T, Option>, - mut ctx: &'a mut C, - seq: A, -) -> Box, A::Error>> + 'a> -// ) -> FromFn<&'a mut dyn FnMut() -> Option, Error>>> -where - C: Context, - A: SeqAccess<'de> + 'a, - T: Representation + Select, - U: Representation, - Option: Select, -{ - // return an iterator - // for each item: - // - descend index, get next selector - // - create a deserializer, set it to state - // - - // - call T::select(inputs) - - let mut decoder = SeqIterDecoder::<_, C, T, U> { - seq, - end: false, - _t: PhantomData, - }; - Box::new(std::iter::from_fn(move || { - if decoder.end { - None - } else { - ctx.set_decoder(&mut decoder); - // todo: using option isnt right - match T::select::>(&selector, &mut state, callback, &mut ctx).transpose() { - Some(Err(err)) => Some(Err(A::Error::custom(err))), - Some(Ok(inner)) => Some(Ok(inner)), - None => None, - } - } - })) - - // T::select::(selector, state, ctx) - // unimplemented!() -} - -pub struct SeqIterDecoder { - pub seq: A, - pub end: u32, - _t: PhantomData<(C, T, U)>, -} - -impl SeqIterDecoder { - // fn new<'de>(seq: A) -> Box> - // where - // A: SeqAccess<'de> + 'static, - // { - // Box::new(>::erase(Self { - // seq, - // end: false, - // })) - // } - - // fn decode(self, visitor: V) -> Result - // where - // V: Visitor<'de>, - // { - - // } -} - -macro_rules! deserialize { - ($fn:ident) => { - // todo issue with this is that we cant add constraints to the V to use it as a seed - fn $fn(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - // if type_eq::, V>() { - // if let Some(next) = self.seq.next_element(self) - // } - } - }; -} - -impl<'de, A: SeqAccess<'de>, C, T, U> Deserializer<'de> for SeqIterDecoder { - type Error = A::Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - serde::serde_if_integer128! { - fn deserialize_i128(self, visitor: V) -> Result - where - V: Visitor<'de> - { - let _ = visitor; - Err(Self::Error::custom("i128 is not supported")) - } - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - serde::serde_if_integer128! { - fn deserialize_u128(self, visitor: V) -> Result - where - V: Visitor<'de> - { - let _ = visitor; - Err(Self::Error::custom("u128 is not supported")) - } - } - - fn deserialize_f32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_f64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } -} - -// default impl<'de, 'a, C, T, U> DeserializeSeed<'de> for SelectorSeed<'a, C, T, U> -// where -// C: Context, -// T: Representation, -// U: Representation, -// { -// default type Value = Option; - -// #[inline] -// default fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// D::Error::custom("must be implemented by an `ipld` crate type") -// } -// } - - */ From 9cbfa5bd1488c8df73e6ec9f824114b626dc7d2f Mon Sep 17 00:00:00 2001 From: sunny-g Date: Mon, 10 Oct 2022 16:09:40 -0500 Subject: [PATCH 5/9] more updates --- macros-internals/src/schema/expand.rs | 6 +- macros-internals/src/schema/mod.rs | 16 +- .../src/schema/union/expand_kinded.rs | 17 +- src/data_model/link.rs | 12 +- src/data_model/list.rs | 57 +- src/data_model/map.rs | 64 ++- src/data_model/primitive.rs | 213 ++++--- src/lib.rs | 1 + src/representation/mod.rs | 39 +- src/selectors/mod.rs | 15 +- src/selectors/seed.rs | 520 +++++++----------- tests/codec-fixtures.rs | 5 +- 12 files changed, 466 insertions(+), 499 deletions(-) diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index 66deedb..0237f92 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -341,8 +341,12 @@ macro_rules! derive_newtype { quote::quote! { // #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty // } + // #lib::dev::macros::impl_selector_seed_serde! { + // @selector_seed_select {} {} #name + // } + #lib::dev::macros::impl_selector_seed_serde! { - @selector_seed_select {} {} #name + @select_newtype {} {} #name { #name => #$inner_ty } } } }}; diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index 62b8d92..f4821a2 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -244,6 +244,11 @@ pub mod kind { /// Marker flag for lib-specific schema types for /// floating-point numbers. const TypedFloat = Self::Float32.bits | Self::Float64.bits; + + /// + const TypedScalar = Self::Scalar.bits + | Self::TypedInt.bits + | Self::TypedFloat.bits; } } @@ -261,12 +266,15 @@ pub mod kind { pub type Scalar = op!(Null | Bool | Int | Float | String | Bytes | Link); pub type Recursive = op!(List | Map); pub type Any = op!(Scalar | Recursive); + pub type Schema = op!(Any | Struct | Enum | Union | Copy | Advanced); - // pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); - // pub type TypedFloat = op!(Float32 | Float64); + pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); + pub type TypedFloat = op!(Float32 | Float64); - // #[doc(hidden)] - // pub type All = op!(Any | Schema | TypedInt | TypedFloat); + pub type TypedScalar = op!(Scalar | TypedInt | TypedFloat); + + #[doc(hidden)] + pub type All = op!(Any | Schema | TypedInt | TypedFloat); #[doc(hidden)] pub type Empty = U0; } diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index 1fee06f..06c5432 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -142,9 +142,9 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { // #lib::dev::macros::impl_selector_seed_serde! { // @selector_seed_codec_deseed @any {} {} #name // } - #lib::dev::macros::impl_selector_seed_serde! { - @selector_seed_select {} {} #name - } + // #lib::dev::macros::impl_selector_seed_serde! { + // @selector_seed_select {} {} #name + // } } } @@ -161,13 +161,10 @@ impl KindedUnionReprDefinition { } fn repr_kind(&self) -> TokenStream { - self - .iter() - .map(|f| f.repr_kind()) - .fold( - quote!(type_kinds::Empty), - |ts, kind| quote!(typenum::Or<#ts, #kind>), - ) + self.iter().map(|f| f.repr_kind()).fold( + quote!(type_kinds::Empty), + |ts, kind| quote!(typenum::Or<#ts, #kind>), + ) } } diff --git a/src/data_model/link.rs b/src/data_model/link.rs index 8790cd3..f3d97bf 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -140,18 +140,18 @@ impl Representation for Link { // } // }} -impl_selector_seed_serde! { @codec_seed_visitor_rk Link - {} { T: 'static } +impl_selector_seed_serde! { @codec_seed_visitor_rk Link T U + { T: 'static, U: Select + 'static } { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a boolean type", Bool::NAME) + write!(f, "A link of type {} to a {}", T::NAME, U::NAME) } }} -impl_selector_seed_serde! { @selector_seed_select - { T: Select + 'static } { } Link -} +// impl_selector_seed_serde! { @selector_seed_select +// { T: Select + 'static } { } Link +// } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, Link> where diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 2788a34..1c8023f 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -131,12 +131,55 @@ impl Representation for List { // { T: Select + 'static } {} List {} // } -impl_selector_seed_serde! { @codec_seed_visitor_rk List - {} { T: 'static } +// TODO: this should only apply to List datamodels with a List repr +// restrict this impl to T: Representation +impl_selector_seed_serde! { @codec_seed_visitor_rk List T U + { T: Default + Extend + 'static, + U: Select + 'static } + { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a boolean type", Bool::NAME) + write!(f, "A list of type {} of {}", T::NAME, U::NAME) + } + + #[inline] + fn visit_seq(self, seq: A) -> Result + where + A: SeqAccess<'de>, + { + if let Some(s) = self.0.selector.as_explore_union() { + if s.matches_first() { + let list = T::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; + return list.__select_in(self.0).map_err(A::Error::custom); + } else { + // todo: support multiple non-overlapping ranges + } + } + + let iter = SerdeListIterator::<'de, _>::from(seq); + match self.0.selector { + Selector::Matcher(_) => { + self.0.match_list::<_C, U, _, _, _, _, _>( + iter, + |_| RefCell::default(), + |dag| Box::new(|child, _| Ok(dag.borrow_mut().extend(iter::once(child)))), + RefCell::into_inner, + ).map_err(A::Error::custom) + }, + Selector::ExploreIndex(s) => self.0 + .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), + Selector::ExploreRange(s) => self.0 + .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), + Selector::ExploreAll(s) => self.0 + .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .map_err(A::Error::custom), + _ => Err(A::Error::custom(Error::unsupported_selector::( + self.0.selector, + ))), + } } }} @@ -152,16 +195,16 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk List // } // }} -impl_selector_seed_serde! { @selector_seed_select - { T: Select + 'static } {} List -} +// impl_selector_seed_serde! { @selector_seed_select +// { T: Select + 'static } {} List +// } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, T: Select + 'static, { - /// match + /// Executes a [`Matcher`] selector against a list (data model) type. /// todo could probably use a collection trait instead of multiple Fns pub fn match_list( mut self, diff --git a/src/data_model/map.rs b/src/data_model/map.rs index ef8c570..95a3a77 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -7,7 +7,7 @@ pub use iterators::*; /// /// TODO: indexmap? -pub type Map = BTreeMap; +pub type Map = BTreeMap; impl Representation for Map where @@ -150,34 +150,58 @@ where // {} Map {} // } -impl_selector_seed_serde! { @codec_seed_visitor_rk Map - {} { T: 'static } +impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) + { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + V: Select + 'static } + { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a boolean type", Bool::NAME) + write!(f, "A map of type {} of {} to {}", T::NAME, K::NAME, V::NAME) + } + + #[inline] + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'de>, + { + if let Some(s) = self.0.selector.as_explore_union() { + if s.matches_first() { + let map = T::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; + return map.__select_in(self.0).map_err(A::Error::custom); + } + } + + let iter = SerdeMapIterator::<'de, _>::from(map); + match self.0.selector { + Selector::Matcher(_) => { + self.0.match_map::<_C, K, V, _, _, _, _, _>( + iter, + |_| RefCell::default(), + |key, dag| Box::new(|child, _| { + dag.borrow_mut().extend(iter::once((key.clone(), child))); + Ok(()) + }), + RefCell::into_inner, + ).map_err(A::Error::custom) + }, + Selector::ExploreFields(_) => self.0 + .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), + Selector::ExploreAll(_) => self.0 + .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), + _ => Err(A::Error::custom(Error::unsupported_selector::( + self.0.selector, + ))), + } } }} -// impl_selector_seed_serde! { @selector_seed_codec_deseed +// impl_selector_seed_serde! { @selector_seed_select // { K: Select + StringRepresentation + 'static, // V: Select + 'static } // {} Map -// { -// #[inline] -// fn deserialize(self, deserializer: D) -> Result<(), D::Error> -// where -// D: Deserializer<'de>, -// { -// deserializer.deserialize_map(self) -// } -// }} - -impl_selector_seed_serde! { @selector_seed_select - { K: Select + StringRepresentation + 'static, - V: Select + 'static } - {} Map -} +// } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index a1a0ab1..247f16e 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -73,12 +73,12 @@ mod null { // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Null {} } - impl_selector_seed_serde! { @codec_seed_visitor_rk Null - {} { T: From + 'static } + impl_selector_seed_serde! { @codec_seed_visitor_rk Null T T + { T: From + 'static } { } { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}, a nothing type", T::NAME) + write!(f, "A nothing type {}", T::NAME) } #[inline] @@ -98,6 +98,10 @@ mod null { } }} + impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Null T T + { T: From + 'static } {} {} + } + impl_selector_seed_serde! { @selector_seed_select {} {} Null } } @@ -152,12 +156,12 @@ mod bool { // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bool {} } - impl_selector_seed_serde! { @codec_seed_visitor_rk Bool - {} { T: From + 'static } + impl_selector_seed_serde! { @codec_seed_visitor_rk Bool T T + { T: From + 'static } { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a boolean type", Bool::NAME) + write!(f, "A boolean type {}", T::NAME) } #[inline] @@ -173,6 +177,10 @@ mod bool { } }} + impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Bool T T + { T: From + 'static } {} {} + } + impl_selector_seed_serde! { @selector_seed_select {} {} Bool } } @@ -181,7 +189,7 @@ mod num { /// Implements IPLD traits for native number types. macro_rules! impl_ipld_num { - ( $ty:ident : $name:ident $kind:ident { + ( $ty:ident : $name:ident $dm_kind:ident { // $deserialize_fn:ident $visit_fn:ident @conv { $($other_ty:ty : $other_visit_fn:ident)* } @@ -195,11 +203,11 @@ mod num { const NAME: &'static str = stringify!($name); const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); - const DATA_MODEL_KIND: Kind = Kind::$kind; + const DATA_MODEL_KIND: Kind = Kind::$dm_kind; const SCHEMA_KIND: Kind = Kind::$name; - // const REPR_KIND: Kind = Kind::$kind; + // const REPR_KIND: Kind = Kind::$dm_kind; - impl_ipld_num!(@field $kind $ty); + impl_ipld_num!(@field $dm_kind $ty); #[doc(hidden)] fn serialize(&self, serializer: S) -> Result @@ -218,43 +226,41 @@ mod num { } } - // impl_selector_seed_serde! { @codec_seed_visitor {} {} $ty { - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "{}, a fixed-length number type represented as a(n) {}", <$ty>::NAME, stringify!($ty)) - // } - - // #[inline] - // fn $visit_fn(self, v: $ty) -> Result - // where - // E: de::Error, - // { - // self.0.select_primitive::<_C>(v).map_err(E::custom) - // } - - // $( - // #[inline] - // fn $other_visit_fn(self, v: $other_ty) -> Result - // where - // E: de::Error, - // { - // let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; - // self.$visit_fn(n) - // } - // )* - // }} - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } - - impl_selector_seed_serde! { @codec_seed_visitor_rk $name - {} { T: From<$ty> + 'static } + impl_selector_seed_serde! { @codec_seed_visitor_rk $name T T + { T: From<$ty> + 'static } { } { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}, a nothing type", T::NAME) + write!(f, + "{}, a fixed-length number type represented as a(n) {}", + <$ty>::NAME, stringify!($ty), + ) } + + #[inline] + fn $visit_fn(self, v: $ty) -> Result + where + E: de::Error, + { + self.0.select_primitive::<_C>(T::from(v)).map_err(E::custom) + } + + $( + #[inline] + fn $other_visit_fn(self, v: $other_ty) -> Result + where + E: de::Error, + { + let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; + self.$visit_fn(n) + } + )* }} + impl_selector_seed_serde! { @codec_seed_visitor_ext_rk $name T T + { T: From<$ty> + 'static } {} {} + } + impl_selector_seed_serde! { @selector_seed_select {} {} $ty } }; (@field Int $ty:ty) => { @@ -446,42 +452,35 @@ mod string { } } - // TODO: - // impl_selector_seed_serde! { @codec_seed_visitor {} {} IpldString { - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "An IPLD string") - // } - - // #[inline] - // fn visit_str(self, s: &str) -> Result - // where - // E: de::Error, - // { - // let v = IpldString::from(s); - // self.0.select_primitive::<_C>(v).map_err(E::custom) - // } - - // #[inline] - // fn visit_string(self, s: String) -> Result - // where - // E: de::Error, - // { - // self.visit_str(s.as_ref()) - // } - // }} - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} IpldString {} } - - impl_selector_seed_serde! { @codec_seed_visitor_rk String - {} { T: From + 'static } + impl_selector_seed_serde! { @codec_seed_visitor_rk String T T + { T: From + 'static } {} { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}, a nothing type", T::NAME) + write!(f, "A string of type {}", T::NAME) + } + + #[inline] + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + self.0.select_primitive::<_C>(T::from(IpldString::from(s))).map_err(E::custom) + } + + #[inline] + fn visit_string(self, s: String) -> Result + where + E: de::Error, + { + self.visit_str(s.as_ref()) } }} + impl_selector_seed_serde! { @codec_seed_visitor_ext_rk String T T + { T: From + 'static } {} {} + } + impl_selector_seed_serde! { @selector_seed_select {} {} IpldString } impl From<&str> for IpldString { @@ -583,52 +582,53 @@ mod bytes { if C == DagJson::CODE { return DagJson::deserialize_bytes(deserializer, BytesVisitor); } + deserializer.deserialize_bytes(BytesVisitor) } } - // impl_selector_seed_serde! { @codec_seed_visitor {} {} Bytes { - // #[inline] - // fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(formatter, "A slice of bytes") - // } - - // #[inline] - // fn visit_bytes(self, bytes: &[u8]) -> Result - // where - // E: de::Error, - // { - // self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) - // } - - // #[inline] - // fn visit_byte_buf(self, bytes: Vec) -> Result - // where - // E: de::Error, - // { - // self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) - // } - // }} - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bytes {} } - - impl_selector_seed_serde! { @codec_seed_visitor_rk Bytes - {} { T: From + 'static } + impl_selector_seed_serde! { @codec_seed_visitor_rk Bytes T T + { T: From + 'static } { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, a nothing type", T::NAME) - } + write!(f, "Bytes of type {}", T::NAME) + } + + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) + // } + + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) + // } }} + impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Bytes T T + { T: From + 'static } {} {} + } + impl_selector_seed_serde! { @selector_seed_select {} {} Bytes } impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> where Ctx: Context, + // impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> + // where + // Ctx: Context, + // T: Select, { /// #[inline] + // TODO: should accept a slice of bytes, then do conversion pub fn select_bytes(mut self, bytes: Bytes) -> Result<(), Error> { // if let Some(s) = self.selector.as_explore_union() { // s.assert_matches_first::()?; @@ -663,22 +663,11 @@ mod bytes { } } -// enum Assert {} -// trait IsTrue {} -// impl IsTrue for Assert {} - -// impl<'a, const C: u64, const RK: u32, Ctx, T> CodecSeed, T> -// where -// Ctx: Context, -// T: Representation + 'static, -// Assert<{ (Kind::Scalar.bits() & RK) == RK }>: IsTrue, -// { -// } - impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, T: Representation + 'static, + // TODO And: TypedScalar { /// pub fn select_primitive(self, raw: T) -> Result<(), Error> diff --git a/src/lib.rs b/src/lib.rs index 7c3cb0b..b83af90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ //! TODO: //! - utf-8 string handling/normalization //! - replace boxed callbacks with a ref +//! - ?? refactor Matcher* logic to only select nodes #![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)] #[cfg_attr(not(feature = "std"), no_std)] diff --git a/src/representation/mod.rs b/src/representation/mod.rs index 414f981..e96c981 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -120,27 +120,6 @@ pub use strategies::*; /// - TODO: ? Representation::visitor(selector: &Selector) // pub trait Representation: Sized { pub trait Representation: Sized { - // /// Marker type for exact `u32` value of the type's - // /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket - // /// implementations of various traits. - // #[doc(hidden)] - // type DATA_MODEL_KIND: TypedKind; - - // /// Marker type for exact `u32` value of the type's - // /// [`Representation::SCHEMA_KIND`], needed for internal blanket - // /// implementations of various traits. - // #[doc(hidden)] - // type SCHEMA_KIND: TypedKind; - - /// Marker type for exact `u32` value of the type's - /// [`Representation::REPR_KIND`], needed for internal blanket - /// implementations of various traits. - #[doc(hidden)] - type ReprKind: TypedKind; - - // TODO: use this seed in Representation::deserialize by default - // type Seed<'de, const C: u64>: Default + DeserializeSeed<'de, Value = Self>; - /// The stringified name of the IPLD type. const NAME: &'static str; @@ -168,6 +147,24 @@ pub trait Representation: Sized { #[doc(hidden)] const __IGNORED: bool = false; + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket + // /// implementations of various traits. + // #[doc(hidden)] + // type DATA_MODEL_KIND: TypedKind; + + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::SCHEMA_KIND`], needed for internal blanket + // /// implementations of various traits. + // #[doc(hidden)] + // type SCHEMA_KIND: TypedKind; + + /// Marker type for exact `u32` value of the type's + /// [`Representation::REPR_KIND`], needed for internal blanket + /// implementations of various traits. + #[doc(hidden)] + type ReprKind: TypedKind; + /// /// todo deprecate const IS_LINK: bool = Self::DATA_MODEL_KIND.is_link(); diff --git a/src/selectors/mod.rs b/src/selectors/mod.rs index 615ef0e..073c62f 100644 --- a/src/selectors/mod.rs +++ b/src/selectors/mod.rs @@ -63,6 +63,13 @@ pub trait Select: Representation { ctx, ); + Self::__select(seed) + } + + #[doc(hidden)] + fn __select<'a>( + seed: SelectorSeed<'a, Ctx, Self>, + ) -> Result<(), Error> { let cid = &seed.state.current_block; let block = seed.ctx.block_reader(cid)?; cid.multicodec()?.read_with_seed(seed, block) @@ -76,7 +83,7 @@ pub trait Select: Representation { where D: Deserializer<'de>, { - Err(D::Error::custom("unimplemented")) + Err(D::Error::custom("__select_de not yet implemented")) // TODO: default impl should use GAT for CodedSeed // Self::Seed::<'a, 'de, C>::from(seed).deserialize(deserializer) } @@ -90,7 +97,7 @@ pub trait Select: Representation { A: SeqAccess<'de>, { // seq.next_element_seed(CodecSeed::from(seed)) - Err(A::Error::custom("unimplemented")) + Err(A::Error::custom("__select_seq not yet implemented")) // TODO: default impl should use GAT for CodedSeed // seq.next_element_seed(Self::Seed::<'a, 'de, C>::from(seed)) } @@ -104,7 +111,7 @@ pub trait Select: Representation { where A: MapAccess<'de>, { - Err(A::Error::custom("unimplemented")) + Err(A::Error::custom("__select_map not yet implemented")) // TODO: default impl should use GAT for CodedSeed // let seed = Self::Seed::<'a, 'de, C>::from(seed); // if is_key { @@ -189,7 +196,7 @@ pub trait Select: Representation { /// /// TODO #[doc(hidden)] - fn patch_in(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { + fn patch_in(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { unimplemented!() } diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index cf58bf5..6a9e68d 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -49,15 +49,16 @@ pub type EmptySeed = SelectorSeed<'static, (), T>; /// currenly selecting against. #[doc(hidden)] #[derive(Debug)] -pub struct CodecSeed::ReprKind>( +pub struct CodecSeed::ReprKind>( pub(crate) S, - PhantomData<(T, RK)>, + PhantomData<(T, U, RK)>, ) where T: Representation, + U: Representation, RK: TypedKind; -impl CodecSeed { +impl CodecSeed { // pub const RK: u32 = RK; // pub const fn is_select() -> bool { // (!RK) @@ -69,16 +70,20 @@ impl CodecSeed { // T::SCHEMA_KIND // } - const fn schema_kind() -> Kind + pub fn from(seed: S) -> Self { + Self(seed, PhantomData) + } + + const fn repr_kind() -> Kind where T: Representation, { - if Kind::TypedInt.contains(T::SCHEMA_KIND) { - Int::SCHEMA_KIND - } else if Kind::TypedFloat.contains(T::SCHEMA_KIND) { - Float::SCHEMA_KIND + if Kind::TypedInt.contains(T::REPR_KIND) { + Int::REPR_KIND + } else if Kind::TypedFloat.contains(T::REPR_KIND) { + Float::REPR_KIND } else { - T::SCHEMA_KIND + T::REPR_KIND } } } @@ -87,13 +92,13 @@ impl CodecSeed { /// Doing this allows us to focus selection implementations on what to do when /// visiting a particular representation. /// -impl<'a, 'de, const C: u64, S, T> DeserializeSeed<'de> for CodecSeed +impl<'a, 'de, const C: u64, S, T, U, RK> DeserializeSeed<'de> for CodecSeed where Self: Visitor<'de> + IpldVisitorExt<'de>, - // Ctx: Context, - // T: Select, - S: SeedType, - T: Representation, + S: SeedType, + T: Representation, + U: Representation, + RK: TypedKind, { type Value = >::Value; @@ -104,33 +109,36 @@ where { use Kind as K; - match (Self::schema_kind(), T::REPR_KIND) { - _ if T::__IGNORED => deserializer.deserialize_ignored_any(self), - (_, K::Null) => deserializer.deserialize_unit(self), - (_, K::Bool) => deserializer.deserialize_bool(self), - (K::Int8, K::Int) => deserializer.deserialize_i8(self), - (K::Int16, K::Int) => deserializer.deserialize_i16(self), - (K::Int32, K::Int) => deserializer.deserialize_i32(self), - (K::Int64, K::Int) => deserializer.deserialize_i64(self), - (K::Int128, K::Int) => deserializer.deserialize_i128(self), - (K::Uint8, K::Int) => deserializer.deserialize_u8(self), - (K::Uint16, K::Int) => deserializer.deserialize_u16(self), - (K::Uint32, K::Int) => deserializer.deserialize_u32(self), - (K::Uint64, K::Int) => deserializer.deserialize_u64(self), - (K::Uint128, K::Int) => deserializer.deserialize_u128(self), - (K::Float32, K::Float) => deserializer.deserialize_f32(self), - (K::Float64, K::Float) => deserializer.deserialize_f64(self), - (_, K::String) => deserializer.deserialize_str(self), - (_, K::Bytes) => { + if T::__IGNORED { + return deserializer.deserialize_ignored_any(self); + } + + match Self::repr_kind() { + K::Null => deserializer.deserialize_unit(self), + K::Bool => deserializer.deserialize_bool(self), + K::Int8 => deserializer.deserialize_i8(self), + K::Int16 => deserializer.deserialize_i16(self), + K::Int32 => deserializer.deserialize_i32(self), + K::Int64 => deserializer.deserialize_i64(self), + K::Int128 => deserializer.deserialize_i128(self), + K::Uint8 => deserializer.deserialize_u8(self), + K::Uint16 => deserializer.deserialize_u16(self), + K::Uint32 => deserializer.deserialize_u32(self), + K::Uint64 => deserializer.deserialize_u64(self), + K::Uint128 => deserializer.deserialize_u128(self), + K::Float32 => deserializer.deserialize_f32(self), + K::Float64 => deserializer.deserialize_f64(self), + K::String => deserializer.deserialize_str(self), + K::Bytes => { #[cfg(feature = "dag-json")] if C == DagJson::CODE { return DagJson::deserialize_bytes(deserializer, self); } deserializer.deserialize_bytes(self) } - (_, K::List) => deserializer.deserialize_seq(self), - (_, K::Map) => deserializer.deserialize_map(self), - (_, K::Link) => { + K::List => deserializer.deserialize_seq(self), + K::Map => deserializer.deserialize_map(self), + K::Link => { #[cfg(feature = "dag-json")] if C == DagJson::CODE { return DagJson::deserialize_cid(deserializer, self); @@ -157,13 +165,16 @@ where } #[doc(hidden)] -pub trait SeedType { +pub trait SeedType { + type Output; const CAN_SELECT: bool; } -impl SeedType for PhantomData { +impl SeedType for PhantomData { + type Output = T; const CAN_SELECT: bool = false; } -impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { +impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { + type Output = (); const CAN_SELECT: bool = true; } @@ -603,231 +614,121 @@ where macro_rules! impl_selector_seed_serde { // visitor for CodedSeed - // // impl Visitor for CodedSeed - // (@codec_seed_visitor - // { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ident $(< - // // match one or more lifetimes separated by a comma - // $( $ty_generics:ident ),+ - // >)? - // { $($visit_fns:tt)* } - // ) => { - // const _: () = { - // #[allow(unused_imports)] - // use $crate::dev::*; - - // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - // Visitor<'de> for - // CodecSeed<_C, - // SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - // $ty $(<$($ty_generics),+>)? - // > - // where - // Ctx: Context, - // $($bounds)* - // { - // type Value = (); - // $($visit_fns)* - // } - // }; - - // const _: () = { - // #[allow(unused_imports)] - // use $crate::dev::*; - - // // const _RK: u32 = true; - // // impl<'a, 'de, const _C: u64, $($generics)*> - // // Visitor<'de> for - // // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> - // // where - // // $($generics)* - // // { - // // type Value = $ty; - // // $($visit_fns)* - // // } - // }; - // }; - // impl Visitor for CodedSeed by REPR_KIND - (@codec_seed_visitor_rk $rk:ident - { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ident - // $(< - // // match one or more lifetimes separated by a comma - // $( $ty_generics:ident ),+ - // >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - // const _RK: u32 = Kind::$rk.bits(); - impl<'_a, 'de, const _C: u64, T, Ctx, $($generics)*> - Visitor<'de> for - CodecSeed<_C, SelectorSeed<'_a, Ctx, T>, T, type_kinds::$rk> - where - T: Representation + Select, - Ctx: Context, - $($bounds)* - { - type Value = (); - $($visit_fns)* - } - - impl<'_a, 'de, const _C: u64, T, Ctx, $($generics)*> - IpldVisitorExt<'de> for - CodecSeed<_C, SelectorSeed<'_a, Ctx, T>, T, type_kinds::$rk> - where - T: Representation + Select, - Ctx: Context, - $($bounds)* - { - // $($visit_fns)* - } - }; - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } + // impl Visitor for CodedSeed + (@codec_seed_visitor + { $($generics:tt)* } { $($bounds:tt)* } + $ty:ident $(< + // match one or more lifetimes separated by a comma + $( $ty_generics:ident ),+ + >)? + { $($visit_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + Visitor<'de> for + CodecSeed<_C, + SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + $ty $(<$($ty_generics),+>)? + > + where + Ctx: Context, + $($bounds)* + { + type Value = (); + $($visit_fns)* + } }; - // impl IpldVisitorExt for CodedSeed - (@codec_seed_visitor_ext - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ident $(< - // match one or more lifetimes separated by a comma - $( $ty_generics:ident ),+ - >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - // IpldVisitorExt<'de> for - // CodecSeed<_C, - // SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - // $ty $(<$($ty_generics),+>)? - // > - // where - // Ctx: Context, - // $($bounds)* - // { - // $($visit_fns)* - // } - }; - - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // const _RK: u32 = true; - // impl<'a, 'de, const _C: u64, $($generics)*> - // IpldVisitorExt<'de> for - // CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> - // where - // $($generics)* - // { - // $($visit_fns)* - // } - }; + }; + // impl IpldVisitorExt for CodedSeed + (@codec_seed_visitor_ext + { $($generics:tt)* } { $($bounds:tt)* } + $ty:ident $(< + // match one or more lifetimes separated by a comma + $( $ty_generics:ident ),+ + >)? + { $($visit_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + IpldVisitorExt<'de> for + CodecSeed<_C, + SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, + $ty $(<$($ty_generics),+>)? + > + where + Ctx: Context, + $($bounds)* + { + $($visit_fns)* + } + }; + }; + + // impl Visitor for CodedSeed by REPR_KIND + + (@codec_seed_visitor_rk $rk:ident $ty:ident $marker_ty:ty + { $($generics:tt)* } { $($bounds:tt)* } + // $ty:ident + // $(< + // // match one or more lifetimes separated by a comma + // $( $ty_generics:ident ),+ + // >)? + { $($visit_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + Visitor<'de> for + CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty, $marker_ty, type_kinds::$rk> + where + $ty: Representation + Select, + Ctx: Context, + $($bounds)* + { + type Value = (); + $($visit_fns)* + } }; - // CodecDeserializeSeed - - // // impl CodecDeserializeSeed for SelectorSeed - // (@selector_seed_codec_deseed - // { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ty - // { $($deseed_fn:tt)* } - // ) => { - // const _: () = { - // #[allow(unused_imports)] - // use $crate::dev::*; - - // // const _RK: u32 = false; - // // impl<'_a, 'de, Ctx, $($generics)*> - // // CodecDeserializeSeed<'de> for - // // SelectorSeed<'_a, Ctx, $ty> - // // where - // // Ctx: Context, - // // $($bounds)* - // // { - // // type Value = (); - // // $($deseed_fn)* - // // // CodecSeed::(self).deserialize(deserializer) - // // } - - // // impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - // // DeserializeSeed<'de> for - // // CodecSeed<_C, _RK, SelectorSeed<'_a, Ctx, $ty>, $ty> - // // where - // // Ctx: Context, - // // { - // // type Value = (); - // // $($deseed_fn)* - // // } - // }; - - // const _: () = { - // #[allow(unused_imports)] - // use $crate::dev::*; - - // // const _RK: u32 = true; - // // impl<'a, 'de, $($generics)*> - // // $crate::dev::CodecDeserializeSeed<'de> for - // // std::marker::PhantomData<$ty> - // // { - // // type Value = $ty; - // // $($deseed_fn)* - // // } - - // // impl<'de, const _C: u64 $($generics)*> - // // $crate::dev::DeserializeSeed<'de> for - // // $crate::dev::CodecSeed<_C, _RK, std::marker::PhantomData<$ty>> - // // where - // // Self: $crate::dev::Visitor<'de>, - // // { - // // type Value = >::Value; - // // $($deseed_fn)* - // // } - // }; - // }; - // impl CodecDeserializeSeed for SelectorSeed, using deserialize_any - (@selector_seed_codec_deseed @any - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty - ) => { - $crate::dev::macros::impl_selector_seed_serde! { - @selector_seed_codec_deseed { $($generics)* } { $($bounds)* } $ty + // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } + }; + // impl Visitor for CodedSeed by REPR_KIND + (@codec_seed_visitor_ext_rk $rk:ident $ty:ident $marker_ty:ty + { $($generics:tt)* } { $($bounds:tt)* } + // $ty:ident + // $(< + // // match one or more lifetimes separated by a comma + // $( $ty_generics:ident ),+ + // >)? + { $($visit_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + IpldVisitorExt<'de> for + CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty, $marker_ty, type_kinds::$rk> + where + $ty: Representation + Select, + Ctx: Context, + $($bounds)* { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - macros::cfg_if! { - if #[cfg(feature = "dag-json")] { - if _C == DagJson::CODE { - DagJson::deserialize_any(deserializer, self) - } else { - deserializer.deserialize_any(self) - } - } else if #[cfg(featureu = "dag-cbor")] { - if _C == DagCbor::CODE { - DagCbor::deserialize_any(deserializer, self) - } else { - deserializer.deserialize_any(self) - } - } else { - deserializer.deserialize_any(self) - } - } - } - }} + $($visit_fns)* + } }; + }; // Select @@ -853,17 +754,17 @@ macro_rules! impl_selector_seed_serde { // SelectorSeed::<'_, Ctx, Self>::select(params, ctx) // } - // #[doc(hidden)] - // fn __select_de<'a, 'de, const C: u64, D>( - // seed: SelectorSeed<'a, Ctx, Self>, - // deserializer: D, - // ) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // let seed = CodecSeed::::from(seed); - // seed.deserialize(deserializer) - // } + #[doc(hidden)] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = CodecSeed::::from(seed); + seed.deserialize(deserializer) + } // #[doc(hidden)] // fn __select_seq<'a, 'de, const C: u64, A>( @@ -942,55 +843,52 @@ macro_rules! impl_selector_seed_serde { { #[doc(hidden)] #[inline] - fn __select<'a, 'de, const C: u64>( + fn __select<'a>( seed: SelectorSeed<'a, Ctx, Self>, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { + ) -> Result<(), Error> { let seed = seed.wrap::<$inner_ty, _>($constructor); - <$inner_ty>::__select::(seed, deserializer) + <$inner_ty>::__select(seed) } - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = seed.wrap::<$inner_ty, _>($constructor); - <$inner_ty>::__select_de::(seed, deserializer) - } + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const C: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // let seed = seed.wrap::<$inner_ty, _>($constructor); + // <$inner_ty>::__select_de::(seed, deserializer) + // } - #[doc(hidden)] - #[inline] - fn __select_seq<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - seq: A, - ) -> Result, A::Error> - where - A: SeqAccess<'de>, - { - let seed = seed.wrap::<$inner_ty, _>($constructor); - <$inner_ty>::__select_seq::(seed, seq) - } + // #[doc(hidden)] + // #[inline] + // fn __select_seq<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // seq: A, + // ) -> Result, A::Error> + // where + // A: SeqAccess<'de>, + // { + // let seed = seed.wrap::<$inner_ty, _>($constructor); + // <$inner_ty>::__select_seq::(seed, seq) + // } - #[doc(hidden)] - #[inline] - fn __select_map<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - map: A, - is_key: bool, - ) -> Result, A::Error> - where - A: MapAccess<'de>, - { - let seed = seed.wrap::<$inner_ty, _>($constructor); - <$inner_ty>::__select_map::(seed, map, is_key) - } + // #[doc(hidden)] + // #[inline] + // fn __select_map<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // map: A, + // is_key: bool, + // ) -> Result, A::Error> + // where + // A: MapAccess<'de>, + // { + // let seed = seed.wrap::<$inner_ty, _>($constructor); + // <$inner_ty>::__select_map::(seed, map, is_key) + // } } }; }; diff --git a/tests/codec-fixtures.rs b/tests/codec-fixtures.rs index 09cd900..d699147 100644 --- a/tests/codec-fixtures.rs +++ b/tests/codec-fixtures.rs @@ -298,7 +298,6 @@ impl Fixture { } } - /* { // next, decode the concrete type using the Matcher selector let mut ctx = self.setup_ctx(); @@ -317,7 +316,7 @@ impl Fixture { .expect(&self.format_err::("should not fail to encode dag")); let new_cid = self .cid - .derive_new(block.as_ref()) + .derive_new(block.as_slice()) .expect(&"should not fail to generate a Cid for a block of bytes"); if self.codec.name() == "dag-json" { @@ -344,7 +343,7 @@ impl Fixture { ); } } - */ + true } From d2b8f9b2439c31a6b7bc1496a4d7b3d0066cc4bf Mon Sep 17 00:00:00 2001 From: sunny-g Date: Wed, 12 Oct 2022 09:36:04 -0500 Subject: [PATCH 6/9] remove macros-hack crate, other changes --- Cargo.toml | 14 +- macros-hack/Cargo.toml | 14 - macros-hack/src/lib.rs | 54 -- macros/Cargo.toml | 7 +- macros/src/lib.rs | 37 +- src/codecs/dag_json.rs | 2 +- src/{data_model/compat.rs => compat/core.rs} | 2 + src/compat/mod.rs | 1 + src/data_model/any.rs | 12 +- src/data_model/link.rs | 49 +- src/data_model/list.rs | 100 +--- src/data_model/map.rs | 82 +-- src/data_model/mod.rs | 1 - src/data_model/primitive.rs | 375 ++++++-------- src/error.rs | 7 +- src/lib.rs | 28 +- src/multihash.rs | 7 +- src/representation/mod.rs | 65 ++- src/selectors/seed.rs | 504 +++++++------------ 19 files changed, 494 insertions(+), 867 deletions(-) delete mode 100644 macros-hack/Cargo.toml delete mode 100644 macros-hack/src/lib.rs rename src/{data_model/compat.rs => compat/core.rs} (99%) create mode 100644 src/compat/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 1614fd5..a8932bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,6 @@ path = "src/lib.rs" # core bytes = "1.2" cid = { version = "0.8", features = ["alloc", "serde-codec"] } -# erased-serde = { version = "0.3", features = ["std"] } -# ipfs = { git = "https://github.com/ipfs-rust/rust-ipfs", branch = "master", optional = true } ipld-macros = { path = "./macros" } ipld-macros-internals = { path = "./macros-internals" } multibase = "0.9" @@ -41,12 +39,14 @@ delegate = { version = "0.8", optional = true } downcast-rs = "1.2" [dev-dependencies] -criterion = "0.4" -proptest = "1.0" +# criterion = "0.4" +# proptest = "1.0" [features] -default = ["multicodec", "std"] +default = ["multicodec", "std", "dev"] std = ["cid/std", "core2/std", "multihash/std"] +# activate dev docs +dev = [] # codecs dag-cbor = ["serde_cbor"] @@ -61,12 +61,8 @@ multicodec = ["dag-cbor", "dag-json", "dag-pb"] [workspace] members = [ - # "advanced-schemas", - # "codegen", "macros", - "macros-hack", "macros-internals", - # "sqlite", ] exclude = [ "codec-fixtures/rust", diff --git a/macros-hack/Cargo.toml b/macros-hack/Cargo.toml deleted file mode 100644 index 7df82e2..0000000 --- a/macros-hack/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "ipld-macros-hack" -version = "0.0.3" -authors = ["sunny-g "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -ipld-macros-internals = { path = "../macros-internals" } -proc-macro-hack = "0.5" -quote = "1.0" -syn = "1.0" diff --git a/macros-hack/src/lib.rs b/macros-hack/src/lib.rs deleted file mode 100644 index 86b0e71..0000000 --- a/macros-hack/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -extern crate proc_macro; - -use ipld_macros_internals::{ - // def_attributes, - RootSelectorDefinition, - // ValueDefinition, - SchemaDefinition, -}; -use proc_macro::TokenStream; -use proc_macro_hack::proc_macro_hack; -use syn::parse_macro_input; - -/// -/// -/// TODO: rename attrs to ipld_macros(), add a `wrap = Box/Rc/etc` attr -#[proc_macro] -pub fn schema(input: TokenStream) -> TokenStream { - let schema = parse_macro_input!(input as SchemaDefinition); - TokenStream::from(schema.expand()) -} - -/// A no-op macro, used to help the `schema!` and `selector!` macros capture -/// relevant arguments. -#[proc_macro_attribute] -pub fn ipld_attr(_attr: TokenStream, items: TokenStream) -> TokenStream { - items -} - -/// -#[proc_macro_hack] -pub fn selector(input: TokenStream) -> TokenStream { - let selector = parse_macro_input!(input as RootSelectorDefinition); - TokenStream::from(selector.expand()) -} - -// /// -// #[proc_macro] -// pub fn value(input: TokenStream) -> TokenStream { -// let value = parse_macro_input!(input as ValueDefinition); -// TokenStream::from(value.expand()) -// } - -// exports attribute proc macros used with `schema!`. -// def_attributes!( -// #[doc(hidden)] -// ipld_macros_internal -// ); -// def_attributes!(try_from); -// def_attributes!(wrap); - -// #[proc_macro_hack] -// pub fn derive_root_select(input: TokenStream) -> TokenStream { -// let expanded -// } diff --git a/macros/Cargo.toml b/macros/Cargo.toml index abebf8a..5700d8d 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -4,14 +4,13 @@ version = "0.0.3" authors = ["sunny-g "] edition = "2018" +[lib] +proc-macro = true + [dependencies] -ipld-macros-hack = { path = "../macros-hack" } ipld-macros-internals = { path = "../macros-internals" } -proc-macro-hack = "0.5" quote = "1.0" syn = "1.0" [features] default = [] -convert = [] -# graphql = ["juniper"] diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 16eb5f5..bac598e 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -4,22 +4,37 @@ //! - support pub/pub(crate) and additional #[derive(...)] statements //! - anything can have an advanced representation, so add support to all types -use proc_macro_hack::proc_macro_hack; - -// pub use ipld_macros_internals::{}; +use ipld_macros_internals::{ + // def_attributes, + RootSelectorDefinition, + // ValueDefinition, + SchemaDefinition, +}; +use proc_macro::TokenStream; +use syn::parse_macro_input; /// -/// todo: docs -pub use ipld_macros_hack::schema; - /// -/// todo: docs -#[proc_macro_hack] -pub use ipld_macros_hack::selector; +/// TODO: rename attrs to ipld_macros(), add a `wrap = Box/Rc/etc` attr +#[proc_macro] +pub fn schema(input: TokenStream) -> TokenStream { + let schema = parse_macro_input!(input as SchemaDefinition); + TokenStream::from(schema.expand()) +} + +/// A no-op macro, used to help the `schema!` and `selector!` macros capture +/// relevant arguments. +#[proc_macro_attribute] +pub fn ipld_attr(_attr: TokenStream, items: TokenStream) -> TokenStream { + items +} /// -/// todo: docs -pub use ipld_macros_hack::ipld_attr; +#[proc_macro] +pub fn selector(input: TokenStream) -> TokenStream { + let selector = parse_macro_input!(input as RootSelectorDefinition); + TokenStream::from(selector.expand()) +} // def_attributes!( // #[doc(hidden)] diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index 094d7f2..15f5bcc 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -41,7 +41,7 @@ impl DagJson { /// `{ "/": { "base64": } }`. #[inline] pub(crate) fn serialize_bytes( - bytes: &[u8], + bytes: impl AsRef<[u8]>, serializer: S, ) -> Result { use ser::SerializeStructVariant; diff --git a/src/data_model/compat.rs b/src/compat/core.rs similarity index 99% rename from src/data_model/compat.rs rename to src/compat/core.rs index f03950a..e6f38c8 100644 --- a/src/data_model/compat.rs +++ b/src/compat/core.rs @@ -35,6 +35,8 @@ mod ignored { mod option { use super::*; + // ? define Optional and Nullable? + impl Representation for Option where T: Representation, diff --git a/src/compat/mod.rs b/src/compat/mod.rs new file mode 100644 index 0000000..9816037 --- /dev/null +++ b/src/compat/mod.rs @@ -0,0 +1 @@ +mod core; diff --git a/src/data_model/any.rs b/src/data_model/any.rs index e3423aa..45bc7fb 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -1,7 +1,7 @@ use crate::dev::*; use macros::{ derive_more::{From, IsVariant, TryInto, Unwrap}, - impl_selector_seed_serde, + repr_serde, }; use maybestd::{fmt, rc::Rc}; use std::path::Path; @@ -16,7 +16,9 @@ use std::path::Path; schema! { /// #[ipld_attr(internal)] - #[derive(Clone, Debug, From, PartialEq, TryInto, IsVariant, Unwrap)] + #[derive(Clone, Debug, From, PartialEq, TryInto, + // IsVariant, Unwrap + )] // #[from(forward)] #[try_into(owned, ref, ref_mut)] // TODO: impl from(forward) and try_into for all unions and enums @@ -45,8 +47,8 @@ schema! { } representation kinded; } -// impl_selector_seed_serde! { @codec_seed_visitor_rk Any -// {} { T: 'static } +// repr_serde! { @visitor T T { type_kinds::Any } +// { T: TryFrom + 'static } {} // { // #[inline] // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -54,6 +56,8 @@ schema! { // } // }} +// repr_serde! { @visitor_ext T T { type_kinds::Any } { T: TryFrom + 'static } {} {}} + /// TODO: convert these to a Node trait, that all types implement impl Any { /// LookupByString looks up a child object in this node and returns it. diff --git a/src/data_model/link.rs b/src/data_model/link.rs index f3d97bf..b3659cd 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -1,5 +1,5 @@ use crate::dev::*; -use macros::{derive_more::From, impl_selector_seed_serde}; +use macros::{derive_more::From, repr_serde}; use maybestd::fmt; /// @@ -119,39 +119,30 @@ impl Representation for Link { } } -// impl_selector_seed_serde! { @codec_seed_visitor -// { T: Select + 'static } { } Link -// { -// #[inline] -// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// write!(f, "A link to a `{}`", T::NAME) -// } -// }} - -// impl_selector_seed_serde! { @codec_seed_visitor_ext -// { T: Select + 'static } { } Link -// { -// #[inline] -// fn visit_cid(self, cid: Cid) -> Result -// where -// E: de::Error, -// { -// self.0.select_link::<_C>(cid).map_err(E::custom) -// } -// }} - -impl_selector_seed_serde! { @codec_seed_visitor_rk Link T U - { T: 'static, U: Select + 'static } { } +repr_serde! { @visitor S T { type_kinds::Link } { S, T } + { S: 'static, T: Select + 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A link of type {} to a {}", T::NAME, U::NAME) + write!(f, "A link of type {} to a {}", S::NAME, T::NAME) } }} -// impl_selector_seed_serde! { @selector_seed_select -// { T: Select + 'static } { } Link -// } +// ? impl From? +repr_serde! { @visitor_ext S T { type_kinds::Link } { S, T } + { S: 'static, T: Select + 'static } +{ + #[inline] + fn visit_cid(self, cid: Cid) -> Result + where + E: de::Error, + { + // self.0.select_link::(cid).map_err(E::custom) + unimplemented!() + } +}} + +repr_serde! { @select Link => T { T } { T: Select + 'static } } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, Link> where @@ -159,6 +150,8 @@ where T: Select + 'static, { fn select_link<'de, const C: u64>(mut self, cid: Cid) -> Result<(), Error> { + // TODO: handle "blocks encoded with rawa codec are valid Bytes kinds" + if self.selector.is_matcher() { if self.is_dag_select() { self.select_dag(Link::Cid(cid))?; diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 1c8023f..72d771c 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -1,5 +1,5 @@ use crate::dev::*; -use macros::impl_selector_seed_serde; +use macros::repr_serde; use maybestd::{ cell::RefCell, fmt, iter, @@ -20,7 +20,6 @@ impl Representation for List { const SCHEMA: &'static str = concat!("type List [", stringify!(T::NAME), "]"); const DATA_MODEL_KIND: Kind = Kind::List; const SCHEMA_KIND: Kind = Kind::List; - // const REPR_KIND: Kind = Kind::List; const HAS_LINKS: bool = T::HAS_LINKS; fn has_links(&self) -> bool { @@ -76,71 +75,15 @@ impl Representation for List { } } -// impl_selector_seed_serde! { @codec_seed_visitor -// { T: Select + 'static } {} List -// { -// #[inline] -// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// write!(f, "A list of `{}`", T::NAME) -// } - -// #[inline] -// fn visit_seq(self, seq: A) -> Result -// where -// A: SeqAccess<'de>, -// { -// if let Some(s) = self.0.selector.as_explore_union() { -// if s.matches_first() { -// let list = >::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; -// return list.__select_in(self.0).map_err(A::Error::custom); -// } else { -// // todo: support multiple non-overlapping ranges -// } -// } - -// let iter = SerdeListIterator::<'de, _>::from(seq); -// match self.0.selector { -// Selector::Matcher(_) => { -// self.0.match_list::<_C, T, _, _, _, _, _>( -// iter, -// |iter| { -// let len = <_ as ListIterator>::size_hint(iter).unwrap_or(8); -// RefCell::new(List::::with_capacity(len)) -// }, -// |dag| Box::new(|child, _| Ok(dag.borrow_mut().push(child))), -// RefCell::into_inner, -// ).map_err(A::Error::custom) -// }, -// Selector::ExploreIndex(s) => self.0 -// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) -// .map_err(A::Error::custom), -// Selector::ExploreRange(s) => self.0 -// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) -// .map_err(A::Error::custom), -// Selector::ExploreAll(s) => self.0 -// .explore_list_range::<_C, T, _, _>(iter, s.to_range()) -// .map_err(A::Error::custom), -// _ => Err(A::Error::custom(Error::unsupported_selector::>( -// self.0.selector, -// ))), -// } -// } -// }} - -// impl_selector_seed_serde! { @codec_seed_visitor_ext -// { T: Select + 'static } {} List {} -// } - // TODO: this should only apply to List datamodels with a List repr // restrict this impl to T: Representation -impl_selector_seed_serde! { @codec_seed_visitor_rk List T U - { T: Default + Extend + 'static, - U: Select + 'static } - { } +repr_serde! { @visitor S T { type_kinds::List } { S, T } + { S: Default + Extend + 'static, + T: Select + 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A list of type {} of {}", T::NAME, U::NAME) + write!(f, "A list of type {} of {}", S::NAME, T::NAME) } #[inline] @@ -150,7 +93,7 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk List T U { if let Some(s) = self.0.selector.as_explore_union() { if s.matches_first() { - let list = T::deserialize::<_C, _>(SeqAccessDeserializer::new(seq))?; + let list = S::deserialize::(SeqAccessDeserializer::new(seq))?; return list.__select_in(self.0).map_err(A::Error::custom); } else { // todo: support multiple non-overlapping ranges @@ -160,7 +103,7 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk List T U let iter = SerdeListIterator::<'de, _>::from(seq); match self.0.selector { Selector::Matcher(_) => { - self.0.match_list::<_C, U, _, _, _, _, _>( + self.0.match_list::( iter, |_| RefCell::default(), |dag| Box::new(|child, _| Ok(dag.borrow_mut().extend(iter::once(child)))), @@ -168,36 +111,27 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk List T U ).map_err(A::Error::custom) }, Selector::ExploreIndex(s) => self.0 - .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .explore_list_range::(iter, s.to_range()) .map_err(A::Error::custom), Selector::ExploreRange(s) => self.0 - .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .explore_list_range::(iter, s.to_range()) .map_err(A::Error::custom), Selector::ExploreAll(s) => self.0 - .explore_list_range::<_C, U, _, _>(iter, s.to_range()) + .explore_list_range::(iter, s.to_range()) .map_err(A::Error::custom), - _ => Err(A::Error::custom(Error::unsupported_selector::( + _ => Err(A::Error::custom(Error::unsupported_selector::( self.0.selector, ))), } } }} -// impl_selector_seed_serde! { @selector_seed_codec_deseed -// { T: Select + 'static } {} List -// { -// #[inline] -// fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// deserializer.deserialize_seq(self) -// } -// }} - -// impl_selector_seed_serde! { @selector_seed_select -// { T: Select + 'static } {} List -// } +repr_serde! { @visitor_ext S T { type_kinds::List } { S, T } + { S: Default + Extend + 'static, + T: Select + 'static } {} +} + +repr_serde! { @select List => T { T } { T: Select + 'static } } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where diff --git a/src/data_model/map.rs b/src/data_model/map.rs index 95a3a77..87097c6 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -1,5 +1,5 @@ use crate::dev::*; -use macros::impl_selector_seed_serde; +use macros::repr_serde; use maybestd::{cell::RefCell, collections::BTreeMap, fmt, iter, marker::PhantomData}; use serde::de::value::MapAccessDeserializer; @@ -97,64 +97,10 @@ where } } -// impl_selector_seed_serde! { @codec_seed_visitor -// { K: Select + StringRepresentation + 'static, -// V: Select + 'static } -// { } -// Map -// { -// #[inline] -// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// write!(f, "{}", Map::::NAME) -// } - -// #[inline] -// fn visit_map(self, map: A) -> Result -// where -// A: MapAccess<'de>, -// { -// if let Some(s) = self.0.selector.as_explore_union() { -// if s.matches_first() { -// let map = >::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; -// return map.__select_in(self.0).map_err(A::Error::custom); -// } -// } - -// let iter = SerdeMapIterator::<'de, _>::from(map); -// match self.0.selector { -// Selector::Matcher(_) => { -// self.0.match_map::<_C, K, V, _, _, _, _, _>( -// iter, -// |iter| RefCell::>::default(), -// |key, dag| Box::new(|child, _| { -// dag.borrow_mut().insert(key.clone(), child); -// Ok(()) -// }), -// RefCell::into_inner, -// ).map_err(A::Error::custom) -// }, -// Selector::ExploreFields(_) => self.0 -// .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), -// Selector::ExploreAll(_) => self.0 -// .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), -// _ => Err(A::Error::custom(Error::unsupported_selector::>( -// self.0.selector, -// ))), -// } -// } -// }} - -// impl_selector_seed_serde! { @codec_seed_visitor_ext -// { K: Select + StringRepresentation + 'static, -// V: Select + 'static } -// {} Map {} -// } - -impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) +repr_serde! { @visitor T (K, V) { type_kinds::Map } { T, K, V } { T: Default + Extend<(K, V)> + 'static, K: Select + StringRepresentation + 'static, V: Select + 'static } - { } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -168,7 +114,7 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) { if let Some(s) = self.0.selector.as_explore_union() { if s.matches_first() { - let map = T::deserialize::<_C, _>(MapAccessDeserializer::new(map))?; + let map = T::deserialize::(MapAccessDeserializer::new(map))?; return map.__select_in(self.0).map_err(A::Error::custom); } } @@ -176,7 +122,7 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) let iter = SerdeMapIterator::<'de, _>::from(map); match self.0.selector { Selector::Matcher(_) => { - self.0.match_map::<_C, K, V, _, _, _, _, _>( + self.0.match_map::( iter, |_| RefCell::default(), |key, dag| Box::new(|child, _| { @@ -187,9 +133,9 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) ).map_err(A::Error::custom) }, Selector::ExploreFields(_) => self.0 - .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), + .explore_map_fields::(iter).map_err(A::Error::custom), Selector::ExploreAll(_) => self.0 - .explore_map_fields::<_C, K, V, _>(iter).map_err(A::Error::custom), + .explore_map_fields::(iter).map_err(A::Error::custom), _ => Err(A::Error::custom(Error::unsupported_selector::( self.0.selector, ))), @@ -197,11 +143,17 @@ impl_selector_seed_serde! { @codec_seed_visitor_rk Map T (K, V) } }} -// impl_selector_seed_serde! { @selector_seed_select -// { K: Select + StringRepresentation + 'static, -// V: Select + 'static } -// {} Map -// } +repr_serde! { @visitor_ext T (K, V) { type_kinds::Map } { T, K, V } + { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + V: Select + 'static } + {} +} + +repr_serde! { @select Map => (K, V) { K, V } + { K: Select + StringRepresentation + 'static, + V: Select + 'static } +} impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where diff --git a/src/data_model/mod.rs b/src/data_model/mod.rs index 82f2752..816e738 100644 --- a/src/data_model/mod.rs +++ b/src/data_model/mod.rs @@ -4,7 +4,6 @@ use crate::dev::*; use macros::derive_more::From; mod any; -mod compat; // pub mod borrowed; // mod canon; mod link; diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index 247f16e..3dd7159 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -1,9 +1,14 @@ use crate::dev::*; use macros::{ derive_more::{AsMut, AsRef, Deref, DerefMut, From, Index, IndexMut, Into, IntoIterator}, - impl_selector_seed_serde, + repr_serde, +}; +use maybestd::{ + borrow::Cow, + fmt, + ops::{self, RangeBounds}, + str::FromStr, }; -use maybestd::{borrow::Cow, fmt, str::FromStr}; pub use self::bool::Bool; pub use self::bytes::Bytes; @@ -43,38 +48,12 @@ mod null { where D: Deserializer<'de>, { - <()>::deserialize(deserializer)?; - Ok(Self) + Ok(Self::from(<()>::deserialize(deserializer)?)) } } - // impl_selector_seed_serde! { @codec_seed_visitor {} {} Null { - // #[inline] - // fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // write!(f, "{}", Null::NAME) - // } - - // #[inline] - // fn visit_none(self) -> Result - // where - // E: de::Error, - // { - // self.0.select_primitive::<_C>(Null).map_err(E::custom) - // } - - // #[inline] - // fn visit_unit(self) -> Result - // where - // E: de::Error, - // { - // self.visit_none() - // } - // }} - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Null {} } - - impl_selector_seed_serde! { @codec_seed_visitor_rk Null T T - { T: From + 'static } { } + repr_serde! { @visitor T T { type_kinds::Null } + { T } { T: From + 'static } { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -86,7 +65,7 @@ mod null { where E: de::Error, { - self.0.select_primitive::<_C>(T::from(Null)).map_err(E::custom) + self.0.select_scalar::(T::from(Null)).map_err(E::custom) } #[inline] @@ -98,11 +77,18 @@ mod null { } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Null T T - { T: From + 'static } {} {} + repr_serde! { @visitor_ext T T { type_kinds::Null } + { T } { T: From + 'static } {} } - impl_selector_seed_serde! { @selector_seed_select {} {} Null } + repr_serde! { @select Null => Null {} {} } + + impl From<()> for Null { + #[inline] + fn from(_: ()) -> Self { + Self + } + } } mod bool { @@ -135,29 +121,8 @@ mod bool { } } - // impl_selector_seed_serde! { @codec_seed_visitor {} {} Bool { - // #[inline] - // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // write!(f, "{}, a boolean type", Bool::NAME) - // } - - // #[inline] - // fn visit_bool(self, v : bool) -> Result - // where - // E: de::Error, - // { - // if self.0.selector.is_explore_union() { - // v.__select_in(self.0).map_err(E::custom) - // } else { - // self.0.match_primitive::<_C>(v).map_err(E::custom) - // } - // } - // }} - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} Bool {} } - - impl_selector_seed_serde! { @codec_seed_visitor_rk Bool T T - { T: From + 'static } { } + repr_serde! { @visitor T T { type_kinds::Bool } + { T } { T: From + 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -169,19 +134,15 @@ mod bool { where E: de::Error, { - if self.0.selector.is_explore_union() { - T::from(v).__select_in(self.0).map_err(E::custom) - } else { - self.0.match_primitive::<_C>(T::from(v)).map_err(E::custom) - } + self.0.select_scalar::(T::from(v)).map_err(E::custom) } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Bool T T - { T: From + 'static } {} {} + repr_serde! { @visitor_ext T T { type_kinds::Bool } + { T } { T: From + 'static } {} } - impl_selector_seed_serde! { @selector_seed_select {} {} Bool } + repr_serde! { @select Bool => Bool {} {} } } mod num { @@ -205,7 +166,6 @@ mod num { const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); const DATA_MODEL_KIND: Kind = Kind::$dm_kind; const SCHEMA_KIND: Kind = Kind::$name; - // const REPR_KIND: Kind = Kind::$dm_kind; impl_ipld_num!(@field $dm_kind $ty); @@ -226,8 +186,8 @@ mod num { } } - impl_selector_seed_serde! { @codec_seed_visitor_rk $name T T - { T: From<$ty> + 'static } { } + repr_serde! { @visitor T T { type_kinds::$name } + { T } { T: From<$ty> + 'static } { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -242,7 +202,7 @@ mod num { where E: de::Error, { - self.0.select_primitive::<_C>(T::from(v)).map_err(E::custom) + self.0.select_scalar::(T::from(v)).map_err(E::custom) } $( @@ -251,17 +211,17 @@ mod num { where E: de::Error, { - let n = <$ty as Representation>::deserialize::<_C, _>(v.into_deserializer())?; + let n = <$ty as Representation>::deserialize::(v.into_deserializer())?; self.$visit_fn(n) } )* }} - impl_selector_seed_serde! { @codec_seed_visitor_ext_rk $name T T - { T: From<$ty> + 'static } {} {} + repr_serde! { @visitor_ext T T { type_kinds::$name } + { T } { T: From<$ty> + 'static } {} } - impl_selector_seed_serde! { @selector_seed_select {} {} $ty } + repr_serde! { @select $ty => $ty {} {} } }; (@field Int $ty:ty) => { fn as_field(&self) -> Option> { @@ -271,120 +231,48 @@ mod num { (@field Float $ty:ty) => {}; } - impl_ipld_num! ( - i8 : Int8 Int { - // deserialize_i8 - visit_i8 - @conv { - i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - i16 : Int16 Int { - // deserialize_i16 - visit_i16 - @conv { - i8:visit_i8 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - i32 : Int32 Int { - // deserialize_i32 - visit_i32 - @conv { - i8:visit_i8 i16:visit_i16 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - i64 : Int64 Int { - // deserialize_i64 - visit_i64 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - i128 : Int128 Int { - // deserialize_i128 - visit_i128 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - u8 : Uint8 Int { - // deserialize_u8 - visit_u8 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - u16 : Uint16 Int { - // deserialize_u16 - visit_u16 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u32:visit_u32 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - u32 : Uint32 Int { - // deserialize_u32 - visit_u32 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u64:visit_u64 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - u64 : Uint64 Int { - // deserialize_u64 - visit_u64 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u128:visit_u128 - } - } - ); - impl_ipld_num! ( - u128 : Uint128 Int { - // deserialize_u128 - visit_u128 - @conv { - i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 - u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 - } - } - ); - impl_ipld_num! ( - f32 : Float32 Float { - // deserialize_f32 - visit_f32 - @conv { f64:visit_f64 } - } - ); - impl_ipld_num! ( - f64 : Float64 Float { - // deserialize_f64 - visit_f64 - @conv { f32:visit_f32 } - } - ); + impl_ipld_num! (i8 : Int8 Int { visit_i8 @conv { + i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (i16 : Int16 Int { visit_i16 @conv { + i8:visit_i8 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (i32 : Int32 Int { visit_i32 @conv { + i8:visit_i8 i16:visit_i16 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (i64 : Int64 Int { visit_i64 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (i128 : Int128 Int { visit_i128 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (u8 : Uint8 Int { visit_u8 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u16:visit_u16 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (u16 : Uint16 Int { visit_u16 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u32:visit_u32 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (u32 : Uint32 Int { visit_u32 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u64:visit_u64 u128:visit_u128 + }}); + impl_ipld_num! (u64 : Uint64 Int { visit_u64 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u128:visit_u128 + }}); + impl_ipld_num! (u128 : Uint128 Int { visit_u128 @conv { + i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64 i128:visit_i128 + u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64 + }}); + impl_ipld_num! (f32 : Float32 Float { visit_f32 @conv { f64:visit_f64 } }); + impl_ipld_num! (f64 : Float64 Float { visit_f64 @conv { f32:visit_f32 } }); } // TODO: unicode normalization? https://ipld.io/docs/data-model/kinds/#string-kind @@ -452,8 +340,8 @@ mod string { } } - impl_selector_seed_serde! { @codec_seed_visitor_rk String T T - { T: From + 'static } {} + repr_serde! { @visitor T T { type_kinds::String } + { T } { T: From + 'static } { #[inline] fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -465,7 +353,7 @@ mod string { where E: de::Error, { - self.0.select_primitive::<_C>(T::from(IpldString::from(s))).map_err(E::custom) + self.0.select_scalar::(T::from(IpldString::from(s))).map_err(E::custom) } #[inline] @@ -477,11 +365,11 @@ mod string { } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext_rk String T T - { T: From + 'static } {} {} + repr_serde! { @visitor_ext T T { type_kinds::String } + { T } { T: From + 'static } {} } - impl_selector_seed_serde! { @selector_seed_select {} {} IpldString } + repr_serde! { @select IpldString => IpldString {} {} } impl From<&str> for IpldString { #[inline] @@ -527,8 +415,72 @@ mod string { mod bytes { use super::*; - /// A bytes type. - pub type Bytes = crate::dev::bytes::Bytes; + // /// A bytes type. + // pub type Bytes = crate::dev::bytes::Bytes; + + /// A `bytes` type, which thinly wraps [`bytes::Bytes`]. + /// + /// TODO: mutability + /// [`Bytes`]: bytes::Bytes + #[derive( + AsRef, + // AsMut, + Clone, + Debug, + Default, + Deref, + Eq, + From, + Hash, + // Index, + IntoIterator, + Ord, + PartialOrd, + PartialEq, + )] + #[as_ref(forward)] + #[deref(forward)] + #[from(forward)] + pub struct Bytes(crate::dev::bytes::Bytes); + + impl Bytes { + /// + pub const fn new() -> Self { + Self(crate::dev::bytes::Bytes::new()) + } + + /// + pub fn copy_from_slice(bytes: &[u8]) -> Self { + Self(crate::dev::bytes::Bytes::copy_from_slice(bytes)) + } + + /// + pub const fn len(&self) -> usize { + self.0.len() + } + + /// + pub const fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// + pub fn slice(&self, range: impl RangeBounds) -> Self { + Self(self.0.slice(range)) + } + + /// + pub fn clear(&mut self) { + self.0.clear() + } + } + + // impl> ops::Index for Bytes { + // type Output = Self; + // fn index(&self, index: R) -> &Self::Output { + // Self(self.0.slice(index)) + // } + // } impl Representation for Bytes { type ReprKind = type_kinds::Bytes; @@ -587,8 +539,9 @@ mod bytes { } } - impl_selector_seed_serde! { @codec_seed_visitor_rk Bytes T T - { T: From + 'static } { } + repr_serde! { @visitor T T { type_kinds::Bytes } { T } + // { T: for<'a> TryFrom<&'a [u8], Error = Error> + 'static } + { T: From + 'static } { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -600,7 +553,7 @@ mod bytes { // where // E: de::Error, // { - // self.0.select_bytes::<_C>(Bytes::copy_from_slice(bytes)).map_err(E::custom) + // self.0.select_bytes::(Bytes::copy_from_slice(bytes)).map_err(E::custom) // } // #[inline] @@ -608,15 +561,16 @@ mod bytes { // where // E: de::Error, // { - // self.0.select_bytes::<_C>(Bytes::from(bytes)).map_err(E::custom) + // self.0.select_bytes::(Bytes::from(bytes)).map_err(E::custom) // } }} - impl_selector_seed_serde! { @codec_seed_visitor_ext_rk Bytes T T - { T: From + 'static } {} {} + repr_serde! { @visitor_ext T T { type_kinds::Bytes } { T } + // { T: for<'a> TryFrom<&'a [u8], Error = Error> + 'static } {} + { T: From + 'static } {} } - impl_selector_seed_serde! { @selector_seed_select {} {} Bytes } + repr_serde! { @select Bytes => Bytes {} {} } impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> where @@ -634,7 +588,7 @@ mod bytes { // s.assert_matches_first::()?; // bytes.__select_in(self) // } else { - // self.match_primitive::(raw) + // self.match_scalar::(raw) // } if let Some(matcher) = self.selector.as_matcher() { @@ -655,7 +609,7 @@ mod bytes { match self.selector { Selector::ExploreInterpretAs(_) => { - todo!("what reprs and ADLs are interpreted from byte nodes?") + todo!("what reprs and ADLs are interpreted from bytes?") } selector => Err(Error::unsupported_selector::(&selector)), } @@ -666,24 +620,21 @@ mod bytes { impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, - T: Representation + 'static, + T: Select + 'static, // TODO And: TypedScalar { /// - pub fn select_primitive(self, raw: T) -> Result<(), Error> - where - T: Select, - { + pub fn select_scalar(self, raw: T) -> Result<(), Error> { if let Some(s) = self.selector.as_explore_union() { s.assert_matches_first::()?; raw.__select_in(self) } else { - self.match_primitive::(raw) + self.match_scalar::(raw) } } #[inline] - fn match_primitive<'de, const C: u64>(mut self, dag: T) -> Result<(), Error> { + fn match_scalar<'de, const C: u64>(mut self, dag: T) -> Result<(), Error> { self.selector.try_as_matcher()?; if self.is_node_select() { diff --git a/src/error.rs b/src/error.rs index 47625ee..88f0664 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,12 +1,11 @@ use crate::dev::*; use cid::Error as CidError; +use maybestd::{ + error::Error as StdError, fmt::Display, num::TryFromIntError, string::FromUtf8Error, +}; use multibase::Error as MultibaseError; use multihash::Error as MultihashError; use serde::{de, ser}; -use std::{ - convert::Infallible, error::Error as StdError, fmt::Display, num::TryFromIntError, - string::FromUtf8Error, sync::mpsc::SendError, -}; use thiserror::Error; #[derive(Debug, Error)] diff --git a/src/lib.rs b/src/lib.rs index b83af90..0c1ae79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,7 @@ mod cid_; #[path = "codecs/mod.rs"] mod codecs_; +mod compat; mod data_model; mod error; mod multicodec; @@ -26,9 +27,12 @@ mod multihash_; mod representation; mod selectors; +pub use cid; #[doc(inline)] pub use error::Error; -#[doc(inline)] +pub use multibase; +pub use multihash; + pub use specs::*; mod specs { @@ -45,16 +49,22 @@ mod specs { // multiformats pub use multibase::Base as Multibase; - pub use multihash::{self, Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}; + + #[doc(hidden)] + pub use multihash::{Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}; pub use multihash_::Multihash; // cid pub use crate::cid_::*; - pub use cid::{Cid as DefaultCid, CidGeneric, Version}; + pub use cid::Version; + #[doc(hidden)] + pub use cid::{Cid as DefaultCid, CidGeneric}; // data model, schemas and representation pub use crate::data_model::*; - pub use crate::representation::{Kind, Representation, TypedKind as _}; + #[doc(hidden)] + pub use crate::representation::TypedKind as _; + pub use crate::representation::{Kind, Representation}; pub use ipld_macros::{ipld_attr, schema}; // selectors @@ -88,7 +98,7 @@ pub mod dev { pub use bytes; /// Useful macros for aiding in providing bespoke IPLD support. pub mod macros { - pub use crate::impl_selector_seed_serde; + pub use crate::repr_serde; // pub use const_format::*; pub use ipld_macros_internals::dev::*; } @@ -118,7 +128,9 @@ pub mod maybestd { extern crate alloc; pub use alloc::{boxed, collections, rc, vec::Vec}; - pub use core::{borrow, cell, cmp, convert, fmt, hash, iter, marker, ops, str, sync}; + pub use core::{ + borrow, cell, cmp, convert, fmt, hash, iter, marker, num, ops, str, string, sync, + }; pub use core2::{error, io}; } #[cfg(feature = "std")] @@ -126,7 +138,7 @@ pub mod maybestd { pub mod maybestd { pub use core2::{error, io}; pub use std::{ - borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, ops, rc, str, - sync, vec::Vec, + borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, num, ops, rc, str, + string, sync, vec::Vec, }; } diff --git a/src/multihash.rs b/src/multihash.rs index 0fb62c8..79a9d5b 100644 --- a/src/multihash.rs +++ b/src/multihash.rs @@ -1,5 +1,6 @@ use crate::dev::*; use macros::derive_more::From; +use maybestd::io; use multihash::Hasher; macro_rules! impl_multihasher { @@ -94,13 +95,13 @@ macro_rules! impl_multihasher { } } - impl std::io::Write for Multihash { - fn write(&mut self, buf: &[u8]) -> std::io::Result { + impl io::Write for Multihash { + fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf); Ok(buf.len()) } - fn flush(&mut self) -> std::io::Result<()> { + fn flush(&mut self) -> io::Result<()> { Ok(()) } } diff --git a/src/representation/mod.rs b/src/representation/mod.rs index e96c981..a66350d 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -14,7 +14,7 @@ mod strategies; use crate::dev::*; use downcast_rs::{impl_downcast, Downcast}; use macros::derive_more::From; -use maybestd::{fmt, str::FromStr}; +use maybestd::{fmt, marker::PhantomData, str::FromStr}; pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKind}; @@ -84,41 +84,22 @@ pub use strategies::*; // impl IsAny<{ Kind::Map.bits() }> for Kind {} // impl IsAny<{ Kind::Link.bits() }> for Kind {} +#[doc(hidden)] +pub struct Label { + label: Field<'static>, + _t: PhantomData, +} + /// /// -/// Some types have in-memory representations distinct from their IPLD representations: -/// - Links can map to types, so they can represent both CIDs and the underling types -/// - Signed/encrypted payloads can be further resolved into native types after verifying the signature/performing decryption -/// -/// -/// TODO? == what are the requirements? -/// - serialize a type to a block -/// - serialize an ipld as this type to a block -/// - deserialize a type from a block -/// - -/// - deserialize an ipld as this type from a block -/// - focus a type to a value (typed or ipld?) based on a selector -/// - ? call a closure on the selected type? -/// - transform a value within a type based on a selector (? and a closure ?) -/// - return a typed value or ipld? -/// -/// TODO? selection can only happen *accurately* against fully-resolved types and blocks -/// -/// TODO: what to impl? -/// - focus(&self, selector, context) -> Result -/// - patch(&mut self, selector, f: F, context) -> Result<()> -/// where F: Fn(&mut T, context); -/// - based on success of recursing, flags any link type as dirty -/// - flush(&self, context) -> Result -/// TODO? << other impls >> -/// - validate_selector(selector) -/// - TODO: ? returns a stateful Visitor + DeserializeSeed? -/// - derive Serialize -/// - in focus(...), impl Deserialize -/// - TODO: ? stateful visitor derived from selector + type? -/// - TODO: ? impl DeserializeSeed for selector? -/// - TODO: ? Representation::visitor(selector: &Selector) -// pub trait Representation: Sized { +// Some types have in-memory representations distinct from their IPLD representations: +// - Links can map to types, so they can represent both CIDs and the underling types +// - Signed/encrypted payloads can be further resolved into native types after verifying the signature/performing decryption +// +// - patch(&mut self, selector, f: F, context) -> Result<()> +// where F: Fn(&mut T, context); +// - based on success of recursing, flags any link type as dirty +// - flush(&self, context) -> Result pub trait Representation: Sized { /// The stringified name of the IPLD type. const NAME: &'static str; @@ -173,7 +154,7 @@ pub trait Representation: Sized { const HAS_LINKS: bool = Self::IS_LINK; /// The type's `Select`able static field names and their IPLD Schema kinds. - const FIELDS: &'static [(Field<'static>, Kind)] = &[]; + const FIELDS: &'static [()] = &[]; /// /// for unions, this ?should delegate to the variant's type name' @@ -345,14 +326,24 @@ pub trait Representation: Sized { /// pub trait StringRepresentation where - Self: Representation + Clone + fmt::Display + FromStr + Ord, + Self: Representation + + Clone + + fmt::Display + + FromStr + + Ord, { } impl StringRepresentation for T where - Self: Representation + Clone + fmt::Display + FromStr + Ord + T: Representation + + Clone + + fmt::Display + + FromStr + + Ord { } +trait AdvancedRepresentation: Representation + Select {} + /// /// TODO: possibly look at erased-serde to complete this "hack" pub(crate) trait ErasedRepresentation: Downcast { diff --git a/src/selectors/seed.rs b/src/selectors/seed.rs index 6a9e68d..bdb7087 100644 --- a/src/selectors/seed.rs +++ b/src/selectors/seed.rs @@ -47,37 +47,24 @@ pub type EmptySeed = SelectorSeed<'static, (), T>; /// A marked [`SelectorSeed`] that's aware of the codec of the block it's /// currenly selecting against. -#[doc(hidden)] +#[cfg_attr(not(feature = "dev"), doc(hidden))] #[derive(Debug)] -pub struct CodecSeed::ReprKind>( +pub struct CodecSeed::ReprKind>( pub(crate) S, PhantomData<(T, U, RK)>, ) where T: Representation, - U: Representation, RK: TypedKind; -impl CodecSeed { - // pub const RK: u32 = RK; - // pub const fn is_select() -> bool { - // (!RK) - // } - // pub const fn repr_kind() -> Kind { - // T::REPR_KIND - // } - // pub const fn schema_kind() -> Kind { - // T::SCHEMA_KIND - // } - +impl CodecSeed { + /// pub fn from(seed: S) -> Self { Self(seed, PhantomData) } - const fn repr_kind() -> Kind - where - T: Representation, - { + /// Normalizes the representation kind, if typed. + const fn repr_kind() -> Kind { if Kind::TypedInt.contains(T::REPR_KIND) { Int::REPR_KIND } else if Kind::TypedFloat.contains(T::REPR_KIND) { @@ -92,12 +79,12 @@ impl CodecSeed DeserializeSeed<'de> for CodecSeed where Self: Visitor<'de> + IpldVisitorExt<'de>, S: SeedType, T: Representation, - U: Representation, RK: TypedKind, { type Value = >::Value; @@ -107,38 +94,36 @@ where where De: Deserializer<'de>, { - use Kind as K; - if T::__IGNORED { return deserializer.deserialize_ignored_any(self); } match Self::repr_kind() { - K::Null => deserializer.deserialize_unit(self), - K::Bool => deserializer.deserialize_bool(self), - K::Int8 => deserializer.deserialize_i8(self), - K::Int16 => deserializer.deserialize_i16(self), - K::Int32 => deserializer.deserialize_i32(self), - K::Int64 => deserializer.deserialize_i64(self), - K::Int128 => deserializer.deserialize_i128(self), - K::Uint8 => deserializer.deserialize_u8(self), - K::Uint16 => deserializer.deserialize_u16(self), - K::Uint32 => deserializer.deserialize_u32(self), - K::Uint64 => deserializer.deserialize_u64(self), - K::Uint128 => deserializer.deserialize_u128(self), - K::Float32 => deserializer.deserialize_f32(self), - K::Float64 => deserializer.deserialize_f64(self), - K::String => deserializer.deserialize_str(self), - K::Bytes => { + Kind::Null => deserializer.deserialize_unit(self), + Kind::Bool => deserializer.deserialize_bool(self), + Kind::Int8 => deserializer.deserialize_i8(self), + Kind::Int16 => deserializer.deserialize_i16(self), + Kind::Int32 => deserializer.deserialize_i32(self), + Kind::Int64 => deserializer.deserialize_i64(self), + Kind::Int128 => deserializer.deserialize_i128(self), + Kind::Uint8 => deserializer.deserialize_u8(self), + Kind::Uint16 => deserializer.deserialize_u16(self), + Kind::Uint32 => deserializer.deserialize_u32(self), + Kind::Uint64 => deserializer.deserialize_u64(self), + Kind::Uint128 => deserializer.deserialize_u128(self), + Kind::Float32 => deserializer.deserialize_f32(self), + Kind::Float64 => deserializer.deserialize_f64(self), + Kind::String => deserializer.deserialize_str(self), + Kind::Bytes => { #[cfg(feature = "dag-json")] if C == DagJson::CODE { return DagJson::deserialize_bytes(deserializer, self); } deserializer.deserialize_bytes(self) } - K::List => deserializer.deserialize_seq(self), - K::Map => deserializer.deserialize_map(self), - K::Link => { + Kind::List => deserializer.deserialize_seq(self), + Kind::Map => deserializer.deserialize_map(self), + Kind::Link => { #[cfg(feature = "dag-json")] if C == DagJson::CODE { return DagJson::deserialize_cid(deserializer, self); @@ -178,46 +163,6 @@ impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { const CAN_SELECT: bool = true; } -impl<'a, const C: u64, Ctx, T> CodecSeed, T> -where - T: Representation, -{ - // /// - // #[inline] - // pub(crate) fn from_parts( - // selector: &'a Selector, - // state: &'a mut State, - // callback: Callback<'a, Ctx, T>, - // ctx: &'a mut Ctx, - // ) -> Self { - // Self( - // SelectorSeed { - // selector, - // state, - // callback, - // ctx, - // // visitor, - // // _t: PhantomData, - // }, - // PhantomData, - // ) - // } - - // /// - // #[inline] - // #[doc(hidden)] - // pub(crate) fn into_parts( - // self, - // ) -> ( - // &'a Selector, - // &'a mut State, - // Callback<'a, Ctx, T>, - // &'a mut Ctx, - // ) { - // (self.0.selector, self.0.state, self.0.callback, self.0.ctx) - // } -} - // impl<'de, const C: u64, T> CodecSeed, T> // // where // // Self: Visitor<'de>, @@ -262,77 +207,6 @@ where // } // } -// /// -// #[doc(hidden)] -// pub type CodedSelectorSeed<'a, const C: u64, Ctx, T> = -// CodecSeed, T>; - -// /// Replacement trait for [`serde::de::DeserializeSeed`], that allows us to -// /// switch deserialization behaviour based on the current block's [`Codec`]. -// /// -// /// How to use: -// /// ? implement this for SelectorSeed -// /// ? call the appropriate deserializer method for the codec -// /// ? pass itself as a visitor -// /// ? for compounds, create CodecSeed -// /// ? pass that as a seed -// #[doc(hidden)] -// pub trait CodecDeserializeSeed<'de> { -// type Value; -// // pub trait CodecDeserializeSeed<'de>: DeserializeSeed<'de, Value = ()> { -// fn deserialize(self, deserializer: RK) -> Result -// where -// // CodecSeed: DeserializeSeed<'de, Value = ()>, -// RK: Deserializer<'de>; -// // { -// // // CodecSeed::(self).deserialize(deserializer) -// // DeserializeSeed::<'_>::deserialize(self, deserializer) -// // } -// -// fn mode(&self) -> SelectionMode { -// unimplemented!() -// } -// -// // fn to_field_select_seed<'b, U>( -// // &mut self, -// // field: Field<'b>, -// // match_cb: Option, -// // post_cb: Option, -// // ) -> Result<(), Error> { -// // unimplemented!() -// // } -// } -// -// // impl<'de, T> CodecDeserializeSeed<'de> for PhantomData -// // where -// // T: Representation, -// // { -// // type Value = T; -// // -// // fn deserialize(self, deserializer: RK) -> Result -// // where -// // RK: Deserializer<'de>, -// // { -// // ::deserialize::(deserializer) -// // } -// // } -// // -// // impl<'a, 'de, Ctx, T> CodecDeserializeSeed<'de> for SelectorSeed<'a, Ctx, T> -// // // where -// // // CodecSeed: DeserializeSeed<'de, Value = ()>, -// // { -// // const RK: u32 = false; -// // type Value = (); -// // fn deserialize(self, deserializer: De) -> Result<(), De::Error> -// // where -// // // CodecSeed as CodecDeserializeSeed<'de>>::RK }, Self>: -// // // DeserializeSeed<'de, Value = ()>, -// // De: Deserializer<'de>, -// // { -// // CodecSeed::(self).deserialize(deserializer) -// // } -// // } - impl<'a, Ctx, T> fmt::Debug for SelectorSeed<'a, Ctx, T> where Ctx: Context, @@ -414,8 +288,8 @@ where pub fn wrap(self, conv: F) -> SelectorSeed<'a, Ctx, U> where Ctx: 'a, - U: Representation + 'static, T: 'static, + U: Representation + 'static, // T: From + 'static, F: Fn(U) -> T + Clone + 'a, { @@ -432,6 +306,29 @@ where ctx, } } + + // /// + // fn wrap_advanced(self, conv: F) -> SelectorSeed<'a, Ctx, U> + // where + // Ctx: 'a, + // T: 'static, + // U: Representation + 'static, + // // T: From + 'static, + // F: Fn(U) -> T + Clone + 'a, + // { + // let Self { + // selector, + // state, + // callback, + // ctx, + // } = self; + // SelectorSeed { + // selector, + // state, + // callback: callback.wrap::(conv), + // ctx, + // } + // } } // dag selection methods @@ -610,72 +507,11 @@ where /// Provides skeletons for conveniently implementing serde-compatibility for /// IPLD types. +#[doc(hidden)] #[macro_export] -macro_rules! impl_selector_seed_serde { - // visitor for CodedSeed - - // impl Visitor for CodedSeed - (@codec_seed_visitor - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ident $(< - // match one or more lifetimes separated by a comma - $( $ty_generics:ident ),+ - >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - Visitor<'de> for - CodecSeed<_C, - SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - $ty $(<$($ty_generics),+>)? - > - where - Ctx: Context, - $($bounds)* - { - type Value = (); - $($visit_fns)* - } - }; - - }; - // impl IpldVisitorExt for CodedSeed - (@codec_seed_visitor_ext - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ident $(< - // match one or more lifetimes separated by a comma - $( $ty_generics:ident ),+ - >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - const _RK: u32 = <$ty as Representation>::REPR_KIND.bits(); - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> - IpldVisitorExt<'de> for - CodecSeed<_C, - SelectorSeed<'_a, Ctx, $ty $(<$($ty_generics),+>)?>, - $ty $(<$($ty_generics),+>)? - > - where - Ctx: Context, - $($bounds)* - { - $($visit_fns)* - } - }; - }; - +macro_rules! repr_serde { // impl Visitor for CodedSeed by REPR_KIND - - (@codec_seed_visitor_rk $rk:ident $ty:ident $marker_ty:ty + (@visitor $ty:ident $marker_ty:ty { $($rk:tt)* } { $($generics:tt)* } { $($bounds:tt)* } // $ty:ident // $(< @@ -688,12 +524,15 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // #[doc(hidden)] + impl<'_a, 'de, const C: u64, Ctx, $($generics)*> Visitor<'de> for - CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty, $marker_ty, type_kinds::$rk> + CodecSeed, + $ty, $marker_ty, $($rk)*> where - $ty: Representation + Select, Ctx: Context, + $ty: Representation + Select, $($bounds)* { type Value = (); @@ -703,8 +542,8 @@ macro_rules! impl_selector_seed_serde { // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } }; - // impl Visitor for CodedSeed by REPR_KIND - (@codec_seed_visitor_ext_rk $rk:ident $ty:ident $marker_ty:ty + // impl IpldVisitorExt for CodedSeed by REPR_KIND + (@visitor_ext $ty:ident $marker_ty:ty { $($rk:tt)* } { $($generics:tt)* } { $($bounds:tt)* } // $ty:ident // $(< @@ -717,12 +556,15 @@ macro_rules! impl_selector_seed_serde { #[allow(unused_imports)] use $crate::dev::*; - impl<'_a, 'de, const _C: u64, Ctx, $($generics)*> + // #[doc(hidden)] + impl<'_a, 'de, const C: u64, Ctx, $($generics)*> IpldVisitorExt<'de> for - CodecSeed<_C, SelectorSeed<'_a, Ctx, $ty>, $ty, $marker_ty, type_kinds::$rk> + CodecSeed, + $ty, $marker_ty, $($rk)*> where - $ty: Representation + Select, Ctx: Context, + $ty: Representation + Select, $($bounds)* { $($visit_fns)* @@ -732,102 +574,106 @@ macro_rules! impl_selector_seed_serde { // Select - // impl Select for T, using the seed's select - (@selector_seed_select - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; + // impl Select for T, using the seed's select + (@select + $ty:ty => $marker_ty:ty + { $($generics:tt)* } { $($bounds:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; - impl Select for $ty + impl Select for $ty + where + Ctx: Context, + $($bounds)* + { + // #[inline] + // fn select( + // params: Params<'_, Ctx, Self>, + // ctx: &mut Ctx, + // ) -> Result<(), Error> { + // SelectorSeed::<'_, Ctx, Self>::select(params, ctx) + // } + + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> where - Ctx: Context, - $($bounds)* + D: Deserializer<'de>, { - // #[inline] - // fn select( - // params: Params<'_, Ctx, Self>, - // ctx: &mut Ctx, - // ) -> Result<(), Error> { - // SelectorSeed::<'_, Ctx, Self>::select(params, ctx) - // } - - #[doc(hidden)] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = CodecSeed::::from(seed); - seed.deserialize(deserializer) - } - - // #[doc(hidden)] - // fn __select_seq<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // mut seq: A, - // ) -> Result, A::Error> - // where - // A: SeqAccess<'de>, - // { - // let seed = CodecSeed::::from(seed); - // seq.next_element_seed(seed) - // } - - // #[doc(hidden)] - // fn __select_map<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // mut map: A, - // is_key: bool, - // ) -> Result, A::Error> - // where - // A: MapAccess<'de>, - // { - // let seed = CodecSeed::::from(seed); - // if is_key { - // map.next_key_seed(seed) - // } else { - // Ok(Some(map.next_value_seed(seed)?)) - // } - // } + let seed = CodecSeed::::from(seed); + seed.deserialize(deserializer) } - }; + + // #[doc(hidden)] + // #[inline] + // fn __select_seq<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // mut seq: A, + // ) -> Result, A::Error> + // where + // A: SeqAccess<'de>, + // { + // let seed = CodecSeed::::from(seed); + // seq.next_element_seed(seed) + // } + + // #[doc(hidden)] + // #[inline] + // fn __select_map<'a, 'de, const C: u64, A>( + // seed: SelectorSeed<'a, Ctx, Self>, + // mut map: A, + // is_key: bool, + // ) -> Result, A::Error> + // where + // A: MapAccess<'de>, + // { + // let seed = CodecSeed::::from(seed); + // if is_key { + // map.next_key_seed(seed) + // } else { + // Ok(Some(map.next_value_seed(seed)?)) + // } + // } + } + }; + }; + /* + (@seed_from_params $params:ident $ctx:ident) => {{ + let Params { + cid, + selector, + max_path_depth, + max_link_depth, + callback, + } = $params; + let mut state = State { + max_path_depth, + max_link_depth, + ..Default::default() }; - /* - (@seed_from_params $params:ident $ctx:ident) => {{ - let Params { - cid, - selector, - max_path_depth, - max_link_depth, - callback, - } = $params; - let mut state = State { - max_path_depth, - max_link_depth, - ..Default::default() - }; - let root = cid.ok_or_else(|| { - Error::InvalidSelectionParams("selection must start against some cid") - })?; - let block = $ctx.block_reader(&root)?; + let root = cid.ok_or_else(|| { + Error::InvalidSelectionParams("selection must start against some cid") + })?; + let block = $ctx.block_reader(&root)?; - let default_selector = Selector::DEFAULT; - SelectorSeed { - selector: &selector.unwrap_or(&default_selector), - state: &mut state, - callback, - ctx: &mut $ctx, - } - }}; - */ + let default_selector = Selector::DEFAULT; + SelectorSeed { + selector: &selector.unwrap_or(&default_selector), + state: &mut state, + callback, + ctx: &mut $ctx, + } + }}; + */ // newtype impls + (@select_newtype { $($generics:tt)* } { $($bounds:tt)* } $ty:ty { $constructor:expr => $inner_ty:ty } @@ -933,23 +779,23 @@ macro_rules! impl_selector_seed_serde { }} }; // produces an seed for the inner_ty, providing the original cb with ty - (@selector_seed_wrap $seed:ident { $constructor:expr => $inner_ty:ty }) => {{ - use $crate::dev::{DagSelection, Callback::*}; - - let SelectorSeed { selector, state, callback, ctx } = $seed.0; - let callback = match callback { - SelectDag { mut cb } => SelectDag { - cb: Box::new(move |selection, ctx| { - let inner_dag = selection.dag.downcast::<$inner_ty>()?; - let dag = $constructor(inner_dag.into()); - cb(DagSelection { dag: dag.into(), ..selection }, ctx) - }), - }, - cb => cb.clone(), - _ => unreachable!(), - }; - Self::from(SelectorSeed { selector, state, callback, ctx }) - }}; + // (@selector_seed_wrap $seed:ident { $constructor:expr => $inner_ty:ty }) => {{ + // use $crate::dev::{DagSelection, Callback::*}; + + // let SelectorSeed { selector, state, callback, ctx } = $seed.0; + // let callback = match callback { + // SelectDag { mut cb } => SelectDag { + // cb: Box::new(move |selection, ctx| { + // let inner_dag = selection.dag.downcast::<$inner_ty>()?; + // let dag = $constructor(inner_dag.into()); + // cb(DagSelection { dag: dag.into(), ..selection }, ctx) + // }), + // }, + // cb => cb.clone(), + // _ => unreachable!(), + // }; + // Self::from(SelectorSeed { selector, state, callback, ctx }) + // }}; // (@empty $seed:ident $constructor:expr => $inner_ty:tt) => { unimplemented!() }; // TODO: deprecate, since we want SelectorSeed to do all the heavy-lifting From 9f10ec9abc47a3c07308b6ec3ccbee5560b8c39f Mon Sep 17 00:00:00 2001 From: sunny-g Date: Fri, 14 Oct 2022 12:33:01 -0500 Subject: [PATCH 7/9] more updates --- Cargo.toml | 11 +- macros-internals/src/common.rs | 1 - macros-internals/src/lib.rs | 1 + macros-internals/src/schema/expand.rs | 11 +- macros-internals/src/schema/mod.rs | 150 +++--- .../src/schema/primitive/expand.rs | 75 ++- macros-internals/src/schema/struct/expand.rs | 12 +- .../src/schema/struct/expand_listpairs.rs | 9 +- .../src/schema/struct/expand_stringjoin.rs | 9 +- .../src/schema/struct/expand_stringpairs.rs | 9 +- .../src/schema/struct/expand_tuple.rs | 9 +- macros-internals/src/schema/union/expand.rs | 5 +- .../src/schema/union/expand_kinded.rs | 230 ++++----- macros-internals/src/schema/union/parse.rs | 5 +- src/cid.rs | 48 +- src/codecs/dag_cbor.rs | 23 +- src/codecs/dag_json.rs | 226 +++++---- src/codecs/mod.rs | 46 +- src/compat/core.rs | 83 +++- src/data_model/any.rs | 14 +- src/data_model/link.rs | 80 +-- src/data_model/list.rs | 127 ++++- src/data_model/map.rs | 78 +-- src/data_model/mod.rs | 4 +- src/data_model/primitive.rs | 230 +++++---- src/lib.rs | 49 +- src/multicodec.rs | 224 +++++++-- src/representation/mod.rs | 74 +-- src/representation/strategies/bytesprefix.rs | 3 + src/representation/strategies/listpairs.rs | 457 ++++++++++++++++++ src/representation/strategies/mod.rs | 219 +++++++++ src/representation/strategies/stringjoin.rs | 22 + src/representation/strategies/stringpairs.rs | 194 ++++++++ src/representation/strategies/stringprefix.rs | 3 + src/representation/strategies/tuple.rs | 412 ++++++++++++++++ src/{selectors => select}/context.rs | 2 +- src/{selectors => select}/mod.rs | 38 +- src/{selectors => select}/seed.rs | 348 +++++++++---- src/{selectors => select}/selectors.rs | 4 +- src/{selectors => select}/state.rs | 56 ++- src/selectors/path.rs | 31 -- src/selectors/str.rs | 1 - 42 files changed, 2770 insertions(+), 863 deletions(-) create mode 100644 src/representation/strategies/bytesprefix.rs create mode 100644 src/representation/strategies/listpairs.rs create mode 100644 src/representation/strategies/mod.rs create mode 100644 src/representation/strategies/stringjoin.rs create mode 100644 src/representation/strategies/stringpairs.rs create mode 100644 src/representation/strategies/stringprefix.rs create mode 100644 src/representation/strategies/tuple.rs rename src/{selectors => select}/context.rs (98%) rename src/{selectors => select}/mod.rs (97%) rename src/{selectors => select}/seed.rs (72%) rename src/{selectors => select}/selectors.rs (99%) rename src/{selectors => select}/state.rs (93%) delete mode 100644 src/selectors/path.rs delete mode 100644 src/selectors/str.rs diff --git a/Cargo.toml b/Cargo.toml index a8932bc..2868eb7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,10 +13,10 @@ path = "src/lib.rs" [dependencies] # core bytes = "1.2" -cid = { version = "0.8", features = ["alloc", "serde-codec"] } +cid = { version = "0.8", features = ["serde-codec"] } ipld-macros = { path = "./macros" } ipld-macros-internals = { path = "./macros-internals" } -multibase = "0.9" +multibase = { version = "0.9", default-features = false } multihash = { version = "0.16", default-features = false } serde = { version = "1.0", default-features = false, features = ["derive", "rc"] } # serde_repr = "0.1" @@ -34,7 +34,7 @@ serde_json = { version = "1.0", optional = true, features = ["float_roundtrip"] anyhow = "1.0" # const-str = "0.3" # const_format = "0.2" -core2 = { version = "0.4", optional = true } +core2 = { version = "0.4", default-features = false, optional = true } delegate = { version = "0.8", optional = true } downcast-rs = "1.2" @@ -43,8 +43,9 @@ downcast-rs = "1.2" # proptest = "1.0" [features] -default = ["multicodec", "std", "dev"] -std = ["cid/std", "core2/std", "multihash/std"] +default = ["multicodec", "alloc", "std", "dev"] +std = ["cid/std", "core2/std", "multibase/std", "multihash/std", "serde/std"] +alloc = ["cid/alloc", "serde/alloc"] # activate dev docs dev = [] diff --git a/macros-internals/src/common.rs b/macros-internals/src/common.rs index 148ef74..f967cdb 100644 --- a/macros-internals/src/common.rs +++ b/macros-internals/src/common.rs @@ -21,7 +21,6 @@ pub(crate) mod attr { pub(crate) const IPLD_CRATE_NAME: &'static str = "ipld"; pub(crate) const ATTR: &'static str = "ipld_attr"; - pub(crate) const INTERNAL: &'static str = "internal"; pub(crate) const TRY_FROM: &'static str = "try_from"; pub(crate) const WRAPPER: &'static str = "wrapper"; pub(crate) const SERDE: &'static str = "serde"; diff --git a/macros-internals/src/lib.rs b/macros-internals/src/lib.rs index 1bb505f..4b84ce9 100644 --- a/macros-internals/src/lib.rs +++ b/macros-internals/src/lib.rs @@ -5,6 +5,7 @@ pub mod selector; pub use schema::SchemaDefinition; pub use selector::{RootSelectorDefinition, SelectorDefinition}; +/// Convenient re-exports for development. pub mod dev { pub use crate::common::*; pub use crate::derive_newtype; diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index 0237f92..cf4ae7c 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -305,11 +305,12 @@ macro_rules! derive_newtype { $crate::dev::impl_repr( $meta, quote::quote! { + type DataModelKind = <#$inner_ty as Representation>::DataModelKind; + type SchemaKind = <#$inner_ty as Representation>::SchemaKind; type ReprKind = <#$inner_ty as Representation>::ReprKind; const DATA_MODEL_KIND: Kind = <#$inner_ty>::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = <#$inner_ty>::SCHEMA_KIND; - // const REPR_KIND: Kind = <#$inner_ty>::REPR_KIND; const IS_LINK: bool = <#$inner_ty>::IS_LINK; const HAS_LINKS: bool = <#$inner_ty>::HAS_LINKS; @@ -339,15 +340,17 @@ macro_rules! derive_newtype { let lib = &$meta.lib; let name = &$meta.name; quote::quote! { - // #lib::dev::macros::impl_selector_seed_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty + // #lib::dev::macros::repr_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty // } - // #lib::dev::macros::impl_selector_seed_serde! { + // #lib::dev::macros::repr_serde! { // @selector_seed_select {} {} #name // } - #lib::dev::macros::impl_selector_seed_serde! { + #lib::dev::macros::repr_serde! { @select_newtype {} {} #name { #name => #$inner_ty } } + + } }}; (@conv @has_constructor $def:ident, $meta:ident => diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index f4821a2..df8eedd 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -138,68 +138,39 @@ pub mod kind { /// /// TODO: BitAnd/BitOr dont work without fully-qualified syntax - pub trait TypedKind + pub trait TypedKind where - Self: NonZero - + Unsigned - // + IsLessOrEqual // TODO: replace with And: IsEqual, - // + BitAnd - // + BitAnd - + BitAnd - + BitAnd - + BitAnd - + BitAnd - // + BitAnd - // + BitAnd - + BitOr, + // TODO: replace with And: IsEqual + Self: NonZero + Unsigned + IsLessOrEqual, { - const KIND: SchemaKind; + const KIND: SchemaKind = SchemaKind::from_bits_truncate(Self::U32); // const IS_SCALAR: bool = SchemaKind::Scalar.contains(Self::KIND); // const IS_RECURSIVE: bool = SchemaKind::Recursive.contains(Self::KIND); - const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); + // const IS_DATA_MODEL: bool = SchemaKind::Any.contains(Self::KIND); // const IS_SCHEMA: bool = SchemaKind::Schema.contains(Self::KIND) || Self::IS_TYPED_NUM; // const IS_TYPED_NUM: bool = SchemaKind::TypedNum.contains(Self::KIND) && !Self::IS_VARIOUS; - const IS_VARIOUS: bool = !is_unary::(); + // const IS_VARIOUS: bool = !is_unary::(); } - impl TypedKind for T - where - T: NonZero - + Unsigned - // + IsLessOrEqual - // + BitAnd - // + BitAnd - + BitAnd - + BitAnd - + BitAnd - + BitAnd - // + BitAnd - // + BitAnd - + BitOr, - // And: IsEqual, + impl TypedKind for T where + T: NonZero + Unsigned + IsLessOrEqual // + BitAnd + // + BitAnd + // + BitAnd + // + BitAnd + // + BitAnd + // + BitAnd + // + BitAnd + // + BitAnd + // + BitOr, { - const KIND: SchemaKind = SchemaKind::from_bits_truncate(T::U32); } - // pub trait DataModelKind: TypedKind - // where - // And: IsEqual, - // { - // } - // impl DataModelKind for T - // where - // T: TypedKind, - // // T: IsLessOrEqual, - // // T: BitAnd, - // And: IsEqual, - // { - // } - macro_rules! def_kind { ( $($name:ident = $b:expr;)*) => { bitflags::bitflags! { - /// Enum of possible [Data Model](), [Schema]() and [Representation]() kinds. + /// Bitflag of possible [Data Model](), [Schema]() and [Representation]() kinds. /// + // #[derive(Debug)] #[repr(transparent)] pub struct SchemaKind: u32 { $( @@ -215,15 +186,14 @@ pub mod kind { | Self::Bytes.bits | Self::Link.bits; - /// Marker flag for scalar data model kinds. + /// Marker flag for recursive data model kinds. const Recursive = Self::List.bits | Self::Map.bits; /// Marker flag for any and all valid data model kinds. const Any = Self::Scalar.bits | Self::Recursive.bits; /// Marker flag for any data model or schema kind. - const Schema = Self::Any.bits - | Self::Struct.bits + const Schema = Self::Struct.bits | Self::Enum.bits | Self::Union.bits | Self::Copy.bits @@ -253,11 +223,10 @@ pub mod kind { } /// [`typenum`] types representing known [`SchemaKind`]s. - // #[macro_use] + /// + /// [`typenum`]: typenum pub mod type_kinds { use super::*; - // use typenum; - // use $crate::dev::typenum_macro; $(pub type $name = tyuint!($b);)* @@ -265,16 +234,20 @@ pub mod kind { pub type Scalar = op!(Null | Bool | Int | Float | String | Bytes | Link); pub type Recursive = op!(List | Map); - pub type Any = op!(Scalar | Recursive); - pub type Schema = op!(Any | Struct | Enum | Union | Copy | Advanced); - pub type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); - pub type TypedFloat = op!(Float32 | Float64); + // hack around type checking limitations that thwart blanket + // impls of Visitor for Any representations + pub type Any = U511; + assert_type_eq!(Any, op!(Scalar | Recursive)); + pub type Schema = op!(Struct | Enum | Union | Copy | Advanced); + + type TypedInt = op!(Int8 | Int16 | Int32 | Int64 | Int128 | Uint8 | Uint16 | Uint32 | Uint64 | Uint128); + type TypedFloat = op!(Float32 | Float64); pub type TypedScalar = op!(Scalar | TypedInt | TypedFloat); #[doc(hidden)] - pub type All = op!(Any | Schema | TypedInt | TypedFloat); + pub type All = op!(Any | Schema | TypedScalar); #[doc(hidden)] pub type Empty = U0; } @@ -316,34 +289,39 @@ pub mod kind { /// Const function for determining equality between [`Kind`]s. #[doc(hidden)] pub const fn eq(&self, other: &Self) -> bool { - match (*self, *other) { - (Self::Null, Self::Null) - | (Self::Bool, Self::Bool) - | (Self::Int, Self::Int) - | (Self::Int8, Self::Int8) - | (Self::Int16, Self::Int16) - | (Self::Int32, Self::Int32) - | (Self::Int64, Self::Int64) - | (Self::Int128, Self::Int128) - | (Self::Uint8, Self::Uint8) - | (Self::Uint16, Self::Uint16) - | (Self::Uint32, Self::Uint32) - | (Self::Uint64, Self::Uint64) - | (Self::Uint128, Self::Uint128) - | (Self::Float, Self::Float) - | (Self::Float32, Self::Float32) - | (Self::Float64, Self::Float64) - | (Self::String, Self::String) - | (Self::Bytes, Self::Bytes) - | (Self::List, Self::List) - | (Self::Map, Self::Map) - | (Self::Link, Self::Link) - | (Self::Struct, Self::Struct) - | (Self::Enum, Self::Enum) - | (Self::Union, Self::Union) - | (Self::Copy, Self::Copy) => true, - _ => false, - } + self.bits == other.bits + // match (*self, *other) { + // (Self::Null, Self::Null) + // | (Self::Bool, Self::Bool) + // | (Self::Int, Self::Int) + // | (Self::Int8, Self::Int8) + // | (Self::Int16, Self::Int16) + // | (Self::Int32, Self::Int32) + // | (Self::Int64, Self::Int64) + // | (Self::Int128, Self::Int128) + // | (Self::Uint8, Self::Uint8) + // | (Self::Uint16, Self::Uint16) + // | (Self::Uint32, Self::Uint32) + // | (Self::Uint64, Self::Uint64) + // | (Self::Uint128, Self::Uint128) + // | (Self::Float, Self::Float) + // | (Self::Float32, Self::Float32) + // | (Self::Float64, Self::Float64) + // | (Self::String, Self::String) + // | (Self::Bytes, Self::Bytes) + // | (Self::List, Self::List) + // | (Self::Map, Self::Map) + // | (Self::Link, Self::Link) + // | (Self::Struct, Self::Struct) + // | (Self::Enum, Self::Enum) + // | (Self::Union, Self::Union) + // | (Self::Copy, Self::Copy) => true, + // _ => false, + // } + } + + pub const fn is_option(&self) -> bool { + self.bits.count_ones() == 2 && self.contains(Self::Null) } /// diff --git a/macros-internals/src/schema/primitive/expand.rs b/macros-internals/src/schema/primitive/expand.rs index 36c0e85..8cf5214 100644 --- a/macros-internals/src/schema/primitive/expand.rs +++ b/macros-internals/src/schema/primitive/expand.rs @@ -78,31 +78,80 @@ macro_rules! derive_newtype_select { //////////////////////////////////////////////////////////////////////////////// impl NullReprDefinition { - fn inner_ty() -> Type { - Type::Verbatim(quote!(Null)) + fn ty(meta: &SchemaMeta) -> Type { + let name = &meta.name; + Type::Verbatim(quote!(#name)) } } impl expand::ExpandBasicRepresentation for NullReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { - let inner_ty = Self::inner_ty(); - derive_newtype!(@typedef self, meta => inner_ty) + let attrs = &meta.attrs; + let vis = &meta.vis; + let name = &meta.name; + let generics = &meta + .generics + .as_ref() + .map(|g| quote::quote!(#g)) + .unwrap_or_default(); + + quote::quote! { + #(#attrs)* + #vis struct #name #generics; + } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let name = &meta.name; - let inner_ty = Self::inner_ty(); - let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " null"); - }; - derive_newtype!(@repr { schema } meta => inner_ty) + crate::dev::impl_repr( + meta, + quote::quote! { + type DataModelKind = ::DataModelKind; + type SchemaKind = ::SchemaKind; + type ReprKind = ::ReprKind; + + const SCHEMA: &'static str = concat!("type ", stringify!(#name), " null"); + const DATA_MODEL_KIND: Kind = ::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = ::SCHEMA_KIND; + const IS_LINK: bool = ::IS_LINK; + const HAS_LINKS: bool = ::HAS_LINKS; + + #[inline] + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Representation::serialize::(&Null, serializer) + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Null::deserialize::(deserializer)?; + Ok(Self) + } + }, + ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { - let inner_ty = Self::inner_ty(); - derive_newtype!(@select meta => inner_ty) + let lib = &meta.lib; + let name = &meta.name; + quote::quote! { + #lib::dev::macros::repr_serde! { @select_for #name {} {} } + } } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { let name = &meta.name; quote! { + impl From<()> for #name { + fn from(_: ()) -> Self { + Self + } + } + impl From<#name> for SelectedNode { fn from(t: #name) -> Self { Self::Null @@ -119,7 +168,7 @@ impl expand::ExpandBasicRepresentation for NullReprDefinition { type Error = Error; fn try_from(any: Any) -> Result { match any { - Any::Null(inner) => Ok(Self(inner)), + Any::Null(inner) => Ok(Self), _ => Err(Error::MismatchedAny) } } @@ -132,7 +181,7 @@ impl expand::ExpandBasicRepresentation for NullReprDefinition { impl BoolReprDefinition { fn inner_ty() -> Type { - Type::Verbatim(quote!(Bool)) + Type::Verbatim(quote!(bool)) } } diff --git a/macros-internals/src/schema/struct/expand.rs b/macros-internals/src/schema/struct/expand.rs index fbc70a9..cc02182 100644 --- a/macros-internals/src/schema/struct/expand.rs +++ b/macros-internals/src/schema/struct/expand.rs @@ -3,7 +3,7 @@ use crate::dev::{ schema::expand::{self, ExpandAdvancedRepresentation, ExpandBasicRepresentation}, SchemaKind, SchemaMeta, }; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_quote, Type}; @@ -93,7 +93,7 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - impl_repr(self, meta, &Self::dm_kind()) + impl_repr(self, meta, &Self::dm_kind(), None) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() @@ -113,9 +113,12 @@ pub(super) fn impl_repr<'a, D: Deref>( fields: &D, meta: &SchemaMeta, repr_kind: &Ident, + repr_strategy: Option, ) -> TokenStream { let lib = &meta.lib; let name = &meta.name; + let repr_strategy = + repr_strategy.map(|strategy| quote!(const REPR_STRATEGY: Strategy = Strategy::#strategy;)); // let fields = iter.map(|f| { // let key = f.key.to_string(); // let val = &f.value; @@ -132,12 +135,15 @@ pub(super) fn impl_repr<'a, D: Deref>( let repr_body = expand::impl_repr( meta, quote! { + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Struct; type ReprKind = type_kinds::#repr_kind; const SCHEMA: &'static str = ""; const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Struct; - // const REPR_KIND: Kind = Kind::#repr_kind; + const REPR_KIND: Kind = Kind::#repr_kind; + #repr_strategy // const FIELDS: Fields = Fields::Struct(&[#(#fields,)*]); }, ); diff --git a/macros-internals/src/schema/struct/expand_listpairs.rs b/macros-internals/src/schema/struct/expand_listpairs.rs index f3673e9..d3d68f0 100644 --- a/macros-internals/src/schema/struct/expand_listpairs.rs +++ b/macros-internals/src/schema/struct/expand_listpairs.rs @@ -6,7 +6,7 @@ use crate::{ }, schema::SchemaKind, }; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_quote, Type}; @@ -29,7 +29,12 @@ impl ExpandBasicRepresentation for ListpairsStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self, meta, &SchemaKind::List.data_model_kind()) + super::expand::impl_repr( + self, + meta, + &SchemaKind::List.data_model_kind(), + Some(Ident::new("ListPairs", Span::call_site())), + ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_stringjoin.rs b/macros-internals/src/schema/struct/expand_stringjoin.rs index 21b4551..61779b2 100644 --- a/macros-internals/src/schema/struct/expand_stringjoin.rs +++ b/macros-internals/src/schema/struct/expand_stringjoin.rs @@ -6,7 +6,7 @@ use crate::{ }, schema::SchemaKind, }; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_quote, Type}; @@ -30,7 +30,12 @@ impl ExpandBasicRepresentation for StringjoinStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self, meta, &SchemaKind::String.data_model_kind()) + super::expand::impl_repr( + self, + meta, + &SchemaKind::String.data_model_kind(), + Some(Ident::new("StringJoin", Span::call_site())), + ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_stringpairs.rs b/macros-internals/src/schema/struct/expand_stringpairs.rs index d1b7f59..263d012 100644 --- a/macros-internals/src/schema/struct/expand_stringpairs.rs +++ b/macros-internals/src/schema/struct/expand_stringpairs.rs @@ -6,7 +6,7 @@ use crate::{ }, schema::SchemaKind, }; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_quote, Type}; @@ -30,7 +30,12 @@ impl ExpandBasicRepresentation for StringpairsStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self, meta, &SchemaKind::String.data_model_kind()) + super::expand::impl_repr( + self, + meta, + &SchemaKind::String.data_model_kind(), + Some(Ident::new("StringPairs", Span::call_site())), + ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/struct/expand_tuple.rs b/macros-internals/src/schema/struct/expand_tuple.rs index 5c11141..fa45034 100644 --- a/macros-internals/src/schema/struct/expand_tuple.rs +++ b/macros-internals/src/schema/struct/expand_tuple.rs @@ -6,7 +6,7 @@ use crate::{ }, schema::SchemaKind, }; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_quote, Type}; @@ -30,7 +30,12 @@ impl ExpandBasicRepresentation for TupleStructReprDefinition { TokenStream::default() } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - super::expand::impl_repr(self, meta, &SchemaKind::List.data_model_kind()) + super::expand::impl_repr( + self, + meta, + &SchemaKind::List.data_model_kind(), + Some(Ident::new("Tuple", Span::call_site())), + ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { TokenStream::default() diff --git a/macros-internals/src/schema/union/expand.rs b/macros-internals/src/schema/union/expand.rs index aad6efe..66eb444 100644 --- a/macros-internals/src/schema/union/expand.rs +++ b/macros-internals/src/schema/union/expand.rs @@ -76,12 +76,15 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { expand::impl_repr( meta, quote! { + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Union; type ReprKind = type_kinds::Map; const SCHEMA: &'static str = ""; const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Union; - // const REPR_KIND: Kind = unimplemented!(); + const REPR_KIND: Kind = Kind::Map; + const REPR_STRATEGY: Strategy = Strategy::Keyed; // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); #[inline] diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index 06c5432..a168b90 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -1,10 +1,7 @@ use super::*; -use crate::dev::{ - schema::{ - expand::{self, ExpandBasicRepresentation}, - kw, SchemaKind, - }, - SchemaMeta, +use crate::dev::schema::{ + expand::{impl_repr, ExpandBasicRepresentation}, + SchemaKind, SchemaMeta, }; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; @@ -29,22 +26,30 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let dm_kind = self.dm_kind(); - let repr_kind = self.repr_kind(); + let name = &meta.name; + let dm_ty = self.dm_ty(); + // let repr_kind = self.repr_kind(); let name_branches = self.iter().map(UnionKindedField::name_branch); // let kind_branches: Vec = self.iter().map(|f| f.kind_branch(&lib)).collect(); let serialize_branches = self.iter().map(UnionKindedField::serialize_branch); // let deserialize_branches = self.iter().map(UnionKindedField::deserialize_branch); - expand::impl_repr( + let non_link_visitors = self.visitors(meta, false, false); + let link_visitors = self.visitors(meta, true, false); + impl_repr( meta, quote! { - type ReprKind = #repr_kind; + type DataModelKind = #dm_ty; + type SchemaKind = type_kinds::Union; + // FIXME: + // cannot be the literal union of the types, as that + // confuses the type checker + type ReprKind = type_kinds::Any; const SCHEMA: &'static str = ""; - const DATA_MODEL_KIND: Kind = #dm_kind; + const DATA_MODEL_KIND: Kind = <#dm_ty>::KIND; const SCHEMA_KIND: Kind = Kind::Union; - // const REPR_KIND: Kind = #repr_kind; + const REPR_KIND: Kind = type_kinds::Any::KIND; // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); #[inline] @@ -76,7 +81,20 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { where D: Deserializer<'de>, { - unimplemented!() + struct KindedVisitor; + impl<'de, const C: u64> Visitor<'de> for KindedVisitor { + type Value = #name; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", stringify!(#name)) + } + #(#non_link_visitors)* + } + impl<'de, const C: u64> LinkVisitor<'de> for KindedVisitor { + #(#link_visitors)* + } + + Multicodec::deserialize_any::(deserializer, KindedVisitor::) } }, ) @@ -85,66 +103,32 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let lib = &meta.lib; let name = &meta.name; - let non_link_visitors = self - .iter() - .filter(|f| f.key != SchemaKind::Link) - .map(|f| f.visit_fn(meta)) - .flatten(); - let link_visitors = self - .iter() - .filter(|f| f.key == SchemaKind::Link) - .map(|f| f.visit_fn(meta)) - .flatten(); + let dm_ty = self.dm_ty(); + let non_link_visitors = self.visitors(meta, false, true); + let link_visitors = self.visitors(meta, true, true); + + // TODO: add a method that does the delegation to the variant, rather than codegen each quote! { - // TODO: add a method that does the delegation to the variant, rather than codegen each - // - // impl<'a, C: Context> ContextSeed<'a, C, #name> { - // fn visit_primitive(self, v: V) -> Result<(), E> - // where - // V: serde::de::IntoDeserializer, - // E: serde::de::Error, - // { - // let seed = #lib::dev::macros::impl_selector_seed_serde! { - // @selector_seed_wrap - // self #constructor => #ty - // }; - // seed.deserialize(v.into_deserializer()) - // } - // - // fn visit_list(self, v: V) -> Result<(), A::Error> - // where - // A: serde::de::SeqAccess, - // { - // let seed = #lib::dev::macros::impl_selector_seed_serde! { - // @selector_seed_wrap - // self #constructor => #ty - // }; - // seed.deserialize(v.into_deserializer()) - // } - // } - - // #lib::dev::macros::impl_selector_seed_serde! { - // @codec_seed_visitor {} {} #name - // { - // #[inline] - // fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // write!(f, "A `{}`", <#name as Representation>::NAME) - // } - - // #(#non_link_visitors)* - // }} - // #lib::dev::macros::impl_selector_seed_serde! { - // @codec_seed_visitor_ext {} {} #name - // { - // #(#link_visitors)* - // }} - // #lib::dev::macros::impl_selector_seed_serde! { - // @selector_seed_codec_deseed @any {} {} #name - // } - // #lib::dev::macros::impl_selector_seed_serde! { - // @selector_seed_select {} {} #name - // } + #lib::dev::macros::repr_serde! { @visitors for #name => #name + { @dk (#dm_ty) @sk (type_kinds::Union) @rk (type_kinds::Any) } + {} {} + @serde { + #[inline] + fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { + write!(f, "A `{}`", <#name as Representation>::NAME) + } + #(#non_link_visitors)* + } + @link { + #(#link_visitors)* + } + } + + #lib::dev::macros::repr_serde! { @select_for #name => #name + { @dk (#dm_ty) @sk (type_kinds::Union) @rk (type_kinds::Any) } + {} {} + } } } @@ -154,18 +138,37 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { } impl KindedUnionReprDefinition { - fn dm_kind(&self) -> TokenStream { - self.iter() - .map(|f| f.dm_kind()) - .fold(quote!(Kind::empty()), |ts, kind| quote!(#ts.union(#kind))) - } - - fn repr_kind(&self) -> TokenStream { - self.iter().map(|f| f.repr_kind()).fold( + // TODO: should be the union of all the actual type's data models (since they may not be the standard) + // fn dm_kind(&self) -> TokenStream { + // self.iter() + // .map(|f| f.dm_kind()) + // .fold(quote!(Kind::empty()), |ts, kind| quote!(#ts.union(#kind))) + // } + + fn dm_ty(&self) -> TokenStream { + self.iter().map(|f| f.ty(true)).fold( quote!(type_kinds::Empty), - |ts, kind| quote!(typenum::Or<#ts, #kind>), + |ts, ty| quote!(typenum::Or<#ts, <#ty as Representation>::DataModelKind>), ) } + + fn visitors<'a>( + &'a self, + meta: &'a SchemaMeta, + for_link: bool, + for_seed: bool, + ) -> impl Iterator + 'a { + self.iter() + .filter(move |f| { + if for_link { + f.key == SchemaKind::Link + } else { + f.key != SchemaKind::Link + } + }) + .map(move |f| f.visit_fn(meta, for_seed)) + .flatten() + } } impl UnionKindedField { @@ -190,21 +193,6 @@ impl UnionKindedField { } } - fn repr_kind(&self) -> TokenStream { - match self.key { - SchemaKind::Null => quote!(type_kinds::Null), - SchemaKind::Bool => quote!(type_kinds::Bool), - SchemaKind::Int => quote!(type_kinds::Int), - SchemaKind::Float => quote!(type_kinds::Float), - SchemaKind::String => quote!(type_kinds::String), - SchemaKind::Bytes => quote!(type_kinds::Bytes), - SchemaKind::List => quote!(type_kinds::List), - SchemaKind::Map => quote!(type_kinds::Map), - SchemaKind::Link => quote!(type_kinds::Link), - _ => unreachable!(), - } - } - fn ty(&self, with_wrapper: bool) -> TokenStream { let generics = &self.generics; let ty = match self.key { @@ -268,13 +256,12 @@ impl UnionKindedField { fn serialize_branch(&self) -> TokenStream { let name = self.name(); - // let ty = &self.value; quote!(Self::#name(ty) => Representation::serialize::(ty, serializer)) } } impl UnionKindedField { - fn visit_params(&self) -> Vec<(TokenStream, TokenStream)> { + fn visit_parts(&self) -> Vec<(TokenStream, TokenStream)> { match self.key { SchemaKind::Null => vec![ (quote!(visit_unit), quote!()), @@ -298,54 +285,69 @@ impl UnionKindedField { (quote!(visit_f64), quote!(v: f64)), ], SchemaKind::Bytes => vec![ + (quote!(visit_borrowed_bytes), quote!(v: &'de [u8])), (quote!(visit_bytes), quote!(v: &[u8])), (quote!(visit_byte_buf), quote!(v: Vec)), ], SchemaKind::String => vec![ + (quote!(visit_borrowed_str), quote!(v: &'de str)), (quote!(visit_str), quote!(v: &str)), (quote!(visit_string), quote!(v: String)), ], SchemaKind::List => vec![(quote!(visit_seq), quote!(v: A))], SchemaKind::Map => vec![(quote!(visit_map), quote!(v: A))], SchemaKind::Link => vec![ - // (quote!(visit_link_bytes), quote!(v: &[u8])), - // (quote!(visit_link_str), quote!(v: &str)), - (quote!(visit_cid), quote!(v: Cid)), + (quote!(visit_link_borrowed_bytes), quote!(v: &'de [u8])), + (quote!(visit_link_bytes), quote!(v: &[u8])), + (quote!(visit_link_borrowed_str), quote!(v: &'de str)), + (quote!(visit_link_str), quote!(v: &str)), + // TODO: provide an impl for this + // (quote!(visit_link), quote!(v: Cid)), ], _ => unreachable!(), } } - fn visit_fn(&self, meta: &SchemaMeta) -> impl Iterator + '_ { - let lib = &meta.lib; + // TODO: potentially inefficient handling of borrowed/owned strs and bytes + fn visit_fn( + &self, + meta: &SchemaMeta, + for_seed: bool, + ) -> impl Iterator + '_ { let name = &meta.name; let field_name = self.name(); let ty = self.ty(false); let visit_impl = { + // TODO: match key's REPR_KIND let deserializer = match self.key { SchemaKind::Null => quote!(().into_deserializer()), + SchemaKind::String => quote!(serde::de::value::CowStrDeserializer::new(v.into())), SchemaKind::Bytes => quote!(serde::de::value::BytesDeserializer::new(&v)), SchemaKind::List => quote!(serde::de::value::SeqAccessDeserializer::::new(v)), SchemaKind::Map => quote!(serde::de::value::MapAccessDeserializer::::new(v)), _ => quote!(v.into_deserializer()), }; - quote! { - // let seed = #lib::dev::macros::impl_selector_seed_serde! { - // @selector_seed_wrap - // self { #name::#field_name => #ty } - // }; - // seed.deserialize::(#deserializer) - unimplemented!() + if for_seed { + quote! { + let seed = self.0 + .wrap::<#ty, _>(|dag| #name::#field_name(dag.into())); + <#ty>::__select_de::(seed, #deserializer) + } + } else { + quote! { + let inner = <#ty as Representation>::deserialize::(#deserializer)?; + Ok(#name::#field_name(inner.into())) + } } }; - self.visit_params() + self.visit_parts() .into_iter() .map(move |(visit_fn, args)| match self.key { SchemaKind::List => quote! { #[inline] - fn #visit_fn(self, #args) -> Result + fn #visit_fn(mut self, #args) -> Result where A: serde::de::SeqAccess<'de> { @@ -354,7 +356,7 @@ impl UnionKindedField { }, SchemaKind::Map => quote! { #[inline] - fn #visit_fn(self, #args) -> Result + fn #visit_fn(mut self, #args) -> Result where A: serde::de::MapAccess<'de> { @@ -363,7 +365,7 @@ impl UnionKindedField { }, _ => quote! { #[inline] - fn #visit_fn(self, #args) -> Result + fn #visit_fn(mut self, #args) -> Result where E: serde::de::Error { @@ -373,5 +375,3 @@ impl UnionKindedField { }) } } - -impl SchemaKind {} diff --git a/macros-internals/src/schema/union/parse.rs b/macros-internals/src/schema/union/parse.rs index 0fe2989..2562a63 100644 --- a/macros-internals/src/schema/union/parse.rs +++ b/macros-internals/src/schema/union/parse.rs @@ -50,6 +50,7 @@ impl Parse for UnionReprDefinition { }) } // inline + // TODO: assert all field ty REPR_KINDs are Maps _ if input.peek(kw::inline) => { input.parse::()?; let fields = field_input.parse()?; @@ -64,18 +65,20 @@ impl Parse for UnionReprDefinition { }) } // byteprefix + // TODO: assert all field ty REPR_KINDs are Bytes _ if input.peek(kw::byteprefix) => { input.parse::()?; let fields = field_input.parse()?; - // TODO: assert that all field types are Bytes Self::BytePrefix(BytePrefixUnionReprDefinition { fields }) } // kinded + // TODO: assert all field ty REPR_KINDs are unique _ if input.peek(kw::kinded) => { input.parse::()?; let fields = field_input.parse::()?; // validate that all the kinds are of the data model and unique + // TODO: should validate that all are unique representation kinds let all = &fields .iter() .map(|fs| fs.key) diff --git a/src/cid.rs b/src/cid.rs index b8c8220..22a1ed2 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -1,4 +1,4 @@ -use crate::dev::{macros::*, *}; +use crate::dev::*; use cid::Error as CidError; use maybestd::{cmp, convert::TryFrom, fmt, hash, io, str::FromStr}; use multibase::Error as MultibaseError; @@ -6,7 +6,7 @@ use multibase::Error as MultibaseError; /// #[derive(Copy, Clone, Debug, Eq)] pub struct Cid { - inner: cid::CidGeneric<{ Self::SIZE }>, + pub(crate) inner: cid::CidGeneric<{ Self::SIZE }>, multibase: Multibase, } @@ -144,11 +144,15 @@ impl Cid { } impl Representation for Cid { + type DataModelKind = type_kinds::Link; + type SchemaKind = type_kinds::Link; type ReprKind = type_kinds::Link; const NAME: &'static str = "Cid"; const SCHEMA: &'static str = "type Cid &Any"; const DATA_MODEL_KIND: Kind = Kind::Link; + const SCHEMA_KIND: Kind = Kind::Link; + const REPR_KIND: Kind = Kind::Link; /// #[inline] @@ -156,16 +160,7 @@ impl Representation for Cid { where S: Serializer, { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::serialize_cid(self, serializer); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::serialize_cid(self, serializer); - } - - Serialize::serialize(&self.inner, serializer) + Multicodec::serialize_link::(self, serializer) } /// @@ -181,8 +176,22 @@ impl Representation for Cid { fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "a Cid containing a Multihash of max {} bytes", Cid::SIZE) } + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + self.visit_link_bytes(bytes) + } + #[inline] + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + self.visit_link_str(s) + } } - impl<'de> IpldVisitorExt<'de> for CidVisitor { + impl<'de> LinkVisitor<'de> for CidVisitor { #[inline] fn visit_cid(self, cid: Cid) -> Result where @@ -192,16 +201,11 @@ impl Representation for Cid { } } - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_cid(deserializer, CidVisitor); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::deserialize_cid(deserializer, CidVisitor); + if Multicodec::is_known::() { + Multicodec::deserialize_link::(deserializer, CidVisitor) + } else { + Ok(Self::from(Deserialize::deserialize(deserializer)?)) } - - Ok(Self::from(Deserialize::deserialize(deserializer)?)) } } diff --git a/src/codecs/dag_cbor.rs b/src/codecs/dag_cbor.rs index 2db62c6..52af964 100644 --- a/src/codecs/dag_cbor.rs +++ b/src/codecs/dag_cbor.rs @@ -17,7 +17,7 @@ use serde_cbor::{ // serde::{Deserializer as CborDeserializer, Serializer as CborSerializer}, // }; use delegate::delegate; -use std::{ +use maybestd::{ borrow::Cow, convert::TryFrom, fmt, @@ -29,9 +29,6 @@ use std::{ pub struct DagCbor; impl DagCbor { - /// The multicodec code that identifies this IPLD Codec. - pub const CODE: u64 = 0x71; - /// The special tag signifying an IPLD link. pub const LINK_TAG: u64 = 42; @@ -43,7 +40,7 @@ impl DagCbor { /// #[inline] - pub(crate) fn serialize_cid( + pub(crate) fn serialize_link( cid: &Cid, serializer: S, ) -> Result { @@ -60,7 +57,7 @@ impl DagCbor { ) -> Result where D: Deserializer<'de>, - V: IpldVisitorExt<'de>, + V: LinkVisitor<'de>, { // deserializer.deserialize_any(DagCborVisitor::<'a', _>(visitor)) unimplemented!() @@ -68,13 +65,13 @@ impl DagCbor { /// #[inline] - pub(crate) fn deserialize_cid<'de, D, V>( + pub(crate) fn deserialize_link<'de, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: IpldVisitorExt<'de>, + V: LinkVisitor<'de>, { match Tagged::<&'de [u8]>::deserialize(deserializer)? { Tagged { @@ -145,6 +142,9 @@ impl DagCbor { } impl Codec for DagCbor { + const NAME: &'static str = "dag-cbor"; + const CODE: u64 = 0x71; + fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> where T: Representation, @@ -286,7 +286,7 @@ mod tag { // visitor for links // TODO: does not work, as Cids are tagged differently than bytes - impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagCborVisitor<'l', V> { + impl<'de, V: LinkVisitor<'de>> Visitor<'de> for DagCborVisitor<'l', V> { type Value = V::Value; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A tagged Cid") @@ -313,7 +313,8 @@ mod tag { #[cfg(test)] mod tests { - use crate::{codecs_::test_utils::*, prelude::*}; + use super::super::test_utils::*; + use crate::prelude::*; #[test] fn test_null() { @@ -345,7 +346,7 @@ mod tests { // floats let cases = &[(4000.5f32, b"\xfb\x40\xaf\x41\x00\x00\x00\x00\x00".as_ref())]; - roundtrip_bytes_codec::(DagCbor::CODE, cases); + roundtrip_bytes_codec::(DagCbor::CODE, cases); let cases = &[(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a".as_ref())]; roundtrip_bytes_codec::(DagCbor::CODE, cases); } diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index 15f5bcc..29d99ff 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -4,10 +4,10 @@ use crate::dev::*; use delegate::delegate; use serde::{de, ser}; #[cfg(not(feature = "simd"))] -use serde_json::{de::IoRead, Deserializer as JsonDeserializer, Serializer as JsonSerializer}; +use serde_json::{Deserializer as JsonDeserializer, Serializer as JsonSerializer}; // #[cfg(feature = "simd")] // use simd_json::{Serializer as JsonSerializer, Deserializer as JsonDeserializer, Error as JsonError}; -use std::{ +use maybestd::{ borrow::Cow, convert::TryFrom, fmt, @@ -21,12 +21,9 @@ use std::{ pub struct DagJson; impl DagJson { - /// The multicodec code that identifies this IPLD Codec. - pub const CODE: u64 = 0x0129; - /// All bytes are encoded with the multibase `base64` w/o padding, resulting /// in the prefix `"m"`. - pub const DEFAULT_MULTIBASE: Multibase = Multibase::Base64; + pub const MB_BYTES: Multibase = Multibase::Base64; /// The map key marking the map value as IPLD bytes or an IPLD link. pub const IPLD_KEY: &'static str = "/"; @@ -37,8 +34,8 @@ impl DagJson { Self } - /// Serializes bytes as a struct variant, e.g. - /// `{ "/": { "base64": } }`. + /// Serializes bytes as a struct variant, e.g. `{ "/": { "bytes": + /// } }`. #[inline] pub(crate) fn serialize_bytes( bytes: impl AsRef<[u8]>, @@ -47,13 +44,14 @@ impl DagJson { use ser::SerializeStructVariant; let mut sv = serializer.serialize_struct_variant("", 0, Self::IPLD_KEY, 1)?; - sv.serialize_field("bytes", &multibase::encode(Self::DEFAULT_MULTIBASE, bytes))?; + sv.serialize_field("bytes", &multibase::encode(Self::MB_BYTES, bytes))?; sv.end() } - /// Serializes links as a newtype variant, e.g. `{ "/": "Qm..." }`. + /// Serializes links as a newtype variant, e.g. `{ "/": + /// }`. #[inline] - pub(crate) fn serialize_cid( + pub(crate) fn serialize_link( cid: &Cid, serializer: S, ) -> Result { @@ -70,9 +68,9 @@ impl DagJson { ) -> Result where D: Deserializer<'de>, - V: IpldVisitorExt<'de>, + V: LinkVisitor<'de>, { - deserializer.deserialize_any(visitor::DagJsonVisitor::<'a', _>(visitor)) + deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } /// @@ -82,23 +80,23 @@ impl DagJson { visitor: V, ) -> Result where - V: Visitor<'de>, D: Deserializer<'de>, + V: LinkVisitor<'de>, { - deserializer.deserialize_map(visitor::DagJsonVisitor::<'b', _>(visitor)) + deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } /// #[inline] - pub(crate) fn deserialize_cid<'de, D, V>( + pub(crate) fn deserialize_link<'de, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: IpldVisitorExt<'de>, + V: LinkVisitor<'de>, { - deserializer.deserialize_map(visitor::DagJsonVisitor::<'l', _>(visitor)) + deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } #[doc(hidden)] @@ -115,6 +113,9 @@ impl DagJson { } impl Codec for DagJson { + const NAME: &'static str = "dag-json"; + const CODE: u64 = 0x0129; + fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> where T: Representation, @@ -156,10 +157,10 @@ mod visitor { use super::*; #[derive(Debug)] - pub(crate) struct DagJsonVisitor(pub(crate) V); + pub(crate) struct DagJsonVisitor(pub(crate) V); // visitor for any - impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagJsonVisitor<'a', V> { + impl<'de, V: LinkVisitor<'de>> Visitor<'de> for DagJsonVisitor { type Value = V::Value; #[inline] fn visit_map(self, mut map: A) -> Result @@ -217,62 +218,6 @@ mod visitor { } } - // visitor for bytes - impl<'de, V: Visitor<'de>> Visitor<'de> for DagJsonVisitor<'b', V> { - type Value = V::Value; - - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("a map containing a byte string") - } - - #[inline] - fn visit_map(self, mut map: A) -> Result - where - A: de::MapAccess<'de>, - { - map.next_key::>()? - .filter(|key| key == DagJson::IPLD_KEY) - .ok_or_else(|| A::Error::custom("expected a \"/\" map key"))?; - - match map.next_value::>()? { - MapLikeVisitor::Bytes(b) => self.0.visit_byte_buf(b), - _ => Err(A::Error::custom("expected a byte string")), - } - } - } - - // visitor for links - impl<'de, V: IpldVisitorExt<'de>> Visitor<'de> for DagJsonVisitor<'l', V> { - type Value = V::Value; - - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("a map containing a Cid") - } - - #[inline] - fn visit_map(self, mut map: A) -> Result - where - A: de::MapAccess<'de>, - { - map.next_key::>()? - .filter(|key| key == DagJson::IPLD_KEY) - .ok_or_else(|| { - A::Error::custom(format!( - "expected the special IPLD map key {}", - DagJson::IPLD_KEY - )) - })?; - - match map.next_value::>()? { - MapLikeVisitor::CidStr(s) => self.0.visit_link_str(s), - MapLikeVisitor::CidString(s) => self.0.visit_link_str(&s), - _ => Err(A::Error::custom("expected a Cid")), - } - } - } - /**************************************************************************/ /**************************************************************************/ @@ -347,7 +292,7 @@ mod visitor { // .next_value_seed(DeserializeWrapper::<{ DagJson::CODE }, IpldString>::default())?; let byte_str = map.next_value::>()?; match multibase::decode(byte_str) { - Ok((DagJson::DEFAULT_MULTIBASE, bytes)) => Ok(MapLikeVisitor::Bytes(bytes)), + Ok((DagJson::MB_BYTES, bytes)) => Ok(MapLikeVisitor::Bytes(bytes)), // Ok((mb, _)) => Err(de::Error::custom(format!( // "DagJSON only supports bytes as base64-encoded strings, found multibase {:?}", // mb @@ -394,7 +339,8 @@ mod visitor { #[cfg(test)] mod tests { - use crate::{codecs_::test_utils::*, prelude::*}; + use super::super::test_utils::*; + use crate::prelude::*; #[test] fn test_null() { @@ -402,23 +348,42 @@ mod tests { roundtrip_str_codec::(DagJson::CODE, cases); let cases = &[(None as Option, "null")]; roundtrip_str_codec::>(DagJson::CODE, cases); + + let cases = &[(Any::Null(Null), "null")]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_bool() { let cases = &[(true, "true"), (false, "false")]; roundtrip_str_codec::(DagJson::CODE, cases); + + let cases = &[(Any::Bool(true), "true"), (Any::Bool(false), "false")]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] fn test_number() { // ints - let cases = &[(123, "123"), (65535, "65535")]; + let cases = &[ + (123, "123"), + (65535, "65535"), + (i64::MAX, &i64::MAX.to_string()), + ]; roundtrip_str_codec::(DagJson::CODE, cases); // floats let cases = &[(123.123, "123.123")]; roundtrip_str_codec::(DagJson::CODE, cases); + + // any + let cases = &[ + (Any::Int(123), "123"), + (Any::Int(65535), "65535"), + (Any::Int(Int::MAX), &Int::MAX.to_string()), + (Any::Float(123.123), "123.123"), + ]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] @@ -426,53 +391,71 @@ mod tests { let cases = &[ // standard string (IpldString::from("hello world"), "\"hello world\""), - // empty string TODO: (IpldString::default(), "\"\""), // non-standard UTF-8 string TODO: // (IpldString::from("ÅΩ"), "\"ÅΩ\""), ]; roundtrip_str_codec::<_>(DagJson::CODE, cases); + + let cases = &[ + // standard string + ( + Any::String(IpldString::from("hello world")), + "\"hello world\"", + ), + (Any::String(IpldString::default()), "\"\""), + // non-standard UTF-8 string TODO: + // (Any::String(IpldString::from("ÅΩ")), "\"ÅΩ\""), + ]; + roundtrip_str_codec::<_>(DagJson::CODE, cases); } #[test] fn test_bytes() { - let cases = &[( - Bytes::from(vec![0x01, 0x02, 0x03]), - r#"{"/":{"bytes":"mAQID"}}"#, - )]; + let cases = &[ + ( + Bytes::from([1u8, 2, 3].as_ref()), + r#"{"/":{"bytes":"mAQID"}}"#, + ), + // TODO: empty bytes + // (Bytes::from(&[]), r#"{"/":{"bytes":"m"}}"#), + ]; roundtrip_str_codec::(DagJson::CODE, cases); - } - #[test] - fn test_link() { - type TestLink = Link; - - let s = String::from("QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"); - let json = format!("{{\"/\":\"{}\"}}", s); - - let cases = &[( - TestLink::from(Cid::try_from(s.as_str()).unwrap()), - json.as_str(), - )]; - roundtrip_str_codec::(DagJson::CODE, cases); + let cases = &[ + ( + Any::Bytes(Bytes::from([1u8, 2, 3].as_ref())), + r#"{"/":{"bytes":"mAQID"}}"#, + ), + // TODO: empty bytes + // (Bytes::from(&[]), r#"{"/":{"bytes":"m"}}"#), + ]; + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] - fn test_seq() { + fn test_list() { // raw types let cases = &[(vec![], "[]"), (vec![1, 2], "[1,2]")]; roundtrip_str_codec::>(DagJson::CODE, cases); // any types let cases = &[ - (vec![], "[]"), - // (vec![Any::Int(1), Any::Int(2)], "[1,2]"), - // // ( - // // vec![Any::Link(Link::Cid(Default::default()).into())], - // // "[{\"/\": }]", - // // ), + (Any::List(vec![]), "[]"), + (Any::List(vec![Any::Int(1), Any::Int(2)]), "[1,2]"), + // ( + // vec![Any::Link(Link::Cid(Default::default()).into())], + // "[{\"/\": }]", + // ), + ( + Any::List(vec![ + Any::List(vec![]), + Any::List(vec![Any::Int(1), Any::Float(123.123)]), + ]), + "[[],[1,123.123]]", + ), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(DagJson::CODE, cases); } #[test] @@ -492,7 +475,36 @@ mod tests { roundtrip_str_codec::>(DagJson::CODE, cases); // any types - let cases = &[]; - roundtrip_str_codec::(DagJson::CODE, cases); + let cases = &[ + (Any::Map(Default::default()), "{}"), + ( + { + let mut map: Map = Default::default(); + map.insert("abc".into(), Any::Int(123)); + Any::Map(map) + }, + "{\"abc\":123}", + ), + ]; + roundtrip_str_codec::(DagJson::CODE, cases); + } + + #[test] + fn test_link() { + let s = String::from("QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"); + let json = format!("{{\"/\":\"{}\"}}", s); + + let cases = &[( + Link::from(Cid::try_from(s.as_str()).unwrap()), + json.as_str(), + )]; + roundtrip_str_codec::(DagJson::CODE, cases); + + // any + let cases = &[( + Any::Link(Link::from(Cid::try_from(s.as_str()).unwrap()).into()), + json.as_str(), + )]; + roundtrip_str_codec::(DagJson::CODE, cases); } } diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index 04d4e67..6168882 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -8,20 +8,7 @@ pub mod dag_json; // pub mod dag_pb; use crate::dev::*; -use serde::{de, ser}; -use std::{ - convert::TryFrom, - io::{Read, Write}, -}; - -// pub trait CodecExt<'de>: Codec { -// type Encoder: Encoder; -// type Decoder: Decoder<'de>; -// -// fn encoder(writer: W) -> Result; -// -// fn decoder(reader: R) -> Result; -// } +use maybestd::convert::TryFrom; // // pub trait Transcoder<'de> { @@ -32,16 +19,17 @@ use std::{ // fn deserializer(&mut self) -> &mut Self::Deserializer; // } -/// A helper trait for visiting special and recursive IPLD types. +/// An extension to the [`serde::de::Visitor`] trait for visiting +/// [`Representation`]s that contain IPLD links. /// -/// Should be implemented by any types representing IPLD links and maps. -pub trait IpldVisitorExt<'de>: Visitor<'de> { +/// [`Representation`]: crate::prelude::Representation +pub trait LinkVisitor<'de>: Visitor<'de> { /// The input contains the string of a [`Cid`]. /// /// The default implementation fails with a type error. fn visit_link_str(self, cid_str: &str) -> Result where - E: de::Error, + E: serde::de::Error, { let cid = Cid::try_from(cid_str).map_err(E::custom)?; self.visit_cid(cid) @@ -53,7 +41,7 @@ pub trait IpldVisitorExt<'de>: Visitor<'de> { #[inline] fn visit_link_borrowed_str(self, cid_str: &'de str) -> Result where - E: de::Error, + E: serde::de::Error, { self.visit_link_str(cid_str) } @@ -64,7 +52,7 @@ pub trait IpldVisitorExt<'de>: Visitor<'de> { #[inline] fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result where - E: de::Error, + E: serde::de::Error, { let cid = Cid::try_from(cid_bytes).map_err(E::custom)?; self.visit_cid(cid) @@ -76,15 +64,15 @@ pub trait IpldVisitorExt<'de>: Visitor<'de> { #[inline] fn visit_link_borrowed_bytes(self, cid_bytes: &'de [u8]) -> Result where - E: de::Error, + E: serde::de::Error, { self.visit_link_bytes(cid_bytes) } /// The input contains an already parsed [`Cid`]. - fn visit_cid(self, cid: Cid) -> Result + fn visit_cid(self, _: Cid) -> Result where - E: de::Error, + E: serde::de::Error, { Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) } @@ -105,7 +93,7 @@ pub(crate) mod test_utils { // writing let bytes = write_to_bytes::(&mut codec, dag).expect(&format!( "Failed to encode `{}` {:?} into {:?}", - dag.name(), + T::NAME, dag, expected, )); @@ -114,7 +102,7 @@ pub(crate) mod test_utils { // decoding let v = decode_from_bytes::(&mut codec, expected).expect(&format!( "Failed to decode `{}` from {:?}", - dag.name(), + T::NAME, expected, )); assert_eq!(dag, &v, "Decoding failure"); @@ -122,7 +110,7 @@ pub(crate) mod test_utils { // reading let v = codec.read(*expected).expect(&format!( "Failed to read `{}` from {:?}", - dag.name(), + T::NAME, expected, )); assert_eq!(dag, &v, "Reading failure"); @@ -139,7 +127,7 @@ pub(crate) mod test_utils { // writing let string = write_to_str::(&mut codec, dag).expect(&format!( "Failed to encode `{}` {:?} into {}", - dag.name(), + T::NAME, dag, expected, )); @@ -148,7 +136,7 @@ pub(crate) mod test_utils { // decoding let v = decode_from_str::(&mut codec, expected).expect(&format!( "Failed to decode `{}` from {}", - dag.name(), + T::NAME, expected, )); assert_eq!(dag, &v, "Decoding failure"); @@ -156,7 +144,7 @@ pub(crate) mod test_utils { // reading let v = codec.read(expected.as_bytes()).expect(&format!( "Failed to read `{}` from {}", - dag.name(), + T::NAME, expected, )); assert_eq!(dag, &v, "Reading failure"); diff --git a/src/compat/core.rs b/src/compat/core.rs index e6f38c8..61bdf1c 100644 --- a/src/compat/core.rs +++ b/src/compat/core.rs @@ -1,17 +1,20 @@ use crate::dev::*; +use macros::repr_serde; use maybestd::{fmt, marker::PhantomData}; mod ignored { use super::*; impl Representation for IgnoredAny { + type DataModelKind = type_kinds::Null; + type SchemaKind = type_kinds::Union; type ReprKind = type_kinds::Any; const NAME: &'static str = "IgnoredAny"; const SCHEMA: &'static str = "type IgnoredAny = Any"; const DATA_MODEL_KIND: Kind = Kind::Null; - const SCHEMA_KIND: Kind = Kind::Any; - // const REPR_KIND: Kind = Kind::Any; + const SCHEMA_KIND: Kind = Kind::Union; + const REPR_KIND: Kind = Kind::Any; const __IGNORED: bool = true; #[doc(hidden)] @@ -30,8 +33,74 @@ mod ignored { Deserialize::deserialize(deserializer) } } + + repr_serde! { @select_for IgnoredAny } + repr_serde! { @visitors for IgnoredAny => IgnoredAny + { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } + {} {} @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", IgnoredAny::NAME) + } + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(()) + } + } + } + + /// + pub type Ignored = PhantomData; + + impl Representation for Ignored { + type DataModelKind = type_kinds::Null; + type SchemaKind = type_kinds::Union; + type ReprKind = type_kinds::Any; + + const NAME: &'static str = "Ignored"; + const SCHEMA: &'static str = "type Ignored = IgnoredAny"; + const DATA_MODEL_KIND: Kind = Kind::Null; + const SCHEMA_KIND: Kind = Kind::Union; + const REPR_KIND: Kind = Kind::Any; + const __IGNORED: bool = true; + + #[doc(hidden)] + fn serialize(&self, _: S) -> Result + where + S: Serializer, + { + Err(S::Error::custom("unimplemented")) + } + + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Err(D::Error::custom("unimplemented")) + } + } + + repr_serde! { @select_for Ignored => Ignored + { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } + { T } { T: Representation } + } + repr_serde! { @visitors for Ignored => Ignored + { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } + { T } { T: Representation + '_a } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", T::NAME) + } + // TODO: delegate + } + } } +// TODO: mod option { use super::*; @@ -41,6 +110,8 @@ mod option { where T: Representation, { + type DataModelKind = T::DataModelKind; + type SchemaKind = T::SchemaKind; type ReprKind = T::ReprKind; // type ReprKind = type_kinds::Optional<::ReprKind>; // type ReprKind = typenum::op!(type_kinds::Null | T::ReprKind); @@ -50,7 +121,7 @@ mod option { const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - // const REPR_KIND: Kind = T::REPR_KIND; + const REPR_KIND: Kind = T::REPR_KIND; const IS_LINK: bool = T::IS_LINK; const HAS_LINKS: bool = T::HAS_LINKS; @@ -142,13 +213,15 @@ mod wrapper { where T: Representation, { - type ReprKind = ::ReprKind; + type DataModelKind = T::DataModelKind; + type SchemaKind = T::SchemaKind; + type ReprKind = T::ReprKind; const NAME: &'static str = T::NAME; const SCHEMA: &'static str = T::SCHEMA; const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - // const REPR_KIND: Kind = T::REPR_KIND; + const REPR_KIND: Kind = T::REPR_KIND; const IS_LINK: bool = T::IS_LINK; const HAS_LINKS: bool = T::HAS_LINKS; diff --git a/src/data_model/any.rs b/src/data_model/any.rs index 45bc7fb..84d1a07 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -4,7 +4,6 @@ use macros::{ repr_serde, }; use maybestd::{fmt, rc::Rc}; -use std::path::Path; // /// // #[derive(Clone, Debug, IsVariant, Unwrap)] @@ -47,17 +46,9 @@ schema! { } representation kinded; } -// repr_serde! { @visitor T T { type_kinds::Any } -// { T: TryFrom + 'static } {} -// { -// #[inline] -// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// write!(f, "{}, a boolean type", Bool::NAME) -// } -// }} - -// repr_serde! { @visitor_ext T T { type_kinds::Any } { T: TryFrom + 'static } {} {}} +// impl FromIterator for Any, (T: StringRepresentation, Any) +/* /// TODO: convert these to a Node trait, that all types implement impl Any { /// LookupByString looks up a child object in this node and returns it. @@ -191,3 +182,4 @@ impl Any { // Calling this method should not cause an allocation. // Prototype() NodePrototype } + */ diff --git a/src/data_model/link.rs b/src/data_model/link.rs index b3659cd..b42d22d 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -19,7 +19,7 @@ pub enum Link { /// #[from(ignore)] - Inner { + Resolved { /// cid: Cid, /// @@ -35,7 +35,7 @@ impl Link { pub const fn cid(&self) -> &Cid { match self { Self::Cid(cid) => cid, - Self::Inner { cid, .. } => cid, + Self::Resolved { cid, .. } => cid, } } @@ -44,7 +44,7 @@ impl Link { pub const fn is_dirty(&self) -> bool { match self { Self::Cid(_) => false, - Self::Inner { dirty, .. } => *dirty, + Self::Resolved { dirty, .. } => *dirty, } } @@ -53,7 +53,7 @@ impl Link { pub const fn as_ref(&self) -> Option<&T> { match self { Self::Cid(_) => None, - Self::Inner { t, .. } => Some(t), + Self::Resolved { t, .. } => Some(t), } } @@ -74,23 +74,27 @@ impl Link { } impl Representation for Link { + type DataModelKind = type_kinds::Link; + type SchemaKind = type_kinds::Link; type ReprKind = type_kinds::Link; const NAME: &'static str = "Link"; - const SCHEMA: &'static str = concat!("type Link &", stringify!(T::NAME)); + const SCHEMA: &'static str = "type Link &Any"; const DATA_MODEL_KIND: Kind = Kind::Link; + const SCHEMA_KIND: Kind = Kind::Link; + const REPR_KIND: Kind = Kind::Link; fn name(&self) -> &'static str { match self { Self::Cid(_) => Self::NAME, - Self::Inner { t, .. } => t.name(), + Self::Resolved { t, .. } => t.name(), } } fn has_links(&self) -> bool { match self { Self::Cid(_) => T::HAS_LINKS, - Self::Inner { t, .. } => t.has_links(), + Self::Resolved { t, .. } => t.has_links(), } } @@ -119,30 +123,44 @@ impl Representation for Link { } } -repr_serde! { @visitor S T { type_kinds::Link } { S, T } - { S: 'static, T: Select + 'static } -{ - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A link of type {} to a {}", S::NAME, T::NAME) +repr_serde! { @select_for Link => T + { @dk (type_kinds::Link) @sk (type_kinds::Link) @rk (type_kinds::Link) } + { T } { T: Select + 'static } +} +repr_serde! { @visitors for S => T + { @dk (type_kinds::Link) @sk (type_kinds::Link) @rk (type_kinds::Link) } + { S, T } { S: 'static, T: Select + 'static } + @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A link of type {} to a {}", S::NAME, T::NAME) + } + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + self.visit_link_bytes(bytes) + } + #[inline] + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + self.visit_link_str(s) + } } -}} - -// ? impl From? -repr_serde! { @visitor_ext S T { type_kinds::Link } { S, T } - { S: 'static, T: Select + 'static } -{ - #[inline] - fn visit_cid(self, cid: Cid) -> Result - where - E: de::Error, - { - // self.0.select_link::(cid).map_err(E::custom) - unimplemented!() + @link { + #[inline] + fn visit_cid(self, cid: Cid) -> Result + where + E: de::Error, + { + // self.0.select_link::(cid).map_err(E::custom) + unimplemented!() + } } -}} - -repr_serde! { @select Link => T { T } { T: Select + 'static } } +} impl<'a, Ctx, T> SelectorSeed<'a, Ctx, Link> where @@ -171,7 +189,7 @@ impl Into for Link { fn into(self) -> Cid { match self { Self::Cid(cid) => cid, - Self::Inner { cid, .. } => cid, + Self::Resolved { cid, .. } => cid, } } } @@ -225,7 +243,7 @@ impl Into for Link { // fn from(link: Link) -> Self { // match link { // Link::Cid(Cid::Generic(inner)) => inner, -// Link::Inner { cid, .. } => cid, +// Link::Resolved { cid, .. } => cid, // } // } // } diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 72d771c..51e52f9 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -5,21 +5,27 @@ use maybestd::{ fmt, iter, marker::PhantomData, ops::{Bound, RangeBounds}, + vec::Vec, }; use serde::de::value::SeqAccessDeserializer; pub use iterators::*; +/// A list type, implemented as a [`Vec`]. /// +/// [`Vec`]: crate::maybestd::vec::Vec pub type List = Vec; impl Representation for List { + type DataModelKind = type_kinds::List; + type SchemaKind = type_kinds::List; type ReprKind = type_kinds::List; const NAME: &'static str = "List"; - const SCHEMA: &'static str = concat!("type List [", stringify!(T::NAME), "]"); + const SCHEMA: &'static str = "type List [Any]"; const DATA_MODEL_KIND: Kind = Kind::List; const SCHEMA_KIND: Kind = Kind::List; + const REPR_KIND: Kind = Kind::List; const HAS_LINKS: bool = T::HAS_LINKS; fn has_links(&self) -> bool { @@ -75,12 +81,14 @@ impl Representation for List { } } -// TODO: this should only apply to List datamodels with a List repr -// restrict this impl to T: Representation -repr_serde! { @visitor S T { type_kinds::List } { S, T } - { S: Default + Extend + 'static, - T: Select + 'static } -{ +repr_serde! { @select_for List => T + { @dk (type_kinds::List) @sk (type_kinds::List) @rk (type_kinds::List) } + { T } { T: Select + 'static } +} +repr_serde! { @visitors for S => T + { @dk (type_kinds::List) @sk (type_kinds::List) @rk (type_kinds::List) } + { S, T } { S: Default + Extend + 'static, + T: Select + 'static } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A list of type {} of {}", S::NAME, T::NAME) @@ -94,6 +102,7 @@ repr_serde! { @visitor S T { type_kinds::List } { S, T } if let Some(s) = self.0.selector.as_explore_union() { if s.matches_first() { let list = S::deserialize::(SeqAccessDeserializer::new(seq))?; + // todo: for each selector, __select_in return list.__select_in(self.0).map_err(A::Error::custom); } else { // todo: support multiple non-overlapping ranges @@ -126,18 +135,46 @@ repr_serde! { @visitor S T { type_kinds::List } { S, T } } }} -repr_serde! { @visitor_ext S T { type_kinds::List } { S, T } - { S: Default + Extend + 'static, - T: Select + 'static } {} -} - -repr_serde! { @select List => T { T } { T: Select + 'static } } - +// repr_serde! { @visitor_ext S T { type_kinds::List } { S, T } +// { S: Default + Extend + 'static, +// T: Select + 'static } {} +// } +// repr_serde! { @link_visitor_blanket for S => T { type_kinds::List } +// { S, T } +// { S: Default + Extend + 'static, T: Select + 'static } {} +// } +// repr_serde! { @select List => T { T } { T: Select + 'static } } +// repr_serde! { @select_blanket S T { type_kinds::List } { S, T } +// { S: Default + Extend + 'static, T: Select + 'static } +// } + +// TODO: constrain to DM=List and SK=List, then blanket Select for them impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, - T: Select + 'static, + T: Representation + Select + 'static, { + /// + pub fn select_list( + mut self, + // dag: Either<&T2, I>, + ) -> Result<(), Error> + where + U: Select, + I: ListIterator, + { + unimplemented!() + } + + /// + pub fn patch_list(mut self, dag: &mut T) -> Result<(), Error> + where + U: Select, + I: ListIterator, + { + unimplemented!() + } + /// Executes a [`Matcher`] selector against a list (data model) type. /// todo could probably use a collection trait instead of multiple Fns pub fn match_list( @@ -164,6 +201,10 @@ where // select against each child for idx in 0usize.. { + // FIXME: + // i think we do want to control the seed, ask to descend and ascend + // i think we can make this function support select, patch and flush + // TODO: should be iter.next_element_seed(self.to_field_select_seed()) if self.select_index::( idx, @@ -246,6 +287,60 @@ where mod iterators { use super::*; + /* + // /// A [`Select`]able list iterator over a serde sequence representation. + // #[doc(hidden)] + // #[derive(Debug)] + // struct SerdeListIterator2<'de, const C: u64, A, T = IgnoredAny, S = DeserializeWrapper> { + // seq: A, + // seed: S, + // _de: PhantomData<&'de T>, + // } + + // impl<'de, const C: u64, A> SerdeListIterator2<'de, C, A> { + // pub const fn ignored(seq: A) -> Self { + // SerdeListIterator2 { + // seq, + // seed: DeserializeWrapper::::new(), + // _de: PhantomData, + // } + // } + // } + + // impl<'de, const C: u64, A, T, S> SerdeListIterator2<'de, C, A, T, S> { + // pub const fn from(seq: A) -> SerdeListIterator2<'de, C, A, T> { + // SerdeListIterator2 { + // seq, + // seed: DeserializeWrapper::::new(), + // _de: PhantomData, + // } + // } + + // pub fn take(self) -> (S, SerdeListIterator2<'de, C, A, IgnoredAny>) { + // SerdeListIterator2 { + // seq: self.seq, + // seed: DeserializeWrapper::::new(), + // _de: PhantomData, + // } + // } + // } + + // impl<'de, const C: u64, A, T, S> Iterator for SerdeListIterator2<'de, C, A, T, S> + // where + // A: SeqAccess<'de>, + // S: DeserializeSeed<'de, Value = T>, + // { + // type Item = Result; + // fn next(&mut self) -> Option { + // match self.seq.next_element_seed(seed) { + // Ok(Some(val)) => Some(Ok(val)), + // Ok(None) => None, + // Err(err) => Some(Err(err)), + // } + // } + // } + */ + /// A [`Select`]able list iterator over a serde sequence representation. #[doc(hidden)] #[derive(Debug)] @@ -301,7 +396,7 @@ mod iterators { { let dag = self .inner - .next_element_seed(DeserializeWrapper::::default()) + .next_element_seed(DeserializeWrapper::::new()) .map_err(|_| Error::explore_index_failure::(self.index))?; if dag.is_none() { diff --git a/src/data_model/map.rs b/src/data_model/map.rs index 87097c6..6df9bcf 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -1,11 +1,15 @@ use crate::dev::*; use macros::repr_serde; -use maybestd::{cell::RefCell, collections::BTreeMap, fmt, iter, marker::PhantomData}; +use maybestd::{ + cell::RefCell, collections::BTreeMap, fmt, iter, marker::PhantomData, str::FromStr, +}; use serde::de::value::MapAccessDeserializer; pub use iterators::*; +/// A map type, implemented as a [`BTreeMap`]. /// +/// [`BTreeMap`]: crate::maybestd::collections::BTreeMap /// TODO: indexmap? pub type Map = BTreeMap; @@ -13,20 +17,19 @@ impl Representation for Map where // TODO: remove clone requirement by switching up callbacks K: StringRepresentation, + ::Err: fmt::Display, // K: AsRef> V: Representation, { + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Map; type ReprKind = type_kinds::Map; const NAME: &'static str = "Map"; - const SCHEMA: &'static str = concat!( - "type Map {", - stringify!(K::NAME), - ":", - stringify!(V::NAME), - "}", - ); + const SCHEMA: &'static str = "type Map {String:Any}"; const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Map; + const REPR_KIND: Kind = Kind::Map; fn has_links(&self) -> bool { self.iter().any(|(k, v)| k.has_links() || v.has_links()) @@ -97,11 +100,18 @@ where } } -repr_serde! { @visitor T (K, V) { type_kinds::Map } { T, K, V } - { T: Default + Extend<(K, V)> + 'static, - K: Select + StringRepresentation + 'static, - V: Select + 'static } -{ +repr_serde! { @select_for Map => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::Map) } + { K, V } { K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } +} +repr_serde! { @visitors for T => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::Map) } + { T, K, V } { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A map of type {} of {} to {}", T::NAME, K::NAME, V::NAME) @@ -114,6 +124,7 @@ repr_serde! { @visitor T (K, V) { type_kinds::Map } { T, K, V } { if let Some(s) = self.0.selector.as_explore_union() { if s.matches_first() { + // TODO: transform the seed to a phantom seed, then recurse let map = T::deserialize::(MapAccessDeserializer::new(map))?; return map.__select_in(self.0).map_err(A::Error::custom); } @@ -133,9 +144,11 @@ repr_serde! { @visitor T (K, V) { type_kinds::Map } { T, K, V } ).map_err(A::Error::custom) }, Selector::ExploreFields(_) => self.0 - .explore_map_fields::(iter).map_err(A::Error::custom), + .explore_map_fields::(iter) + .map_err(A::Error::custom), Selector::ExploreAll(_) => self.0 - .explore_map_fields::(iter).map_err(A::Error::custom), + .explore_map_fields::(iter) + .map_err(A::Error::custom), _ => Err(A::Error::custom(Error::unsupported_selector::( self.0.selector, ))), @@ -143,17 +156,26 @@ repr_serde! { @visitor T (K, V) { type_kinds::Map } { T, K, V } } }} -repr_serde! { @visitor_ext T (K, V) { type_kinds::Map } { T, K, V } - { T: Default + Extend<(K, V)> + 'static, - K: Select + StringRepresentation + 'static, - V: Select + 'static } - {} -} +// repr_serde! { @visitor_ext T (K, V) { type_kinds::Map } { T, K, V } +// { T: Default + Extend<(K, V)> + 'static, +// K: Select + StringRepresentation + 'static, +// ::Err: fmt::Display, +// V: Select + 'static } +// {} +// } +// repr_serde! { @link_visitor_blanket for T => (K, V) { type_kinds::Map } { T, K, V } +// { T: Default + Extend<(K, V)> + 'static, +// K: Select + StringRepresentation + 'static, +// ::Err: fmt::Display, +// V: Select + 'static } +// {} +// } -repr_serde! { @select Map => (K, V) { K, V } - { K: Select + StringRepresentation + 'static, - V: Select + 'static } -} +// repr_serde! { @select Map => (K, V) { K, V } +// { K: Select + StringRepresentation + 'static, +// ::Err: fmt::Display, +// V: Select + 'static } +// } impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where @@ -170,6 +192,7 @@ where ) -> Result<(), Error> where K: Select + StringRepresentation, + ::Err: fmt::Display, V: Select, I: MapIterator, T2: Default + 'static, @@ -225,6 +248,7 @@ where pub(crate) fn explore_map_fields(self, mut iter: I) -> Result<(), Error> where K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, V: Select + 'static, I: MapIterator, { @@ -286,7 +310,7 @@ mod iterators { { let key = self .inner - .next_key_seed(DeserializeWrapper::::default()) + .next_key_seed(DeserializeWrapper::::new()) .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; // TODO: assert that key == expected_field_name @@ -305,7 +329,7 @@ mod iterators { V: Representation, { self.inner - .next_value_seed(DeserializeWrapper::::default()) + .next_value_seed(DeserializeWrapper::::new()) .or_else(|_| Err(Error::explore_value_failure::(field))) } diff --git a/src/data_model/mod.rs b/src/data_model/mod.rs index 816e738..f86d7d7 100644 --- a/src/data_model/mod.rs +++ b/src/data_model/mod.rs @@ -41,8 +41,8 @@ where #[doc(hidden)] #[derive(Debug)] pub struct DeserializeWrapper(std::marker::PhantomData); -impl Default for DeserializeWrapper { - fn default() -> Self { +impl DeserializeWrapper { + pub const fn new() -> Self { Self(std::marker::PhantomData) } } diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index 3dd7159..490c941 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -3,12 +3,7 @@ use macros::{ derive_more::{AsMut, AsRef, Deref, DerefMut, From, Index, IndexMut, Into, IntoIterator}, repr_serde, }; -use maybestd::{ - borrow::Cow, - fmt, - ops::{self, RangeBounds}, - str::FromStr, -}; +use maybestd::{borrow::Cow, fmt, ops::RangeBounds, str::FromStr}; pub use self::bool::Bool; pub use self::bytes::Bytes; @@ -16,26 +11,32 @@ pub use self::null::Null; pub use self::num::*; pub use self::string::IpldString; -/// Type alias for integers, which are represented as `i128`s. -pub type Int = Int64; -/// Type alias for floats, which are represented as `f64`s. -pub type Float = Float64; +/// Default type for IPLD integers, which aliases to [`i64`]. +pub type Int = i64; + +/// Default type for IPLD floats, which aliases to [`f64`]. +pub type Float = f64; mod null { use super::*; /// A nothing type. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq, Deserialize, Serialize)] + #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub struct Null; impl Representation for Null { + type DataModelKind = type_kinds::Null; + type SchemaKind = type_kinds::Null; type ReprKind = type_kinds::Null; const NAME: &'static str = "Null"; const SCHEMA: &'static str = "type Null null"; const DATA_MODEL_KIND: Kind = Kind::Null; + const SCHEMA_KIND: Kind = Kind::Null; + const REPR_KIND: Kind = Kind::Null; #[doc(hidden)] + #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -44,6 +45,7 @@ mod null { } #[doc(hidden)] + #[inline] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -52,22 +54,21 @@ mod null { } } - repr_serde! { @visitor T T { type_kinds::Null } - { T } { T: From + 'static } - { + repr_serde! { @select_for Null } + repr_serde! { @visitors for T => T + { @dk (type_kinds::Null) @sk (type_kinds::Null) @rk (type_kinds::Null) } + { T } { T: From<()> + 'static } @serde { #[inline] - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A nothing type {}", T::NAME) } - #[inline] fn visit_none(self) -> Result where E: de::Error, { - self.0.select_scalar::(T::from(Null)).map_err(E::custom) + self.0.select_scalar::(T::from(())).map_err(E::custom) } - #[inline] fn visit_unit(self) -> Result where @@ -77,12 +78,6 @@ mod null { } }} - repr_serde! { @visitor_ext T T { type_kinds::Null } - { T } { T: From + 'static } {} - } - - repr_serde! { @select Null => Null {} {} } - impl From<()> for Null { #[inline] fn from(_: ()) -> Self { @@ -94,17 +89,24 @@ mod null { mod bool { use super::*; - /// A boolean type. + /// A boolean type, represented as a [`bool`]. + /// + /// [`bool`]: crate::maybestd::primitive::bool pub type Bool = bool; impl Representation for bool { + type DataModelKind = type_kinds::Bool; + type SchemaKind = type_kinds::Bool; type ReprKind = type_kinds::Bool; const NAME: &'static str = "Bool"; const SCHEMA: &'static str = "type Bool bool"; const DATA_MODEL_KIND: Kind = Kind::Bool; + const SCHEMA_KIND: Kind = Kind::Bool; + const REPR_KIND: Kind = Kind::Bool; #[doc(hidden)] + #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -113,6 +115,7 @@ mod bool { } #[doc(hidden)] + #[inline] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -121,9 +124,11 @@ mod bool { } } - repr_serde! { @visitor T T { type_kinds::Bool } - { T } { T: From + 'static } - { + repr_serde! { @select_for bool } + repr_serde! { @visitors for T => T + { @dk (type_kinds::Bool) @sk (type_kinds::Bool) @rk (type_kinds::Bool) } + { T } { T: TryFrom + 'static, + >::Error: fmt::Display } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A boolean type {}", T::NAME) @@ -134,15 +139,10 @@ mod bool { where E: de::Error, { - self.0.select_scalar::(T::from(v)).map_err(E::custom) + let b = T::try_from(v).map_err(E::custom)?; + self.0.select_scalar::(b).map_err(E::custom) } }} - - repr_serde! { @visitor_ext T T { type_kinds::Bool } - { T } { T: From + 'static } {} - } - - repr_serde! { @select Bool => Bool {} {} } } mod num { @@ -156,20 +156,27 @@ mod num { @conv { $($other_ty:ty : $other_visit_fn:ident)* } } ) => { - #[doc = concat!("a fixed-length number type represented as a(n)", stringify!($ty))] - pub type $name = $ty; + // #[doc = concat!("Type alias for [`", stringify!($ty), "`]s.")] + // /// + // #[doc = concat!("[`", stringify!($ty), "`]: ")] + // #[doc = concat!("crate::maybestd::primitive::", stringify!($ty))] + // pub type $name = $ty; impl Representation for $ty { + type DataModelKind = type_kinds::$dm_kind; + type SchemaKind = type_kinds::$name; type ReprKind = type_kinds::$name; const NAME: &'static str = stringify!($name); const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); const DATA_MODEL_KIND: Kind = Kind::$dm_kind; const SCHEMA_KIND: Kind = Kind::$name; + const REPR_KIND: Kind = Kind::$name; impl_ipld_num!(@field $dm_kind $ty); #[doc(hidden)] + #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -178,6 +185,7 @@ mod num { } #[doc(hidden)] + #[inline] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -186,27 +194,27 @@ mod num { } } - repr_serde! { @visitor T T { type_kinds::$name } - { T } { T: From<$ty> + 'static } - { + repr_serde! { @select_for $ty } + repr_serde! { @visitors for T => T + { @dk (type_kinds::$dm_kind) @sk (type_kinds::$name) @rk (type_kinds::$name) } + { T } { T: TryFrom<$ty> + 'static, + >::Error: fmt::Display } @serde { #[inline] - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}, a fixed-length number type represented as a(n) {}", <$ty>::NAME, stringify!($ty), ) } - #[inline] fn $visit_fn(self, v: $ty) -> Result where E: de::Error, { - self.0.select_scalar::(T::from(v)).map_err(E::custom) + let n = T::try_from(v).map_err(E::custom)?; + self.0.select_scalar::(n).map_err(E::custom) } - - $( - #[inline] + $( #[inline] fn $other_visit_fn(self, v: $other_ty) -> Result where E: de::Error, @@ -216,12 +224,6 @@ mod num { } )* }} - - repr_serde! { @visitor_ext T T { type_kinds::$name } - { T } { T: From<$ty> + 'static } {} - } - - repr_serde! { @select $ty => $ty {} {} } }; (@field Int $ty:ty) => { fn as_field(&self) -> Option> { @@ -278,7 +280,15 @@ mod num { // TODO: unicode normalization? https://ipld.io/docs/data-model/kinds/#string-kind mod string { use super::*; - use unicode_normalization::UnicodeNormalization; + use unicode_normalization::*; + + // struct NfcChars<'a>(Recompositions>); + // impl<'a> ToOwned for <'a> { + // type Owned = String; + // fn to_owned(&self) -> Self::Owned { + + // } + // } /// #[derive( @@ -313,17 +323,22 @@ mod string { } impl Representation for IpldString { + type DataModelKind = type_kinds::String; + type SchemaKind = type_kinds::String; type ReprKind = type_kinds::String; const NAME: &'static str = "String"; const SCHEMA: &'static str = "type String string"; const DATA_MODEL_KIND: Kind = Kind::String; + const SCHEMA_KIND: Kind = Kind::String; + const REPR_KIND: Kind = Kind::String; fn as_field(&self) -> Option> { Some(self.0.as_str().into()) } #[doc(hidden)] + #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -332,6 +347,7 @@ mod string { } #[doc(hidden)] + #[inline] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -340,11 +356,13 @@ mod string { } } - repr_serde! { @visitor T T { type_kinds::String } - { T } { T: From + 'static } - { + repr_serde! { @select_for IpldString } + repr_serde! { @visitors for T => T + { @dk (type_kinds::String) @sk (type_kinds::String) @rk (type_kinds::String) } + { T } { T: TryFrom + 'static, + >::Error: fmt::Display } @serde { #[inline] - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A string of type {}", T::NAME) } @@ -353,7 +371,8 @@ mod string { where E: de::Error, { - self.0.select_scalar::(T::from(IpldString::from(s))).map_err(E::custom) + let s = T::try_from(IpldString::from(s)).map_err(E::custom)?; + self.0.select_scalar::(s).map_err(E::custom) } #[inline] @@ -365,12 +384,6 @@ mod string { } }} - repr_serde! { @visitor_ext T T { type_kinds::String } - { T } { T: From + 'static } {} - } - - repr_serde! { @select IpldString => IpldString {} {} } - impl From<&str> for IpldString { #[inline] fn from(s: &str) -> Self { @@ -433,6 +446,7 @@ mod bytes { From, Hash, // Index, + Into, IntoIterator, Ord, PartialOrd, @@ -440,7 +454,6 @@ mod bytes { )] #[as_ref(forward)] #[deref(forward)] - #[from(forward)] pub struct Bytes(crate::dev::bytes::Bytes); impl Bytes { @@ -475,6 +488,17 @@ mod bytes { } } + impl From<&[u8]> for Bytes { + fn from(bytes: &[u8]) -> Self { + Self::copy_from_slice(bytes) + } + } + impl From> for Bytes { + fn from(bytes: Vec) -> Self { + Self(crate::dev::bytes::Bytes::from(bytes)) + } + } + // impl> ops::Index for Bytes { // type Output = Self; // fn index(&self, index: R) -> &Self::Output { @@ -483,11 +507,15 @@ mod bytes { // } impl Representation for Bytes { + type DataModelKind = type_kinds::Bytes; + type SchemaKind = type_kinds::Bytes; type ReprKind = type_kinds::Bytes; const NAME: &'static str = "Bytes"; const SCHEMA: &'static str = "type Bytes bytes"; const DATA_MODEL_KIND: Kind = Kind::Bytes; + const SCHEMA_KIND: Kind = Kind::Bytes; + const REPR_KIND: Kind = Kind::Bytes; #[doc(hidden)] fn serialize(&self, serializer: S) -> Result @@ -511,8 +539,8 @@ mod bytes { impl<'de> Visitor<'de> for BytesVisitor { type Value = Bytes; #[inline] - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "A slice of bytes") + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A slice of bytes of type {}", Self::Value::NAME) } #[inline] fn visit_bytes(self, bytes: &[u8]) -> Result @@ -529,56 +557,50 @@ mod bytes { Ok(Self::Value::from(bytes)) } } + impl<'de> LinkVisitor<'de> for BytesVisitor {} - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, BytesVisitor); - } - - deserializer.deserialize_bytes(BytesVisitor) + Multicodec::deserialize_bytes::(deserializer, BytesVisitor) } } - repr_serde! { @visitor T T { type_kinds::Bytes } { T } - // { T: for<'a> TryFrom<&'a [u8], Error = Error> + 'static } - { T: From + 'static } - { + repr_serde! { @select_for Bytes } + repr_serde! { @visitors for T => T + { @dk (type_kinds::Bytes) @sk (type_kinds::Bytes) @rk (type_kinds::Bytes) } + { T } { T: TryFrom> + for<'a> TryFrom<&'a [u8]> + 'static, + >>::Error: fmt::Display, + for<'a> >::Error: fmt::Display } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Bytes of type {}", T::NAME) } - - // #[inline] - // fn visit_bytes(self, bytes: &[u8]) -> Result - // where - // E: de::Error, - // { - // self.0.select_bytes::(Bytes::copy_from_slice(bytes)).map_err(E::custom) - // } - - // #[inline] - // fn visit_byte_buf(self, bytes: Vec) -> Result - // where - // E: de::Error, - // { - // self.0.select_bytes::(Bytes::from(bytes)).map_err(E::custom) - // } + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + // let bytes = T::try_from(bytes).map_err(E::custom)?; + // self.0.select_bytes::(bytes).map_err(E::custom) + unimplemented!() + } + #[inline] + fn visit_byte_buf(self, bytes: Vec) -> Result + where + E: de::Error, + { + // let bytes = T::try_from(bytes).map_err(E::custom)?; + // self.0.select_bytes::(bytes).map_err(E::custom) + unimplemented!() + } }} - repr_serde! { @visitor_ext T T { type_kinds::Bytes } { T } - // { T: for<'a> TryFrom<&'a [u8], Error = Error> + 'static } {} - { T: From + 'static } {} - } - - repr_serde! { @select Bytes => Bytes {} {} } - + // TODO: be generic over T + // impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> + // where + // Ctx: Context, + // T: Select, impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> where Ctx: Context, - // impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> - // where - // Ctx: Context, - // T: Select, { /// #[inline] diff --git a/src/lib.rs b/src/lib.rs index 0c1ae79..2cee9b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ //! TODO: //! - utf-8 string handling/normalization //! - replace boxed callbacks with a ref -//! - ?? refactor Matcher* logic to only select nodes #![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)] #[cfg_attr(not(feature = "std"), no_std)] @@ -25,7 +24,7 @@ mod multicodec; #[path = "multihash.rs"] mod multihash_; mod representation; -mod selectors; +mod select; pub use cid; #[doc(inline)] @@ -43,53 +42,48 @@ mod specs { pub use crate::codecs_::dag_cbor::DagCbor; #[cfg(feature = "dag-json")] pub use crate::codecs_::dag_json::DagJson; - // #[cfg(feature = "dag-pb")] - // pub use crate::codecs_::dag_pb::DagPb; pub use crate::multicodec::{Codec, Multicodec}; // multiformats pub use multibase::Base as Multibase; - #[doc(hidden)] pub use multihash::{Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}; pub use multihash_::Multihash; // cid - pub use crate::cid_::*; - pub use cid::Version; + pub use crate::cid_::Cid; #[doc(hidden)] - pub use cid::{Cid as DefaultCid, CidGeneric}; + pub use cid::{Cid as DefaultCid, CidGeneric, Version}; - // data model, schemas and representation + // data model, schemas and representations pub use crate::data_model::*; #[doc(hidden)] pub use crate::representation::TypedKind as _; - pub use crate::representation::{Kind, Representation}; + pub use crate::representation::{strategies::Strategy, Kind, Representation}; pub use ipld_macros::{ipld_attr, schema}; // selectors - pub use crate::selectors::{Context, Params, Select, Selector}; + pub use crate::select::{Context, Params, Select, Selector}; // pub use ipld_macros::selector; } /// All the exports and re-exports necessary for using `ipld`. pub mod prelude { + #[doc(hidden)] + pub use crate::representation::strategies::*; #[doc(inline)] - pub use crate::codecs_::IpldVisitorExt; - #[doc(inline)] - pub use crate::specs::*; - #[doc(inline)] - pub use crate::Error; + pub use crate::{codecs_::LinkVisitor, specs::*, Error}; #[doc(hidden)] pub use serde::{Deserialize, Deserializer, Serialize, Serializer}; } /// All exports from `ipld::prelude`, plus re-exports of first- and third-party /// dependencies to aid developers wanting to implement or extend `ipld` behaviour. +#[cfg_attr(not(feature = "dev"), doc(hidden))] pub mod dev { #[doc(hidden)] pub use crate::maybestd; - pub use crate::{prelude::*, representation::*, selectors::*}; + pub use crate::{prelude::*, representation::*, select::*}; // dependency re-exports for macro convenience #[doc(hidden)] @@ -103,6 +97,10 @@ pub mod dev { pub use ipld_macros_internals::dev::*; } + #[doc(hidden)] + pub use ipld_macros_internals::dev::typenum; + #[doc(hidden)] + pub use ipld_macros_internals::dev::typenum_macro; #[doc(hidden)] pub use serde::{ self, @@ -111,14 +109,7 @@ pub mod dev { IntoDeserializer as _, MapAccess, SeqAccess, VariantAccess, Visitor, }, ser::{self, Error as _}, - Deserialize, Deserializer, Serialize, Serializer, }; - // #[doc(hidden)] - // pub use serde_repr; - #[doc(hidden)] - pub use ipld_macros_internals::dev::typenum; - #[doc(hidden)] - pub use ipld_macros_internals::dev::typenum_macro; } /// @@ -127,18 +118,20 @@ pub mod dev { pub mod maybestd { extern crate alloc; - pub use alloc::{boxed, collections, rc, vec::Vec}; + pub use alloc::{boxed, collections, rc, vec}; pub use core::{ - borrow, cell, cmp, convert, fmt, hash, iter, marker, num, ops, str, string, sync, + borrow, cell, cmp, convert, fmt, hash, iter, marker, num, ops, primitive, str, string, sync, }; pub use core2::{error, io}; + pub use std::path; } #[cfg(feature = "std")] #[doc(hidden)] pub mod maybestd { pub use core2::{error, io}; + pub use std::path; pub use std::{ - borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, num, ops, rc, str, - string, sync, vec::Vec, + borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, num, ops, + primitive, rc, str, string, sync, vec, }; } diff --git a/src/multicodec.rs b/src/multicodec.rs index 0f8d438..ece497a 100644 --- a/src/multicodec.rs +++ b/src/multicodec.rs @@ -1,5 +1,5 @@ use crate::dev::*; -use std::{ +use maybestd::{ convert::TryFrom, io::{Read, Write}, }; @@ -10,6 +10,12 @@ pub use multicodec::Multicodec; /// [Codec](https://github.com/ipld/specs/blob/master/block-layer/codecs/README.dsmd)s, /// providing methods for reading and writing blocks. pub trait Codec: TryFrom { + /// The standardized [`Multicodec`] name for this IPLD codec. + const NAME: &'static str; + + /// The standardized [`Multicodec`] code that identifies this IPLD codec. + const CODE: u64; + /// Given a dag, serialize it to a `Vec`. fn encode(&mut self, dag: &T) -> Result, Error> where @@ -48,7 +54,7 @@ mod multicodec { ($( #[cfg(feature = $feature:expr)] $(#[$meta:meta])* - $variant:ident -> $ty:ty as $name:expr, + $variant:ident -> $ty:ty, )*) => { /// A generic [multicodec]() enum. #[derive(Clone, Debug)] @@ -62,13 +68,24 @@ mod multicodec { } impl Multicodec { + #[inline] + pub const fn is_known() -> bool { + match C { + $( + #[cfg(feature = $feature)] + <$ty>::CODE => true, + )* + _ => false, + } + } + /// The standardized name of the given codec. #[inline] pub const fn name(&self) -> &'static str { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => $name, + Self::$variant(_) => <$ty>::NAME, )* // _ => unimplemented!() } @@ -92,7 +109,7 @@ mod multicodec { match name { $( #[cfg(feature = $feature)] - $name => Ok(Self::$variant(<$ty>::new())), + <$ty>::NAME => Ok(Self::$variant(<$ty>::new())), )* name => Err(Error::UnknownMulticodecName(name.to_string())) } @@ -110,108 +127,215 @@ mod multicodec { } } - #[doc(hidden)] - pub fn read_with_seed( - &mut self, - seed: SelectorSeed<'_, Ctx, T>, - reader: R, - ) -> Result<(), Error> + /// + pub fn encode(&mut self, dag: &T) -> Result, Error> where - Ctx: Context, - T: Select, - R: Read, + T: Representation, { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$ty>::read_with_seed(seed, reader), + Self::$variant(inner) => inner.encode(dag), )* + // _ => unimplemented!() } } - } - impl TryFrom for Multicodec { - type Error = Error; - #[inline] - fn try_from(code: u64) -> Result { - match code { + /// + pub fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> + where + T: Representation, + W: Write, + { + match self { $( #[cfg(feature = $feature)] - <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), + Self::$variant(inner) => inner.write(dag, writer), )* - _ => Err(Error::UnknownMulticodecCode(code)), + // _ => unimplemented!() } } - } - impl<'a> TryFrom<&'a str> for Multicodec { - type Error = Error; - #[inline] - fn try_from(s: &'a str) -> Result { - match s { + /// + pub fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result + where + T: Representation, + { + match self { $( #[cfg(feature = $feature)] - $name => Ok(Self::$variant(<$ty>::new())), + Self::$variant(inner) => inner.decode(bytes), )* - _ => Err(Error::UnknownMulticodecName(s.into())), + // _ => unimplemented!() } } - } - impl Codec for Multicodec { - fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> + /// + pub fn read(&mut self, reader: R) -> Result where T: Representation, - W: Write, + R: Read, { match self { $( #[cfg(feature = $feature)] - Self::$variant(inner) => inner.write(dag, writer), + Self::$variant(inner) => inner.read(reader), )* // _ => unimplemented!() } } - fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result + #[doc(hidden)] + pub fn read_with_seed( + &mut self, + seed: SelectorSeed<'_, Ctx, T>, + reader: R, + ) -> Result<(), Error> where - T: Representation, + Ctx: Context, + T: Select, + R: Read, { match self { $( #[cfg(feature = $feature)] - Self::$variant(inner) => inner.decode(bytes), + Self::$variant(_) => <$ty>::read_with_seed(seed, reader), )* - // _ => unimplemented!() } } - fn read(&mut self, reader: R) -> Result + #[inline] + #[doc(hidden)] + pub fn serialize_bytes( + dag: impl AsRef<[u8]>, + serializer: S, + ) -> Result where - T: Representation, - R: Read, + S: Serializer, { - match self { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::serialize_bytes(dag, serializer); + } + serializer.serialize_bytes(dag.as_ref()) + } + + #[inline] + #[doc(hidden)] + pub fn serialize_link( + cid: &Cid, + serializer: S, + ) -> Result + where + S: Serializer, + { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::serialize_link(cid, serializer); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::serialize_link(cid, serializer); + } + Serialize::serialize(&cid.inner, serializer) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_any<'de, const C: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de>, + { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_any(deserializer, visitor); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::deserialize_any(deserializer, visitor); + } + deserializer.deserialize_any(visitor) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_bytes<'de, const C: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de>, + { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_bytes(deserializer, visitor); + } + deserializer.deserialize_bytes(visitor) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_link<'de, const C: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de>, + { + #[cfg(feature = "dag-json")] + if C == DagJson::CODE { + return DagJson::deserialize_link(deserializer, visitor); + } + #[cfg(feature = "dag-cbor")] + if C == DagCbor::CODE { + return DagCbor::deserialize_link(deserializer, visitor); + } + deserializer.deserialize_any(visitor) + } + } + + impl TryFrom for Multicodec { + type Error = Error; + #[inline] + fn try_from(code: u64) -> Result { + match code { $( #[cfg(feature = $feature)] - Self::$variant(inner) => inner.read(reader), + <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), )* - // _ => unimplemented!() + _ => Err(Error::UnknownMulticodecCode(code)), + } + } + } + + impl<'a> TryFrom<&'a str> for Multicodec { + type Error = Error; + #[inline] + fn try_from(s: &'a str) -> Result { + match s { + $( + #[cfg(feature = $feature)] + <$ty>::NAME => Ok(Self::$variant(<$ty>::new())), + )* + _ => Err(Error::UnknownMulticodecName(s.into())), } } } }} impl_multicodec! { - // Raw -> Raw as "raw", #[cfg(feature = "dag-cbor")] /// - DagCbor -> DagCbor as "dag-cbor", + DagCbor -> DagCbor, #[cfg(feature = "dag-json")] /// - DagJson -> DagJson as "dag-json", - // DagJose -> DagJose as "dag-jose", - // DagBipf -> DagBipf as "dag-bipf", + DagJson -> DagJson, // Custom(Box), } diff --git a/src/representation/mod.rs b/src/representation/mod.rs index a66350d..60bedc9 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -9,7 +9,8 @@ //! type from/to bytes, as well query and mutate a type, while specifically //! defining for the type it's `Context` requirements for these operations. -mod strategies; +#[doc(hidden)] +pub mod strategies; use crate::dev::*; use downcast_rs::{impl_downcast, Downcast}; @@ -18,9 +19,6 @@ use maybestd::{fmt, marker::PhantomData, str::FromStr}; pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKind}; -#[doc(hidden)] -pub use strategies::*; - // /// // #[derive(Debug, Eq, Hash, PartialEq)] // pub struct Field { @@ -109,36 +107,38 @@ pub trait Representation: Sized { const SCHEMA: &'static str; /// The IPLD [Data Model Kind](https://ipld.io/docs/data-model/kinds/) of - /// the type, which would inform a user of its access patterns. - const DATA_MODEL_KIND: Kind; // Self::DATA_MODEL_KIND::KIND + /// the type, which denotes the access API and executable [`Selector`]s. + const DATA_MODEL_KIND: Kind = Self::DataModelKind::KIND; - /// The IPLD [Schema - /// Kind](https://ipld.io/docs/schemas/features/typekinds/#schema-kinds) of - /// the type. - const SCHEMA_KIND: Kind = Self::DATA_MODEL_KIND; + /// The IPLD [Schema Kind](https://ipld.io/docs/schemas/features/typekinds/) + /// of the type, which denotes how the type is defined by its schema. + const SCHEMA_KIND: Kind = Self::SchemaKind::KIND; - /// The IPLD [Representation Kind]() of the type, which would inform a user of how the type is represented when encoded. - // const REPR_KIND: Kind = Self::DATA_MODEL_KIND; + /// The IPLD [Representation Kind]() of the type, which, in combination with + /// the [`Representation::REPR_STRATEGY`], denotes how the type is + /// represented on-disk by any given codec. const REPR_KIND: Kind = Self::ReprKind::KIND; - // const IS_ADL: bool = false; + /// The IPLD specific [Representation]() [`Strategy`] used to encode this + /// type. + const REPR_STRATEGY: Strategy = Strategy::DataModel; /// Marker for types that can have any representation *and* should be /// ignored entirely during selection/deserialization. #[doc(hidden)] const __IGNORED: bool = false; - // /// Marker type for exact `u32` value of the type's - // /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket - // /// implementations of various traits. - // #[doc(hidden)] - // type DATA_MODEL_KIND: TypedKind; + /// Marker type for exact `u32` value of the type's + /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket + /// implementations of various traits. + #[doc(hidden)] + type DataModelKind: TypedKind; - // /// Marker type for exact `u32` value of the type's - // /// [`Representation::SCHEMA_KIND`], needed for internal blanket - // /// implementations of various traits. - // #[doc(hidden)] - // type SCHEMA_KIND: TypedKind; + /// Marker type for exact `u32` value of the type's + /// [`Representation::SCHEMA_KIND`], needed for internal blanket + /// implementations of various traits. + #[doc(hidden)] + type SchemaKind: TypedKind; /// Marker type for exact `u32` value of the type's /// [`Representation::REPR_KIND`], needed for internal blanket @@ -154,7 +154,8 @@ pub trait Representation: Sized { const HAS_LINKS: bool = Self::IS_LINK; /// The type's `Select`able static field names and their IPLD Schema kinds. - const FIELDS: &'static [()] = &[]; + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &[]; /// /// for unions, this ?should delegate to the variant's type name' @@ -324,25 +325,24 @@ pub trait Representation: Sized { } /// -pub trait StringRepresentation +pub trait StringRepresentation: Representation where - Self: Representation - + Clone - + fmt::Display - + FromStr - + Ord, + Self: Clone + FromStr + fmt::Display + Ord, + ::Err: fmt::Display, { } -impl StringRepresentation for T where - T: Representation - + Clone - + fmt::Display - + FromStr - + Ord +impl StringRepresentation for T +where + T: Representation + Clone + FromStr + fmt::Display + Ord, + ::Err: fmt::Display, { } -trait AdvancedRepresentation: Representation + Select {} +/// +pub trait BytesRepresentation: Representation {} + +/// +pub trait AdvancedRepresentation: Representation + Select {} /// /// TODO: possibly look at erased-serde to complete this "hack" diff --git a/src/representation/strategies/bytesprefix.rs b/src/representation/strategies/bytesprefix.rs new file mode 100644 index 0000000..8770d6e --- /dev/null +++ b/src/representation/strategies/bytesprefix.rs @@ -0,0 +1,3 @@ +use crate::dev::*; + +const STRATEGY: Strategy = Strategy::BytesPrefix; diff --git a/src/representation/strategies/listpairs.rs b/src/representation/strategies/listpairs.rs new file mode 100644 index 0000000..987eea6 --- /dev/null +++ b/src/representation/strategies/listpairs.rs @@ -0,0 +1,457 @@ +use crate::dev::*; +use macros::{ + derive_more::{AsMut, AsRef, Deref, Index, IndexMut, IntoIterator}, + repr_serde, +}; +use maybestd::{fmt, marker::PhantomData, str::FromStr}; + +const STRATEGY: Strategy = Strategy::ListPairs; + +/* +// Blanket impl for maps. +repr_serde! { @visitors for T => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::List) } + { T, K, V } { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A list of type {} of {}", S::NAME, T::NAME) + } + + // #[inline] + // fn visit_seq(self, seq: A) -> Result + // where + // A: SeqAccess<'de>, + // { + // if let Some(s) = self.0.selector.as_explore_union() { + // if s.matches_first() { + // let list = S::deserialize::(SeqAccessDeserializer::new(seq))?; + // // todo: for each selector, __select_in + // return list.__select_in(self.0).map_err(A::Error::custom); + // } else { + // // todo: support multiple non-overlapping ranges + // } + // } + + // let iter = SerdeListIterator::<'de, _>::from(seq); + // match self.0.selector { + // Selector::Matcher(_) => { + // self.0.match_list::( + // iter, + // |_| RefCell::default(), + // |dag| Box::new(|child, _| Ok(dag.borrow_mut().extend(iter::once(child)))), + // RefCell::into_inner, + // ).map_err(A::Error::custom) + // }, + // Selector::ExploreIndex(s) => self.0 + // .explore_list_range::(iter, s.to_range()) + // .map_err(A::Error::custom), + // Selector::ExploreRange(s) => self.0 + // .explore_list_range::(iter, s.to_range()) + // .map_err(A::Error::custom), + // Selector::ExploreAll(s) => self.0 + // .explore_list_range::(iter, s.to_range()) + // .map_err(A::Error::custom), + // _ => Err(A::Error::custom(Error::unsupported_selector::( + // self.0.selector, + // ))), + // } + // } +}} + */ + +// /// +// #[derive( +// AsRef, +// AsMut, +// Clone, +// Debug, +// Deref, +// // DerefMut, +// Eq, +// Hash, +// Index, +// IndexMut, +// IntoIterator, +// Ord, +// PartialEq, +// PartialOrd, +// )] +// #[as_ref(forward)] +// #[deref(forward)] +// pub struct ListPairsMap(Map); + +// impl Default for ListPairsMap { +// fn default() -> Self { +// Self(Map::new()) +// } +// } + +// type ListPair = StructTuple2<(K, V), K, V>; +// type ListPairRef<'a, K, V> = StructTupleRef2<'a, (K, V), K, V>; + +// impl Representation for ListPairsMap +// where +// // TODO: remove clone requirement by switching up callbacks +// K: Representation + AsRef + Clone + Ord, +// V: Representation, +// { +// type ReprKind = type_kinds::List; + +// const NAME: &'static str = "Map"; +// const SCHEMA: &'static str = concat!( +// "type Map {", +// stringify!(K::NAME), +// ":", +// stringify!(V::NAME), +// "} representation listpairs", +// ); +// const DATA_MODEL_KIND: Kind = Kind::Map; +// // const REPR_KIND: Kind = Kind::List; + +// fn has_links(&self) -> bool { +// self.0.has_links() +// } + +// #[inline] +// #[doc(hidden)] +// fn serialize(&self, serializer: S) -> Result +// where +// S: Serializer, +// { +// use ser::SerializeSeq; + +// let mut seq = serializer.serialize_seq(Some(self.0.len()))?; +// for listpair in self.0.iter().map(ListPairRef::::from) { +// seq.serialize_element(&SerializeWrapper::<'_, C, _>(&listpair))?; +// } +// seq.end() +// } + +// #[inline] +// #[doc(hidden)] +// fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// struct ListPairsMapVisitor(PhantomData<(K, V)>); +// impl<'de, const C: u64, K, V> Visitor<'de> for ListPairsMapVisitor +// where +// K: Representation + Ord, +// V: Representation, +// { +// type Value = ListPairsMap; +// #[inline] +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// write!(f, "A map of `{}` to `{}` listpairs", K::NAME, V::NAME) +// } +// #[inline] +// fn visit_seq(self, mut seq: A) -> Result +// where +// A: SeqAccess<'de>, +// { +// let mut map = ListPairsMap::default(); +// while let Some(listpair) = +// seq.next_element_seed(DeserializeWrapper::>::new())? +// { +// map.0.insert(listpair.0, listpair.1); +// } +// Ok(map) + +// // let mut new_map = Map::new(); +// // let mut iter = SerdeListPairsIterator::<'de, A>::from(map); +// // while let Some(key) = +// // as MapIterator>::next_key::(&mut iter, None) +// // .map_err(A::Error::custom)? +// // { +// // let val = key +// // .as_field() +// // .ok_or_else(|| Error::explore_key_failure::(None)) +// // .and_then(|field| { +// // as MapIterator>::next_value::( +// // &mut iter, &field, +// // ) +// // }) +// // .map_err(A::Error::custom)?; +// // new_map.insert(key, val); +// // } +// // Ok(new_map) +// } +// } + +// deserializer.deserialize_seq(ListPairsMapVisitor::(PhantomData)) +// } +// } + +mod iterators { + use super::*; + use de::value::SeqAccessDeserializer; + + // /// An iterator over a key-value pair represented as a serde list. + // #[derive(Debug)] + // pub struct SerdeListPairIterator<'de, A> + // where + // A: SeqAccess<'de>, + // { + // inner: A, + // _t: PhantomData<&'de ()>, + // } + + // impl<'de, T, A> ListIterator for SerdeListPairIterator<'de, A> where A: SeqAccess<'de> {} + + /// + #[doc(hidden)] + #[derive(Debug)] + pub struct SerdeListPairsIterator<'de, A> + where + A: SeqAccess<'de>, + { + inner: A, + // key: Option>, + // pair_de: Option>, + _t: PhantomData<&'de ()>, + } + + impl<'de, A> From for SerdeListPairsIterator<'de, A> + where + A: SeqAccess<'de>, + { + fn from(inner: A) -> Self { + Self { + inner, + // key: None, + // pair_de: None, + _t: PhantomData, + } + } + } + + impl<'de, K, V, A> MapIterator for SerdeListPairsIterator<'de, A> + where + A: SeqAccess<'de>, + { + fn size_hint(&self) -> Option { + self.inner.size_hint() + } + + fn field(&self) -> Field<'_> { + unimplemented!() + } + + /// + /// pass a visitor that deserializes the key, and if the field_name matches, deserializes the value + fn next_key( + &mut self, + expected_field_name: Option<&'static str>, + ) -> Result, Error> + where + K: Representation, + { + // let key = self + // .inner + // .next_key_seed(DeserializeWrapper::::default()) + // .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; + + // // TODO: assert that key == expected_field_name + // Ok(key) + unimplemented!() + } + + fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { + // self.inner + // .next_value::() + // .or_else(|_| Err(Error::explore_value_failure::(field)))?; + // Ok(()) + unimplemented!() + } + + fn next_value(&mut self, field: &Field<'_>) -> Result + where + V: Representation, + { + // self.inner + // .next_value_seed(DeserializeWrapper::::default()) + // .or_else(|_| Err(Error::explore_value_failure::(field))) + unimplemented!() + } + + fn next_value_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + // field: &Field<'_>, + ) -> Result<(), Error> + where + K: Representation, + V: Select, + { + // let key = >::key(self); + // let field = Representation::as_field(key); + // let field = self.field(); + // let err = || Error::explore_value_failure::(field); + + // V::__select_map::(seed, &mut self.inner, false) + // .ok() + // .flatten() + // .ok_or_else(|| Error::explore_value_failure::(field)) + unimplemented!() + } + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! listpairs { + ($name:ident $ref_name:ident => $($ty:ident)*) => { + /// Type that implements selection against tuple-represented structs. + #[doc(hidden)] + // #[derive(Clone, Debug, From)] + pub struct $ref_name<'a, T, $($ty,)*>($(pub &'a $ty,)* PhantomData); + + impl<'a, T, $($ty,)*> $ref_name<'a, T, $($ty,)*> + where + // T: Representation, + $($ty: Representation,)* + { + pub(crate) const LEN: usize = $crate::tuple!(@len $($ty)*); + } + + // impl<'a, T, $($ty,)*> From<&'a ($($ty,)*)> + // for $ref_name<'a, T, $($ty,)*> + // { + // #[inline] + // fn from(($($ty,)*): &'a ($($ty,)*)) -> Self { + // Self($($ty,)* PhantomData) + // } + // } + + // impl<'a, T, $($ty,)*> From<($(&'a $ty,)*)> + // for $ref_name<'a, T, $($ty,)*> + // { + // #[inline] + // fn from(($($ty,)*): ($(&'a $ty,)*)) -> Self { + // Self($($ty,)* PhantomData) + // } + // } + + // impl<'a, T, $($ty,)*> From<&'a $name> + // for $ref_name<'a, T, $($ty,)*> + // { + // #[inline] + // fn from(tuple: &'a $name) -> Self { + // let $name($(ref $ty,)* _) = tuple; + // Self($($ty,)* PhantomData) + // } + // } + + /// + #[doc(hidden)] + // #[derive(Clone, Debug, From)] + pub struct $name($(pub $ty,)* PhantomData); + + impl $name + where + // T: Representation, + $($ty: Representation,)* + { + pub(crate) const LEN: usize = $crate::tuple!(@len $($ty)*); + } + + // impl From<($($ty,)*)> for $name { + // fn from(($($ty,)*): ($($ty,)*)) -> Self { + // Self($($ty,)* PhantomData) + // } + // } + + const _: () = { + impl<'a, T, $($ty,)*> Representation for $ref_name<'a, T, $($ty,)*> + where + T: Representation, + $($ty: Representation,)* + { + $crate::tuple!(@repr_consts $ref_name List => $($ty)*); + + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + use ser::SerializeSeq; + + // let Self($($ty,)* _) = self; + // let mut seq = serializer.serialize_seq(Some(Self::LEN))?; + // $( + // seq.serialize_element(&SerializeWrapper::<'_, MC, $ty>($ty))?; + // )* + // seq.end() + unimplemented!() + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result + where + De: Deserializer<'de>, + { + unreachable!( + "cannot deserialize {}; use {}::as_ref instead", + stringify!($ref_name), + stringify!($name), + ) + } + } + + impl Representation for $name + where + T: Representation, + $($ty: Representation,)* + { + const NAME: &'static str = stringify!($name); + const SCHEMA: &'static str = ""; + const DATA_MODEL_KIND: Kind = Kind::List; + const SCHEMA_KIND: Kind = Kind::Struct; + const REPR_KIND: Kind = Kind::List; + const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; + + $crate::tuple!(@repr_consts $name List => $($ty)*); + + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + // $ref_name::from(self).serialize::(serializer) + unimplemented!() + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result + where + De: Deserializer<'de>, + { + // Ok(Self::from(<($($ty,)*)>::deserialize::(deserializer)?)) + unimplemented!() + } + } + }; + }; +} + +// listpairs!(ListPairsStruct2 ListPairsStructRef2 => A B); +// listpairs!(ListPairsStruct3 ListPairsStructRef3 => A B C); +// listpairs!(ListPairsStruct4 ListPairsStructRef4 => A B C D); +// listpairs!(ListPairsStruct5 ListPairsStructRef5 => A B C D E); +// listpairs!(ListPairsStruct6 ListPairsStructRef6 => A B C D E F); +// listpairs!(ListPairsStruct7 ListPairsStructRef7 => A B C D E F G); +// listpairs!(ListPairsStruct8 ListPairsStructRef8 => A B C D E F G H); +// listpairs!(ListPairsStruct9 ListPairsStructRef9 => A B C D E F G H I); +// listpairs!(ListPairsStruct10 ListPairsStructRef10 => A B C D E F G H I J); +// listpairs!(ListPairsStruct11 ListPairsStructRef11 => A B C D E F G H I J K); +// listpairs!(ListPairsStruct12 ListPairsStructRef12 => A B C D E F G H I J K L); +// listpairs!(ListPairsStruct13 ListPairsStructRef13 => A B C D E F G H I J K L M); +// listpairs!(ListPairsStruct14 ListPairsStructRef14 => A B C D E F G H I J K L M N); +// listpairs!(ListPairsStruct15 ListPairsStructRef15 => A B C D E F G H I J K L M N O); +// listpairs!(ListPairsStruct16 ListPairsStructRef16 => A B C D E F G H I J K L M N O P); +// listpairs!(ListPairsStruct17 ListPairsStructRef17 => A B C D E F G H I J K L M N O P Q); +// listpairs!(ListPairsStruct18 ListPairsStructRef18 => A B C D E F G H I J K L M N O P Q R); +// listpairs!(ListPairsStruct19 ListPairsStructRef19 => A B C D E F G H I J K L M N O P Q R S); diff --git a/src/representation/strategies/mod.rs b/src/representation/strategies/mod.rs new file mode 100644 index 0000000..34f06f5 --- /dev/null +++ b/src/representation/strategies/mod.rs @@ -0,0 +1,219 @@ +mod bytesprefix; +#[macro_use] +mod listpairs; +mod stringjoin; +mod stringpairs; +mod stringprefix; +#[macro_use] +mod tuple; + +#[doc(hidden)] +pub use tuple::*; + +use crate::dev::*; +use maybestd::marker::PhantomData; + +/// +#[repr(u8)] +pub enum Strategy { + DataModel = 'd' as u8, + BytesPrefix = 'b' as u8, + Envelope = 'e' as u8, + Inline = 'i' as u8, + Keyed = 'k' as u8, + ListPairs = 'l' as u8, + StringJoin = 'j' as u8, + StringPairs = 'p' as u8, + StringPrefix = 's' as u8, + Tuple = 't' as u8, +} + +impl Strategy { + // pub const fn dm_kind(repr_kind: Kind) -> Kind { + // match repr_kind { + // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, + // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, + // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, + // _ if S == Self::StringPairs as u8 => Kind::String, + // Kind::Union if S == Self::StringPrefix as u8 => Kind::Map, + // _ if S == Self::Tuple as u8 => Kind::List, + // _ => panic!(), + // } + // } + + // pub const fn schema_kind() -> Kind { + // match S { + // _ if S == Self::BytesPrefix as u8 => Kind::Union, + // _ if S == Self::ListPairs as u8 => Kind::Struct, + // _ if S == Self::StringJoin as u8 => Kind::Struct, + // _ if S == Self::StringPairs as u8 => Kind::Struct, + // _ if S == Self::StringPrefix as u8 => Kind::Union, + // _ if S == Self::Tuple as u8 => Kind::Struct, + // _ => panic!(), + // } + // } + + // pub const fn repr_kind() -> Kind { + // match S { + // _ if S == Self::BytesPrefix as u8 => Kind::Bytes, + // _ if S == Self::ListPairs as u8 => Kind::List, + // _ if S == Self::StringJoin as u8 => Kind::String, + // _ if S == Self::StringPairs as u8 => Kind::String, + // _ if S == Self::StringPrefix as u8 => Kind::String, + // _ if S == Self::Tuple as u8 => Kind::List, + // _ => panic!(), + // } + // } +} + +/// An iterator over the elements of a list-like type, whether produced from an +/// in-memory type or from an underlying [`Representation`]. +#[doc(hidden)] +pub trait ListIterator { + fn size_hint(&self) -> Option; + + fn field(&self) -> Field<'_>; + + fn next_ignored(&mut self) -> Result; + + fn next(&mut self) -> Result, Error> + where + T: Representation, + { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + } + + fn next_ref(&mut self) -> Result, Error> + where + T: Representation, + { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + } + + fn next_ref_mut(&mut self) -> Result, Error> + where + T: Representation, + { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + } + + fn next_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, T>, + ) -> Result + where + T: Select; +} + +/// An iterator over the keys and values of a map-like type, whether produced +/// from an in-memory type or from an underlying [`Representation`]. +#[doc(hidden)] +pub trait MapIterator { + fn size_hint(&self) -> Option; + + fn field(&self) -> Field<'_>; + + fn next_key( + &mut self, + expected_field_name: Option<&'static str>, + ) -> Result, Error> + where + K: Representation; + + fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error>; + + fn next_value(&mut self, field: &Field<'_>) -> Result + where + V: Representation, + { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + } + + fn next_value_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + // field: &Field<'_>, + ) -> Result<(), Error> + where + K: Representation, + V: Select; + + // fn next_entry<'a, const C: u64>( + // &mut self, + // // seed: SelectorSeed<'a, Ctx, V>, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result, Error> + // where + // K: Representation, + // { + // unimplemented!() + // } + + // fn next_entry_seed<'a, const C: u64, T, Ctx: Context>( + // &mut self, + // root_seed: &mut SelectorSeed<'a, Ctx, T>, + // // seeder: F, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result + // where + // T: Representation, + // K: Representation, + // V: Select, + // // F: FnOnce(K) -> Result>, Error>, + // { + // let key = if let Some(key) = self.next_key::(None)? { + // key + // } else { + // return Ok(true); + // }; + + // root_seed.select_field::(root_seed.) + + // Ok(false) + // } + + // /// + // /// impl DeSeed and Visitor::visit_seq for some type + // /// if key matches, create field select seed and call V::__select_map + // /// else, ignore value + // /// return is_empty + // fn next_entry_seed<'a, const C: u64, Ctx: Context, F>( + // &'a mut self, + // // seed: SelectorSeed<'a, Ctx, V>, + // seeder: F, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result + // where + // Ctx: 'a, + // K: Representation, + // V: Select, + // F: FnOnce(K) -> Result, Error>, + // { + // let key = if let Some(key) = self.next_key::(None)? { + // key + // } else { + // return Ok(true); + // }; + + // self.next_value_seed::(seeder(key)?)?; + // Ok(false) + // } +} + +// impl<'a, const C: u64, F, Ctx, T, O> RepresentationIterator<'a, C, F, Ctx, T, O> +// where +// F: FnMut(SelectorSeed<'a, Ctx, T>) -> Result, +// Ctx: Context, +// T: Select, +// { +// // fn next(&mut self, seed: SelectorSeed<'a, Ctx, T>) -> Result<(), Error> { + +// // } + +// fn next_with_seed(&mut self, seed: SelectorSeed<'a, Ctx, T>) -> Result { +// (self.func)(seed) +// } +// } diff --git a/src/representation/strategies/stringjoin.rs b/src/representation/strategies/stringjoin.rs new file mode 100644 index 0000000..ea45770 --- /dev/null +++ b/src/representation/strategies/stringjoin.rs @@ -0,0 +1,22 @@ +use crate::dev::*; + +const STRATEGY: Strategy = Strategy::StringJoin; + +/* +// Blanket impl for structs. +macro_rules! stringjoin { + () => { + repr_serde! { @visitors for T => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::String) } + { T, K, V } { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A list of type {} of {}", S::NAME, T::NAME) + } + } + } +} + */ diff --git a/src/representation/strategies/stringpairs.rs b/src/representation/strategies/stringpairs.rs new file mode 100644 index 0000000..3b5081c --- /dev/null +++ b/src/representation/strategies/stringpairs.rs @@ -0,0 +1,194 @@ +use crate::dev::*; +use maybestd::{borrow::Cow, fmt, str::FromStr}; + +const STRATEGY: Strategy = Strategy::StringPairs; + +/* +// Blanket impl for maps. +repr_serde! { @visitors for T => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::String) } + { T, K, V } { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A list of type {} of {}", S::NAME, T::NAME) + } +} + */ + +/* +// Blanket impl for structs. +macro_rules! stringpairs { + () => { + repr_serde! { @visitors for T => (K, V) + { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::String) } + { T, K, V } { T: Default + Extend<(K, V)> + 'static, + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A list of type {} of {}", S::NAME, T::NAME) + } + } + } +} + */ + +/* +/// +#[derive(Debug)] +pub struct StringPairsMap(pub Map) +where + K: StringRepresentation, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display; + +// type StringPair = Tuple2<{ Strategy::Tuple as u8 }, (K, V), K, V>; +// type StringPairRef<'a, K, V> = TupleRef2<'a, { Strategy::Tuple as u8 }, (K, V), K, V>; + +impl Default for StringPairsMap +where + K: StringRepresentation, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display, +{ + fn default() -> Self { + Self(Default::default()) + } +} + +// TODO: impl Display for StringPairsIter +impl fmt::Display for StringPairsMap +where + K: StringRepresentation, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let last_idx = self.0.len() - 1; + for (idx, (key, val)) in self.0.iter().enumerate() { + key.fmt(f)?; + I.fmt(f)?; + val.fmt(f)?; + if idx < last_idx { + E.fmt(f)?; + } + } + + Ok(()) + } +} + +impl FromStr for StringPairsMap +where + K: StringRepresentation, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display, +{ + type Err = Error; + + fn from_str(s: &str) -> Result { + unimplemented!() + } +} + +impl Representation for StringPairsMap +where + // TODO: remove clone requirement by switching up callbacks + K: StringRepresentation + AsRef + Clone + Ord, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display, +{ + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Map; + type ReprKind = type_kinds::String; + + const NAME: &'static str = "Map"; + const SCHEMA: &'static str = concat!( + "type Map {", + stringify!(K::NAME), + ":", + stringify!(V::NAME), + "} representation stringpairs {", + "}", + ); + const DATA_MODEL_KIND: Kind = Kind::Map; + // const REPR_KIND: Kind = Kind::List; + + fn has_links(&self) -> bool { + self.0.iter().any(|(k, v)| k.has_links() || v.has_links()) + } + + #[inline] + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use ser::SerializeSeq; + + // let mut seq = serializer.serialize_seq(Some(self.0.len()))?; + // for listpair in self.0.iter().map(StringPairRef::::from) { + // seq.serialize_element(&SerializeWrapper::<'_, C, _>(&listpair))?; + // } + // seq.end() + unimplemented!() + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + /* + struct StringPairsMapVisitor( + PhantomData<(K, V)>, + ); + impl<'de, const C: u64, const I: char, const E: char, K, V> Visitor<'de> + for StringPairsMapVisitor + where + K: StringRepresentation + AsRef + Ord, + V: StringRepresentation, + ::Err: fmt::Display, + ::Err: fmt::Display, + { + type Value = StringPairsMap; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A map of `{}` to `{}` listpairs", K::NAME, V::NAME) + } + #[inline] + fn visit_str(self, s: &str) -> Result { + let mut map = StringPairsMap::default(); + + // TODO: move this to StringPairsIter + while let Some(pair) = s.split(E).map(|s| s.split_once(I)).next() { + let (key_str, val_str) = pair.ok_or_else(|| Er::custom("missing pair"))?; + + let key = K::from_str(key_str).map_err(Er::custom)?; + let val = V::from_str(val_str).map_err(Er::custom)?; + + map.0.insert(key, val); + } + + Ok(map) + } + } + + deserializer.deserialize_str(StringPairsMapVisitor::(PhantomData)) + */ + + let s = Cow::<'_, str>::deserialize(deserializer)?; + Self::from_str(s.as_ref()).map_err(D::Error::custom) + } +} + */ diff --git a/src/representation/strategies/stringprefix.rs b/src/representation/strategies/stringprefix.rs new file mode 100644 index 0000000..6292631 --- /dev/null +++ b/src/representation/strategies/stringprefix.rs @@ -0,0 +1,3 @@ +use crate::dev::*; + +const STRATEGY: Strategy = Strategy::StringPrefix; diff --git a/src/representation/strategies/tuple.rs b/src/representation/strategies/tuple.rs new file mode 100644 index 0000000..6931ff7 --- /dev/null +++ b/src/representation/strategies/tuple.rs @@ -0,0 +1,412 @@ +use crate::dev::*; +use macros::derive_more::From; +use maybestd::{fmt, marker::PhantomData}; + +#[doc(hidden)] +#[macro_export] +macro_rules! tuple { + ($name:ident $ref_name:ident => $($ty:ident)*) => { + /// Type that implements selection against tuple-represented structs. + #[doc(hidden)] + #[derive(Clone, Debug, From)] + pub struct $ref_name<'a, T = Any, $($ty = Any,)*>($(pub &'a $ty,)* PhantomData); + + impl<'a, T, $($ty,)*> $ref_name<'a, T, $($ty,)*> + where + T: Representation, + $($ty: Representation,)* + { + pub(crate) const LEN: usize = tuple!(@len $($ty)*); + } + + impl<'a, T, $($ty,)*> From<&'a ($($ty,)*)> + for $ref_name<'a, T, $($ty,)*> + { + #[inline] + fn from(($($ty,)*): &'a ($($ty,)*)) -> Self { + Self($($ty,)* PhantomData) + } + } + + impl<'a, T, $($ty,)*> From<($(&'a $ty,)*)> + for $ref_name<'a, T, $($ty,)*> + { + #[inline] + fn from(($($ty,)*): ($(&'a $ty,)*)) -> Self { + Self($($ty,)* PhantomData) + } + } + + impl<'a, T, $($ty,)*> From<&'a $name> + for $ref_name<'a, T, $($ty,)*> + { + #[inline] + fn from(tuple: &'a $name) -> Self { + let $name($(ref $ty,)* _) = tuple; + Self($($ty,)* PhantomData) + } + } + + /// + #[doc(hidden)] + #[derive(Clone, Debug, From)] + pub struct $name($(pub $ty,)* PhantomData); + + impl $name + where + T: Representation, + $($ty: Representation,)* + { + pub(crate) const LEN: usize = tuple!(@len $($ty)*); + } + + impl From<($($ty,)*)> for $name { + fn from(($($ty,)*): ($($ty,)*)) -> Self { + Self($($ty,)* PhantomData) + } + } + + const _: () = { + tuple!(@tuple $name $ref_name => $($ty)*); + }; + const _: () = { + tuple!(@struct_tuple $name $ref_name => $($ty)*); + }; + const _: () = { + // tuple!(listpairs! $name $ref_name => $($ty)*); + }; + const _: () = { + // tuple!(stringjoin! $name $ref_name => $($ty)*); + }; + const _: () = { + // tuple!(stringpairs! $name $ref_name => $($ty)*); + }; + const _: () = { + // tuple!(stringprefix! $name $ref_name => $($ty)*); + }; + }; + (@repr_ext $name:ident $repr:ident => $($ty:ident)*) => { + fn has_links(&self) -> bool { + // let ($($ty,)*) = self; + // false $(| $ty.has_links())* + unimplemented!() + } + }; + (@len) => (0); + (@len $first:ident $($ty:ident)*) => (1usize + $crate::tuple!(@len $($ty)*)); + // ($macro_name:ident! $name:ident $ref_name:ident => $($ty:ident)*) => { + // $macro_name!($name $ref_name => $($ty)*); + // }; + (@tuple $name:ident $ref_name:ident => $($ty:ident)*) => { + const LEN: usize = $crate::tuple!(@len $($ty)*); + + impl<$($ty,)*> Representation for ($($ty,)*) + where + $($ty: Representation,)* + { + type DataModelKind = type_kinds::List; + type SchemaKind = type_kinds::Struct; + type ReprKind = type_kinds::List; + + const NAME: &'static str = stringify!($name); + const SCHEMA: &'static str = ""; + const DATA_MODEL_KIND: Kind = Kind::List; + const SCHEMA_KIND: Kind = Kind::Struct; + const REPR_KIND: Kind = Kind::List; + const REPR_STRATEGY: Strategy = Strategy::Tuple; + const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; + + $crate::tuple!(@repr_ext $name List => $($ty)*); + + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + <$ref_name<'_, Null, $($ty,)*>>::from(self) + .serialize::(serializer) + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result + where + De: Deserializer<'de>, + { + struct TupleVisitor(PhantomData<($($ty,)*)>); + impl<'de, const MC: u64, $($ty,)*> Visitor<'de> for TupleVisitor + where + $($ty: Representation,)* + { + type Value = ($($ty,)*); + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A tuple of {} elements", LEN) + } + #[inline] + fn visit_seq(self, mut seq: Ac) -> Result + where + Ac: SeqAccess<'de>, + { + Ok(( + $(seq + .next_element_seed(DeserializeWrapper::::new())? + .ok_or_else(|| Ac::Error::missing_field(""))? + ,)* + )) + } + } + + deserializer.deserialize_seq(TupleVisitor::(PhantomData)) + } + } + }; + (@struct_tuple $name:ident $ref_name:ident => $($ty:ident)*) => { + impl<'a, T, $($ty,)*> Representation for $ref_name<'a, T, $($ty,)*> + where + T: Representation, + $($ty: Representation,)* + { + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Struct; + type ReprKind = type_kinds::List; + + const NAME: &'static str = stringify!($name); + const SCHEMA: &'static str = ""; + const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Struct; + const REPR_KIND: Kind = Kind::List; + const REPR_STRATEGY: Strategy = Strategy::Tuple; + const FIELDS: &'static [&'static str] = T::FIELDS; + const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; + + $crate::tuple!(@repr_ext $ref_name List => $($ty)*); + + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + use ser::SerializeSeq; + + let Self($($ty,)* _) = self; + let mut seq = serializer.serialize_seq(Some(Self::LEN))?; + $( + seq.serialize_element(&SerializeWrapper::<'_, MC, $ty>($ty))?; + )* + seq.end() + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const MC: u64, De>(_: De) -> Result + where + De: Deserializer<'de>, + { + unreachable!( + "cannot deserialize {}; use {}::as_ref instead", + stringify!($ref_name), + stringify!($name), + ) + } + } + + impl Representation for $name + where + T: Representation, + $($ty: Representation,)* + { + type DataModelKind = type_kinds::Map; + type SchemaKind = type_kinds::Struct; + type ReprKind = type_kinds::List; + + const NAME: &'static str = stringify!($name); + const SCHEMA: &'static str = ""; + const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Struct; + const REPR_KIND: Kind = Kind::List; + const REPR_STRATEGY: Strategy = Strategy::Tuple; + const FIELDS: &'static [&'static str] = T::FIELDS; + const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; + + $crate::tuple!(@repr_ext $name List => $($ty)*); + + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + $ref_name::from(self).serialize::(serializer) + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result + where + De: Deserializer<'de>, + { + Ok(Self::from(<($($ty,)*)>::deserialize::(deserializer)?)) + } + } + + // // Blanket impls for structs. + // repr_serde! { @visitors for T => $name + // { @dk type_kinds::Map @sk type_kinds::Struct @rk type_kinds::List } + // { T, $($ty)* } + // { T: Default + TryFrom<($($ty,)*)> + 'static, + // >::Error: fmt::Display, + // $($ty: Select + 'static,)*, } @serde { + // } + // }; + }; +} + +tuple!(StructTuple2 StructTupleRef2 => A B); +tuple!(StructTuple3 StructTupleRef3 => A B C); +tuple!(StructTuple4 StructTupleRef4 => A B C D); +tuple!(StructTuple5 StructTupleRef5 => A B C D E); +tuple!(StructTuple6 StructTupleRef6 => A B C D E F); +tuple!(StructTuple7 StructTupleRef7 => A B C D E F G); +tuple!(StructTuple8 StructTupleRef8 => A B C D E F G H); +tuple!(StructTuple9 StructTupleRef9 => A B C D E F G H I); +tuple!(StructTuple10 StructTupleRef10 => A B C D E F G H I J); +tuple!(StructTuple11 StructTupleRef11 => A B C D E F G H I J K); +tuple!(StructTuple12 StructTupleRef12 => A B C D E F G H I J K L); +tuple!(StructTuple13 StructTupleRef13 => A B C D E F G H I J K L M); +tuple!(StructTuple14 StructTupleRef14 => A B C D E F G H I J K L M N); +tuple!(StructTuple15 StructTupleRef15 => A B C D E F G H I J K L M N O); +tuple!(StructTuple16 StructTupleRef16 => A B C D E F G H I J K L M N O P); +tuple!(StructTuple17 StructTupleRef17 => A B C D E F G H I J K L M N O P Q); +tuple!(StructTuple18 StructTupleRef18 => A B C D E F G H I J K L M N O P Q R); +tuple!(StructTuple19 StructTupleRef19 => A B C D E F G H I J K L M N O P Q R S); + +// impl_tuple!(@repr Tuple12 Tuple12RefTuple2Ref => A B C D E F G H I J K L { + +// } { +// fn serialize(&self, serializer: Se) -> Result +// where +// Se: Serializer, +// { +// use ser::SerializeSeq; + +// // let Self($(ref $ty,)*) = self; +// // let mut seq = serializer.serialize_seq(Some(LEN))?; +// // $( +// // seq.serialize_element(&SerializeWrapper::<'_, MC, _>($ty))?; +// // )* +// // seq.end() +// // self.as_ref().serialize::(serializer) +// unimplemented!() +// } + +// #[inline] +// #[doc(hidden)] +// fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result +// where +// De: Deserializer<'de>, +// { +// unimplemented!() + +// // struct TupleVisitor(PhantomData<($($ty,)*)>); +// // impl Default for TupleVisitor { +// // fn default() -> Self { +// // Self(PhantomData) +// // } +// // } +// // impl<'de, const MC: u64, const S: u8, $($ty,)*> Visitor<'de> for TupleVisitor { +// // type Value = $name; +// // #[inline] +// // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// // // write!(f, "A list of `{}`", T::NAME) +// // unimplemented!() +// // } + +// // #[inline] +// // fn visit_seq(self, mut seq: Ac) -> Result +// // where +// // Ac: SeqAccess<'de>, +// // { +// // // let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); +// // // while let Some(elem) = +// // // seq.next_element_seed(DeserializeWrapper::::default())? +// // // { +// // // list.push(elem); +// // // } +// // // Ok(list) +// // unimplemented!() +// // } +// // } + +// // deserializer.deserialize_seq(TupleVisitor::::default()) +// // } +// } +// }); + +// impl_tuple!(Tuple2 Tuple2Ref Strategy::BytesPrefix as u8 => A B { +// #[inline] +// #[doc(hidden)] +// fn serialize(&self, serializer: Se) -> Result +// where +// Se: Serializer, +// { +// use ser::SerializeSeq; + +// // let Self($(ref $ty,)*) = self; +// // let mut seq = serializer.serialize_seq(Some(LEN))?; +// // $( +// // seq.serialize_element(&SerializeWrapper::<'_, MC, _>($ty))?; +// // )* +// // seq.end() +// // self.as_ref().serialize::(serializer) +// unimplemented!() +// } + +// #[inline] +// #[doc(hidden)] +// fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result +// where +// De: Deserializer<'de>, +// { +// unimplemented!() + +// // struct TupleVisitor(PhantomData<($($ty,)*)>); +// // impl Default for TupleVisitor { +// // fn default() -> Self { +// // Self(PhantomData) +// // } +// // } +// // impl<'de, const MC: u64, const S: u8, $($ty,)*> Visitor<'de> for TupleVisitor { +// // type Value = $name; +// // #[inline] +// // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// // // write!(f, "A list of `{}`", T::NAME) +// // unimplemented!() +// // } + +// // #[inline] +// // fn visit_seq(self, mut seq: Ac) -> Result +// // where +// // Ac: SeqAccess<'de>, +// // { +// // // let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); +// // // while let Some(elem) = +// // // seq.next_element_seed(DeserializeWrapper::::default())? +// // // { +// // // list.push(elem); +// // // } +// // // Ok(list) +// // unimplemented!() +// // } +// // } + +// // deserializer.deserialize_seq(TupleVisitor::::default()) +// // } +// } +// }); +// // impl_tuple!(Tuple3 Tuple3Ref => A B C); +// // impl_tuple!(Tuple4 Tuple4Ref => A B C D); +// // impl_tuple!(Tuple5 Tuple5Ref => A B C D E); +// // impl_tuple!(Tuple6 Tuple6Ref => A B C D E F); +// // impl_tuple!(Tuple7 Tuple7Ref => A B C D E F G); +// // impl_tuple!(Tuple8 Tuple8Ref => A B C D E F G H); +// // impl_tuple!(Tuple9 Tuple9Ref => A B C D E F G H I); +// // impl_tuple!(Tuple10 Tuple10Ref => A B C D E F G H I J); +// // impl_tuple!(Tuple11 Tuple11Ref => A B C D E F G H I J K); +// // impl_tuple!(Tuple12 Tuple12Ref => A B C D E F G H I J K L); diff --git a/src/selectors/context.rs b/src/select/context.rs similarity index 98% rename from src/selectors/context.rs rename to src/select/context.rs index 382cdca..a570b33 100644 --- a/src/selectors/context.rs +++ b/src/select/context.rs @@ -114,7 +114,7 @@ impl Context for () { type Writer = Sink; fn block_reader(&mut self, _: &Cid) -> Result { - Ok(empty()) + Err(Error::Context(anyhow::Error::msg("empty block"))) } } diff --git a/src/selectors/mod.rs b/src/select/mod.rs similarity index 97% rename from src/selectors/mod.rs rename to src/select/mod.rs index 073c62f..dea4144 100644 --- a/src/selectors/mod.rs +++ b/src/select/mod.rs @@ -33,7 +33,7 @@ use std::{ /// /// TODO: + 'static? /// - Selectable? -pub trait Select: Representation { +pub trait Select: Representation { // /// // #[doc(hidden)] // type Seed<'a, 'de, const C: u64>: From> + DeserializeSeed<'de> = CodedSelectorSeed<'a, C, false, Ctx, Self>; @@ -67,9 +67,7 @@ pub trait Select: Representation { } #[doc(hidden)] - fn __select<'a>( - seed: SelectorSeed<'a, Ctx, Self>, - ) -> Result<(), Error> { + fn __select<'a>(seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { let cid = &seed.state.current_block; let block = seed.ctx.block_reader(cid)?; cid.multicodec()?.read_with_seed(seed, block) @@ -191,12 +189,12 @@ pub trait Select: Representation { } /// Patches the dag according to the selector, loading more blocks from - /// `Ctx` if required. Returns `true` it a patch was performed somewhere - /// within the dag. + /// `Ctx` if required. Returns `true` if any patch operation was executed + /// and subsequently mutated a part of the dag. /// /// TODO #[doc(hidden)] - fn patch_in(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { + fn patch(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { unimplemented!() } @@ -551,51 +549,51 @@ mod selection { /// #[serde(rename = "int8")] - Int8(Int8), + Int8(i8), /// #[serde(rename = "int16")] - Int16(Int16), + Int16(i16), /// #[serde(rename = "int32")] - Int32(Int32), + Int32(i32), /// #[serde(rename = "int64")] - Int64(Int64), + Int64(i64), /// #[serde(rename = "int")] - Int128(Int128), + Int128(i128), /// #[serde(rename = "uint8")] - Uint8(Uint8), + Uint8(u8), /// #[serde(rename = "uint16")] - Uint16(Uint16), + Uint16(u16), /// #[serde(rename = "uint32")] - Uint32(Uint32), + Uint32(u32), /// #[serde(rename = "uint64")] - Uint64(Uint64), + Uint64(u64), /// #[serde(rename = "uint128")] - Uint128(Uint128), + Uint128(u128), /// #[serde(rename = "float32")] - Float32(Float32), + Float32(f32), /// #[serde(rename = "float64")] - Float64(Float64), + Float64(f64), /// #[serde(skip)] // TODO @@ -745,7 +743,7 @@ mod field { } } - pub(crate) fn as_key(&self) -> Option<&str> { + pub(crate) fn as_key(&'a self) -> Option<&'a str> { match self { Self::Key(s) => Some(s.as_ref()), Self::Index(_) => None, diff --git a/src/selectors/seed.rs b/src/select/seed.rs similarity index 72% rename from src/selectors/seed.rs rename to src/select/seed.rs index bdb7087..35d5c40 100644 --- a/src/selectors/seed.rs +++ b/src/select/seed.rs @@ -1,6 +1,5 @@ -use super::*; use crate::dev::{macros::derive_more::From, *}; -use std::{fmt, marker::PhantomData}; +use maybestd::{fmt, marker::PhantomData, str::FromStr}; /// The selection mode of the selector, which determines what gets visited, /// matched, sent and returned. @@ -14,10 +13,12 @@ pub enum SelectionMode { MatchNode, /// Selection will invoke the provided callback on all matched [`Dag`]s. - MatchDag, - // /// Selection updates matching dags with the output of a callback. - // /// Optionally flushes changes after each callback. - // Patch, + Select, + + /// Selection will invoke the provided callback on all matched [`Dag`]s, + /// optionally mutating the dag updates matching dags with the output of a callback. + /// Optionally flushes changes after each callback. + Patch, } /// A helper type for guided decoding of a dag, using a selector to direct @@ -36,7 +37,7 @@ pub enum SelectionMode { /// e.g. /// ? - ergo, for ADLs: /// ? - map the input selector to another tailored for the underlying types -pub struct SelectorSeed<'a, Ctx, T = Any> { +pub struct SelectorSeed<'a, Ctx, T> { pub(crate) selector: &'a Selector, pub(crate) state: &'a mut State, pub(crate) callback: Callback<'a, Ctx, T>, @@ -49,12 +50,19 @@ pub type EmptySeed = SelectorSeed<'static, (), T>; /// currenly selecting against. #[cfg_attr(not(feature = "dev"), doc(hidden))] #[derive(Debug)] -pub struct CodecSeed::ReprKind>( - pub(crate) S, - PhantomData<(T, U, RK)>, -) +pub struct CodecSeed< + const C: u64, + S, + T, + U, + DK = ::DataModelKind, + SK = ::SchemaKind, + RK = ::ReprKind, +>(pub(crate) S, PhantomData<(T, U, DK, SK, RK)>) where - T: Representation, + T: Representation, + DK: TypedKind, + SK: TypedKind, RK: TypedKind; impl CodecSeed { @@ -76,90 +84,106 @@ impl CodecSeed { } /// Blanket impl for all `CodecSeed`s that implement `Visitor` for a given `T`. -/// Doing this allows us to focus selection implementations on what to do when -/// visiting a particular representation. -/// -/// TODO: support for enums? other types by their schema? -impl<'a, 'de, const C: u64, S, T, U, RK> DeserializeSeed<'de> for CodecSeed +/// Doing this allows us to more easily "escape" [`serde`]'s traits into our own +/// methods for selection. +impl<'a, 'de, const C: u64, S, T, U, DK, SK, RK> DeserializeSeed<'de> + for CodecSeed where - Self: Visitor<'de> + IpldVisitorExt<'de>, + Self: Visitor<'de> + LinkVisitor<'de>, S: SeedType, - T: Representation, + T: Representation, + DK: TypedKind, + SK: TypedKind, RK: TypedKind, { type Value = >::Value; #[inline] - fn deserialize(self, deserializer: De) -> Result + fn deserialize(self, deserializer: D) -> Result where - De: Deserializer<'de>, + D: Deserializer<'de>, { if T::__IGNORED { return deserializer.deserialize_ignored_any(self); + } else if T::DATA_MODEL_KIND.is_option() { + return deserializer.deserialize_option(self); } - match Self::repr_kind() { - Kind::Null => deserializer.deserialize_unit(self), - Kind::Bool => deserializer.deserialize_bool(self), - Kind::Int8 => deserializer.deserialize_i8(self), - Kind::Int16 => deserializer.deserialize_i16(self), - Kind::Int32 => deserializer.deserialize_i32(self), - Kind::Int64 => deserializer.deserialize_i64(self), - Kind::Int128 => deserializer.deserialize_i128(self), - Kind::Uint8 => deserializer.deserialize_u8(self), - Kind::Uint16 => deserializer.deserialize_u16(self), - Kind::Uint32 => deserializer.deserialize_u32(self), - Kind::Uint64 => deserializer.deserialize_u64(self), - Kind::Uint128 => deserializer.deserialize_u128(self), - Kind::Float32 => deserializer.deserialize_f32(self), - Kind::Float64 => deserializer.deserialize_f64(self), - Kind::String => deserializer.deserialize_str(self), - Kind::Bytes => { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, self); - } - deserializer.deserialize_bytes(self) - } - Kind::List => deserializer.deserialize_seq(self), - Kind::Map => deserializer.deserialize_map(self), - Kind::Link => { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_cid(deserializer, self); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::deserialize_cid(deserializer, self); - } - deserializer.deserialize_any(self) - } - _ => { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_any(deserializer, self); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::deserialize_any(deserializer, self); - } - deserializer.deserialize_any(self) + match (T::SCHEMA_KIND, Self::repr_kind()) { + // union (kinded => any, stringprefix => str, bytesprefix => bytes) + // union keyed (ref), envelope (tag + ref), inline (tag + inline) + (Kind::Union, Kind::Map) => deserializer.deserialize_enum(T::NAME, T::FIELDS, self), + + // structs (stringpair, stringjoin => str) + // struct map + (Kind::Struct, Kind::Map) => deserializer.deserialize_struct(T::NAME, T::FIELDS, self), + // struct tuple, listpairs + (Kind::Struct, Kind::List) => { + deserializer.deserialize_tuple_struct(T::NAME, T::FIELDS.len(), self) } + + // enum (int => int, string => str) + + // basic + (_, Kind::Null) => deserializer.deserialize_unit(self), + (_, Kind::Bool) => deserializer.deserialize_bool(self), + (_, Kind::Int8) => deserializer.deserialize_i8(self), + (_, Kind::Int16) => deserializer.deserialize_i16(self), + (_, Kind::Int32) => deserializer.deserialize_i32(self), + (_, Kind::Int64) => deserializer.deserialize_i64(self), + (_, Kind::Int128) => deserializer.deserialize_i128(self), + (_, Kind::Uint8) => deserializer.deserialize_u8(self), + (_, Kind::Uint16) => deserializer.deserialize_u16(self), + (_, Kind::Uint32) => deserializer.deserialize_u32(self), + (_, Kind::Uint64) => deserializer.deserialize_u64(self), + (_, Kind::Uint128) => deserializer.deserialize_u128(self), + (_, Kind::Float32) => deserializer.deserialize_f32(self), + (_, Kind::Float64) => deserializer.deserialize_f64(self), + (_, Kind::String) => deserializer.deserialize_str(self), + (_, Kind::Bytes) => Multicodec::deserialize_bytes::(deserializer, self), + (_, Kind::List) => deserializer.deserialize_seq(self), + (_, Kind::Map) => deserializer.deserialize_map(self), + (_, Kind::Link) => Multicodec::deserialize_link::(deserializer, self), + // anything else + _ => Multicodec::deserialize_any::(deserializer, self), } } } #[doc(hidden)] -pub trait SeedType { +pub trait SeedType: Sized { + type Input; type Output; + type Wrapped: SeedType; const CAN_SELECT: bool; + + // fn select_node() -> Result<(), Error> { + // unimplemented!() + // } + // fn get_mut(&mut self) -> &mut T { + // unimplemented!() + // } + + fn wrap(self, conv: F) -> Option { + unimplemented!() + } } -impl SeedType for PhantomData { +impl SeedType for PhantomData { + type Input = (); type Output = T; + type Wrapped = PhantomData; const CAN_SELECT: bool = false; } -impl<'a, Ctx, T> SeedType for SelectorSeed<'a, Ctx, T> { +// impl SeedType for DeserializeWrapper { +// type Input = (); +// type Output = T; +// type Wrapped = DeserializeWrapper; +// const CAN_SELECT: bool = false; +// } +impl<'a, Ctx, T: 'a, U: 'a> SeedType for SelectorSeed<'a, Ctx, T> { + type Input = &'a mut T; type Output = (); + type Wrapped = SelectorSeed<'a, Ctx, U>; const CAN_SELECT: bool = true; } @@ -245,16 +269,16 @@ where match &self.callback { Callback::SelectNode { .. } if self.selector.is_matcher() => SelectionMode::MatchNode, Callback::SelectNode { .. } => SelectionMode::CoverNode, - Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::MatchDag, - // Self::Patch { .. } => SelectionMode::Patch, + Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::Select, + Callback::Patch { .. } => SelectionMode::Patch, } } /// #[inline] pub const fn is_node_select(&self) -> bool { - match self.callback { - Callback::SelectNode { .. } => true, + match self.mode() { + SelectionMode::CoverNode | SelectionMode::MatchNode => true, _ => false, } } @@ -262,8 +286,17 @@ where /// #[inline] pub const fn is_dag_select(&self) -> bool { - match self.callback { - Callback::SelectDag { .. } | Callback::MatchDag { .. } => true, + match self.mode() { + SelectionMode::Select => true, + _ => false, + } + } + + /// + #[inline] + pub const fn is_patch(&self) -> bool { + match self.mode() { + SelectionMode::Patch => true, _ => false, } } @@ -423,6 +456,7 @@ where ) -> Result<(), Error> where K: StringRepresentation, + ::Err: fmt::Display, V: Select, { iter.next_value_seed::({ @@ -539,10 +573,8 @@ macro_rules! repr_serde { $($visit_fns)* } }; - - // impl_selector_seed_serde! { @codec_seed_visitor_ext {} {} $ty {} } }; - // impl IpldVisitorExt for CodedSeed by REPR_KIND + // impl LinkVisitor for CodedSeed by REPR_KIND (@visitor_ext $ty:ident $marker_ty:ty { $($rk:tt)* } { $($generics:tt)* } { $($bounds:tt)* } // $ty:ident @@ -558,7 +590,7 @@ macro_rules! repr_serde { // #[doc(hidden)] impl<'_a, 'de, const C: u64, Ctx, $($generics)*> - IpldVisitorExt<'de> for + LinkVisitor<'de> for CodecSeed, $ty, $marker_ty, $($rk)*> @@ -621,7 +653,7 @@ macro_rules! repr_serde { // let seed = CodecSeed::::from(seed); // seq.next_element_seed(seed) // } - + // // #[doc(hidden)] // #[inline] // fn __select_map<'a, 'de, const C: u64, A>( @@ -642,6 +674,157 @@ macro_rules! repr_serde { } }; }; + + /////////////////////////////////////////////////////////////// + (@visitors for $T:ty => $U:ty + { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } + { $($generics:tt)* } { $($bounds:tt)* } + @serde { $($visit_fns:tt)* } + ) => { + repr_serde!(@visitors for $T => $U + { @dk ($($dk)*) @sk ($($sk)*) @rk ($($rk)*) } + { $($generics)* } { $($bounds)* } + @serde { $($visit_fns)* } @link {} + ); + }; + (@visitors for $T:ty => $U:ty + { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } + { $($generics:tt)* } { $($bounds:tt)* } + @serde { $($visit_fns:tt)* } + @link { $($visit_link_fns:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + #[doc(hidden)] + impl<'_a, 'de, const C: u64, Ctx, $($generics)*> + Visitor<'de> for + CodecSeed, $T, $U, + $($dk)*, $($sk)*, $($rk)* + > + where + Ctx: Context, + $T: Select + Representation< + DataModelKind = $($dk)*, + SchemaKind = $($sk)*, + ReprKind = $($rk)* + >, + $($bounds)* + { + type Value = as SeedType<$T>>::Output; + $($visit_fns)* + } + + #[doc(hidden)] + impl<'_a, 'de, const C: u64, Ctx, $($generics)*> + LinkVisitor<'de> for + CodecSeed, $T, $U, + $($dk)*, $($sk)*, $($rk)* + > + where + Ctx: Context, + $T: Select + Representation< + DataModelKind = $($dk)*, + SchemaKind = $($sk)*, + ReprKind = $($rk)* + >, + $($bounds)* + { + $($visit_link_fns)* + } + }; + }; + // (@select_for $T:ty => $U:ty + // ) => { + // repr_serde!( + // @select_for $T => $U + // { @dk (<$T as Representation>::DataModelKind) + // @sk (<$T as Representation>::SchemaKind) + // @rk (<$T as Representation>::ReprKind) } + // ); + // }; + (@select_for $T:ty) => { + repr_serde!(@select_for $T {} {}); + }; + (@select_for $T:ty { $($generics:tt)* } { $($bounds:tt)* }) => { + repr_serde!(@select_for $T => $T { $($generics)* } { $($bounds)* }); + }; + (@select_for $T:ty => $U:ty { $($generics:tt)* } { $($bounds:tt)* }) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + impl Select for $T + where + Ctx: Context, + $($bounds)* + { + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = CodecSeed::::from(seed); + seed.deserialize(deserializer) + } + } + }; + }; + (@select_for $T:ty => $U:ty + { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } + ) => { + repr_serde!(@select_for $T => $U + { @dk ($($dk)*) @sk ($($sk)*) @rk ($($rk)*) } {} {} + ); + }; + (@select_for $T:ty => $U:ty + { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } + { $($generics:tt)* } { $($bounds:tt)* } + ) => { + repr_serde!(@select_for $T => $U { $($generics)* } { + $T: Representation< + DataModelKind = $($dk)*, + SchemaKind = $($sk)*, + ReprKind = $($rk)* + >, + $($bounds)* + }); + }; + (@select_for_newtype $T:ty => $($constructor:tt)* ( $U:ty ) + { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } + { $($generics:tt)* } { $($bounds:tt)* } + ) => { + const _: () = { + #[allow(unused_imports)] + use $crate::dev::*; + + impl Select for $T + where + Ctx: Context, + $T: Representation< + DataModelKind = $($dk)*, + SchemaKind = $($sk)*, + ReprKind = $($rk)* + >, + $($bounds)* + { + #[doc(hidden)] + #[inline] + fn __select<'a>( + seed: SelectorSeed<'a, Ctx, Self>, + ) -> Result<(), Error> { + let seed = seed.wrap::<$U, _>($constructor); + <$U>::__select(seed) + } + } + }; + }; + /* (@seed_from_params $params:ident $ctx:ident) => {{ let Params { @@ -739,6 +922,8 @@ macro_rules! repr_serde { }; }; + /* + // TODO: instead of transmuting cb in DeSeed, transmute it in Select (@selector_seed_codec_deseed_newtype { $($generics:tt)* } { $($bounds:tt)* } @@ -892,4 +1077,5 @@ macro_rules! repr_serde { // } // } // }; + */ } diff --git a/src/selectors/selectors.rs b/src/select/selectors.rs similarity index 99% rename from src/selectors/selectors.rs rename to src/select/selectors.rs index 1368eb2..1189abf 100644 --- a/src/selectors/selectors.rs +++ b/src/select/selectors.rs @@ -211,7 +211,9 @@ schema! { /// simultaneously continuing to explore deeper parts of the tree with /// another selector, for example. #[ipld_attr(internal)] - #[derive(Clone, Debug, From)] + #[derive(Clone, Debug + // From + )] pub type ExploreUnion null; // pub type ExploreUnion [Selector]; } diff --git a/src/selectors/state.rs b/src/select/state.rs similarity index 93% rename from src/selectors/state.rs rename to src/select/state.rs index 0bc2743..03f811e 100644 --- a/src/selectors/state.rs +++ b/src/select/state.rs @@ -1,6 +1,6 @@ use crate::dev::*; use macros::derive_more::{AsMut, AsRef, From}; -use std::{ +use maybestd::{ boxed::Box, fmt, path::{Path, PathBuf}, @@ -202,6 +202,36 @@ mod callbacks { } } + /// + pub trait PatchDagOp: FnMut(&mut T, &mut C) -> Result { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } + + impl PatchDagOp for F + where + F: FnMut(&mut T, &mut C) -> Result + Clone, + { + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } + } + + impl<'a, T, C> Clone for Box + 'a> + where + T: 'a, + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } + } + /// #[doc(hidden)] pub enum Callback<'a, C, T> { @@ -215,15 +245,16 @@ mod callbacks { }, MatchDag { cb: Box + 'a>, - }, // Patch { - // /// current dag we're selecting against - // /// if none, then load and store while patching - // current: &'a mut T, - // flush: bool, - // // op to perform on matching dags, allowing update-inplace - // // op: Box + 'a>, - // // op: PatchFn, - // } + }, + Patch { + /// current dag we're selecting against + /// if none, then load and store while patching + // current: &'a mut T, + // flush: bool, + // op to perform on matching dags, allowing update-inplace + cb: Box + 'a>, + // op: PatchFn, + }, } impl<'a, C, T> fmt::Debug for Callback<'a, C, T> @@ -246,6 +277,7 @@ mod callbacks { .debug_struct("SelectionParams::MatchDag") .field("source", &T::NAME) .finish(), + _ => unimplemented!(), // Self::Patch { current, flush, .. } => f // .debug_struct("SelectionParams::Patch") // .field("current", ¤t) @@ -268,6 +300,7 @@ mod callbacks { }, Self::SelectDag { cb } => Self::SelectDag { cb: cb.clone() }, Self::MatchDag { cb } => Self::MatchDag { cb: cb.clone() }, + _ => unimplemented!(), } } } @@ -328,7 +361,8 @@ mod callbacks { Self::MatchDag { mut cb } => { let cb = Box::new(move |dag: U, ctx: &mut C| cb(conv(dag), ctx)); Callback::MatchDag { cb } - } // _ => unimplemented!(), + } + _ => unimplemented!(), } } diff --git a/src/selectors/path.rs b/src/selectors/path.rs deleted file mode 100644 index 2f0046a..0000000 --- a/src/selectors/path.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::dev::*; -use std::{ - marker::PhantomData, - path::{Path, PathBuf}, -}; - -// /// -// #[derive(Debug)] -// pub struct PathSeed { -// max_block_depth: usize, -// path: PathBuf, -// _type: PhantomData, -// } - -// impl<'de, T: Representation> DeserializeSeed<'de> for PathSeed { -// type Value = (Option, Option); - -// #[inline] -// fn deserialize(self, deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// T::try_deserialize_path(self, deserializer).map_err(D::Error::custom) -// } -// } - -impl From for Selector { - fn from(path: Path) -> Self { - unimplemented!() - } -} diff --git a/src/selectors/str.rs b/src/selectors/str.rs deleted file mode 100644 index f36992d..0000000 --- a/src/selectors/str.rs +++ /dev/null @@ -1 +0,0 @@ -use super::Selector; From 9b7be08ef5f5a2bb3bd123446b2aec1787e5be01 Mon Sep 17 00:00:00 2001 From: sunny-g Date: Fri, 9 Dec 2022 18:23:31 -0600 Subject: [PATCH 8/9] closer to nostd, starts derive macros, refactor prep --- Cargo.toml | 118 +- macros-internals/Cargo.toml | 6 +- macros-internals/src/lib.rs | 4 +- .../src/schema/compound/expand_list.rs | 37 +- .../src/schema/compound/expand_map.rs | 143 ++- macros-internals/src/schema/compound/parse.rs | 4 +- macros-internals/src/schema/enum/expand.rs | 13 +- macros-internals/src/schema/expand.rs | 350 +++--- macros-internals/src/schema/mod.rs | 90 +- macros-internals/src/schema/parse.rs | 2 +- .../src/schema/primitive/expand.rs | 203 ++-- .../src/schema/primitive/expand_bytes.rs | 30 +- .../src/schema/primitive/expand_link.rs | 33 +- .../src/schema/primitive/parse.rs | 6 +- macros-internals/src/schema/struct/expand.rs | 110 +- .../src/schema/struct/expand_listpairs.rs | 3 - .../src/schema/struct/expand_stringjoin.rs | 3 - .../src/schema/struct/expand_stringpairs.rs | 3 - .../src/schema/struct/expand_tuple.rs | 3 - macros-internals/src/schema/union/expand.rs | 62 +- .../src/schema/union/expand_byte_prefix.rs | 3 - .../src/schema/union/expand_envelope.rs | 3 - .../src/schema/union/expand_inline.rs | 3 - .../src/schema/union/expand_kinded.rs | 215 ++-- macros-internals/src/schema2/mod.rs | 223 ++++ .../src/schema2/representation.rs | 246 ++++ macros-internals/src/schema2/select.rs | 34 + macros/src/lib.rs | 51 +- src/cid.rs | 369 ++++-- src/codecs/dag_cbor.rs | 68 +- src/codecs/dag_json.rs | 200 ++-- src/codecs/mod.rs | 487 +++++++- src/compat/core.rs | 400 ++++--- src/compat/mod.rs | 6 + src/data_model/any.rs | 139 +-- src/data_model/link.rs | 66 +- src/data_model/list.rs | 253 ++-- src/data_model/map.rs | 341 +++--- src/data_model/mod.rs | 55 +- src/data_model/primitive.rs | 469 ++++---- src/error.rs | 44 +- src/lib.rs | 119 +- src/multicodec.rs | 299 +++-- src/multihash.rs | 67 +- src/representation/mod.rs | 274 +++-- src/representation/strategies/bytesprefix.rs | 2 +- src/representation/strategies/listpairs.rs | 424 ++++--- src/representation/strategies/mod.rs | 173 +-- src/representation/strategies/stringjoin.rs | 2 +- src/representation/strategies/stringpairs.rs | 2 +- src/representation/strategies/stringprefix.rs | 2 +- src/representation/strategies/tuple.rs | 264 +++-- src/select/context.rs | 19 +- src/select/mod.rs | 110 +- src/select/seed.rs | 1053 ++++++----------- src/select/selectors.rs | 50 +- src/select/state.rs | 244 ++-- 57 files changed, 4516 insertions(+), 3486 deletions(-) create mode 100644 macros-internals/src/schema2/mod.rs create mode 100644 macros-internals/src/schema2/representation.rs create mode 100644 macros-internals/src/schema2/select.rs diff --git a/Cargo.toml b/Cargo.toml index 2868eb7..77215f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,54 +12,141 @@ path = "src/lib.rs" [dependencies] # core -bytes = "1.2" -cid = { version = "0.8", features = ["serde-codec"] } +arrayvec = { version = "0.7", default-features = false } +bytes = { version = "1.2", default-features = false, features = ["serde"] } +cid = { version = "0.8", default-features = false, features = ["serde-codec"] } +# digest = { version = "0.10", optional = true } +# erased-serde = { version = "0.3", default-features = false } +# TODO: optional? also not no_std ipld-macros = { path = "./macros" } ipld-macros-internals = { path = "./macros-internals" } multibase = { version = "0.9", default-features = false } -multihash = { version = "0.16", default-features = false } +# todo: allow for better customization of multihash +multihash = { version = "0.16", default-features = false, features = ["multihash-impl", "secure-hashes"] } serde = { version = "1.0", default-features = false, features = ["derive", "rc"] } # serde_repr = "0.1" +# TODO: not no_std thiserror = "1.0" -unicode-normalization = "0.1" +unicode-normalization = { version = "0.1", default-features = false } # codecs -serde_cbor = { version = "0.11", optional = true, features = ["tags"] } +rkyv = { version = "*", default-features = false, optional = true } +serde_cbor = { version = "0.11", default-features = false, optional = true, features = ["tags"] } # cbor4ii = { version = "0.2", optional = true, features = ["serde1", "use_std"] } # serde_ipld_dagcbor = { version = "0.2", optional = true, features = ["std"] } -serde_json = { version = "1.0", optional = true, features = ["float_roundtrip"] } +serde_json = { version = "1.0", default-features = false, optional = true, features = ["float_roundtrip", "unbounded_depth"] } # simd-json = { version = "0.6", optional = true, features = ["serde_impl", "128bit"] } +# risc0-zeroio = { git = "https://github.com/risc0/risc0", default-features = false, optional = true } +# risc0-zeroio-derive = { git = "https://github.com/risc0/risc0", default-features = false, optional = true } + +# compatibility with other libraries +im = { version = "*", default-features = false, optional = true } +indexmap = { version = "*", default-features = false, optional = true } +libp2p-core = { version = "0.38", optional = true } +multiaddr = { version = "0.17", default-features = false, optional = true } +# bigint +# ed25519, secp256k1, rsa, bls, recrypt +# time, ?half +# serdect +# radixdb = { version = "0.2", optional = true } +wnfs = { version = "*", default-features = false, optional = true } + +# adls +crdts = { version = "7.2", default-features = false, optional = true } +# merkle-log = { version = "*", default-features = false, optional = true } +# vb_accumulator = { version = "*", default-features = false, optional = true } # misc anyhow = "1.0" # const-str = "0.3" # const_format = "0.2" core2 = { version = "0.4", default-features = false, optional = true } -delegate = { version = "0.8", optional = true } +delegate = { version = "0.8" } +# derive_builder = "0.11" downcast-rs = "1.2" +# lexical, itoa = "1.0" dtoa? +paste = "1.0" +# ref-cast = "1.0" [dev-dependencies] # criterion = "0.4" # proptest = "1.0" [features] -default = ["multicodec", "alloc", "std", "dev"] -std = ["cid/std", "core2/std", "multibase/std", "multihash/std", "serde/std"] -alloc = ["cid/alloc", "serde/alloc"] +default = [ + "std", + "multicodec", + # TODO: remove these + "dev", + "multiaddr", +] +alloc = [ + "cid/alloc", + "multihash/alloc", + "serde/alloc", + "serde_cbor?/alloc", + "serde_json?/alloc", +] +std = [ + "alloc", + "sync", + "arrayvec/std", + "bytes/std", + "cid/std", + "core2/std", + "multibase/std", + "multihash/std", + "serde/std", + "unicode-normalization/std", + # optional + "indexmap?/std", + "serde_cbor?/std", + "serde_json?/std", +] +sync = [] +parallel = ["std"] # activate dev docs -dev = [] +dev = [ + "hamt", + "merkle-crdts", +] # codecs -dag-cbor = ["serde_cbor"] +dag-cbor = ["dep:serde_cbor"] # dag-cbor = ["cbor4ii", "delegate"] # dag-cbor = ["serde_ipld_dagcbor", "delegate"] -dag-json = ["serde_json", "delegate"] -dag-pb = [] +dag-json = ["dep:serde_json"] +# dag-pb = [] +# raw = [] # enables all available multicodecs -multicodec = ["dag-cbor", "dag-json", "dag-pb"] +multicodec = ["dag-cbor", "dag-json"] # # enables simd-related implementations, including an alternate dag-json # simd = ["dag-json", "simd-json"] +# compatibility with other libraries +crdts = ["dep:crdts", "std"] +# ecdsa = [] +# dalek = [] +indexmap = ["dep:indexmap"] +im = ["dep:im"] +libp2p = ["dep:libp2p-core"] +multiaddr = ["dep:multiaddr"] +# signature = [] +wnfs = ["dep:wnfs"] + +# adls +fbl = [] +hamt = [] +merkle-crdts = ["crdts"] +# merkle-log = ["dep:merkle-log"] +prolly-tree = [] +# vb-collection = ["dep:vb_accumulator"] + + +[package.metadata.docs.rs] +features = ["multicodec", "std", "dev"] +rustdoc-args = ["--cfg", "docsrs"] + [workspace] members = [ "macros", @@ -72,3 +159,4 @@ exclude = [ [patch.crates-io] # cid = { path = "../rust-cid" } # multihash = { path = "../rust-multihash" } +wnfs = { path = "vendor/wnfs/wnfs" } diff --git a/macros-internals/Cargo.toml b/macros-internals/Cargo.toml index 94ae955..6723c6b 100644 --- a/macros-internals/Cargo.toml +++ b/macros-internals/Cargo.toml @@ -6,18 +6,16 @@ edition = "2018" [dependencies] bitflags = "1.3" +darling = "0.14" derive_more = "0.99" # impls = "1" -# juniper = { version = "0.14", optional = true } # num-traits = "0.2" -proc-macro-crate = "1.1" +proc-macro-crate = "1.1" # todo: remove proc-macro2 = "1.0" quote = "1.0" # static_assertions = "1.1.0" syn = { version = "1.0", features = ["extra-traits", "printing"] } # tylift = "0.3" -typenum = "1.15" -typenum-macro = { git = "https://github.com/paholg/typenum", branch = "proc_macro" } [dev-dependencies] syn = { version = "1.0", features = ["full"] } diff --git a/macros-internals/src/lib.rs b/macros-internals/src/lib.rs index 4b84ce9..853c442 100644 --- a/macros-internals/src/lib.rs +++ b/macros-internals/src/lib.rs @@ -1,5 +1,6 @@ pub mod common; pub mod schema; +pub mod schema2; pub mod selector; pub use schema::SchemaDefinition; @@ -15,7 +16,6 @@ pub mod dev { pub use crate::selector::*; pub use crate::*; + pub use darling; pub use derive_more; - pub use typenum; - pub use typenum_macro; } diff --git a/macros-internals/src/schema/compound/expand_list.rs b/macros-internals/src/schema/compound/expand_list.rs index b662158..9d5a8f2 100644 --- a/macros-internals/src/schema/compound/expand_list.rs +++ b/macros-internals/src/schema/compound/expand_list.rs @@ -1,42 +1,39 @@ use super::*; use crate::dev::*; use quote::quote; -use syn::{ - braced, bracketed, - parse::{Parse, ParseStream, Result as ParseResult}, - LitStr, Path, Token, Type, -}; +use syn::Type; impl ExpandBasicRepresentation for ListReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let name_str = meta.name_str(); + let (_, child_name) = self.child(); + quote!(concat!("type ", #name_str, " [", #child_name, "]")) + } + fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; - let (_, child_name) = self.child_ty(); - let schema = quote! { - const SCHEMA: &'static str = concat!( - "type ", stringify!(#name), " [", #child_name, "]", - ); - }; - let inner_ty = self.inner_ty(); - derive_newtype!(@repr { schema } meta => inner_ty) + let consts = quote! { + const DATA_MODEL_KIND: Kind = Kind::List; + const SCHEMA_KIND: Kind = Kind::List; + const REPR_KIND: Kind = Kind::List; + }; + derive_newtype!(@repr self, meta => inner_ty { consts }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - // let dm_ty = SchemaKind::List.data_model_kind(); - // derive_newtype!(@conv self, meta => dm_ty dm_ty) - quote!() + derive_newtype!(@conv @has_constructor self, meta) } } impl ListReprDefinition { - fn child_ty(&self) -> (Type, TokenStream) { + fn child(&self) -> (Type, TokenStream) { match self { Self::Basic { elem, nullable } if *nullable => ( Type::Verbatim(quote!(Option<#elem>)), @@ -47,7 +44,7 @@ impl ListReprDefinition { } } fn inner_ty(&self) -> Type { - let (child_ty, _) = self.child_ty(); + let (child_ty, _) = self.child(); Type::Verbatim(quote!(List<#child_ty>)) } } diff --git a/macros-internals/src/schema/compound/expand_map.rs b/macros-internals/src/schema/compound/expand_map.rs index 6c27856..fe8fcd0 100644 --- a/macros-internals/src/schema/compound/expand_map.rs +++ b/macros-internals/src/schema/compound/expand_map.rs @@ -1,16 +1,40 @@ use super::*; use crate::dev::*; use quote::quote; -use syn::{ - braced, bracketed, - parse::{Parse, ParseStream, Result as ParseResult}, - LitStr, Path, Token, Type, -}; +use syn::Type; impl ExpandBasicRepresentation for MapReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let name_str = meta.name_str(); + let (_, key_name) = self.key(); + let (_, val_name) = self.val(); + let base_schema = quote! { + concat!("type ", #name_str, " {", #key_name, ":", #val_name, "}") + }; + + match self { + Self::Basic { .. } => quote! { + concat!(#base_schema, " representation map") + }, + Self::Listpairs { .. } => quote! { + concat!(#base_schema, " representation listpairs") + }, + Self::Stringpairs { + inner_delim, + entry_delim, + .. + } => quote! { + concat!(#base_schema, " representation stringpairs { ", + "innerDelim ", #inner_delim, " ", + "entryDelim ", #entry_delim, " ", + "}") + }, + _ => unimplemented!(), + } + } + fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - match self { Self::Basic { .. } => derive_newtype!(@typedef self, meta => inner_ty), Self::Stringpairs { .. } => derive_newtype!(@typedef self, meta => inner_ty), @@ -19,72 +43,59 @@ impl ExpandBasicRepresentation for MapReprDefinition { } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; - let key_ty = self.key_ty(); - let (val_ty, val_name) = self.val_ty(); let inner_ty = self.inner_ty(); - let repr_kind = self.repr_kind(); - let base_schema = quote! { - "type ", stringify!(#name), " ", - "{", stringify!(#key_ty), ":", stringify!(#val_name), "}", + let (repr_kind, repr_strategy) = self.repr(); + let consts = quote! { + const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Map; + const REPR_KIND: Kind = #repr_kind; + const REPR_STRATEGY: Strategy = #repr_strategy; }; - match self { - Self::Basic { .. } => { - let schema = quote! { - const SCHEMA: &'static str = concat!(#base_schema); - }; - derive_newtype!(@repr { schema } meta => inner_ty) - } - Self::Listpairs { .. } => { - let schema = quote! { - const SCHEMA: &'static str = - concat!(#base_schema, "representation listpairs"); - }; - derive_newtype!(@repr { schema } meta => inner_ty) - } - Self::Stringpairs { - inner_delim, - entry_delim, - .. - } => { - let schema = quote! { - const SCHEMA: &'static str = concat!( - #base_schema, - "representation stringpairs { ", - "innerDelim ", #inner_delim, " ", - "entryDelim ", #entry_delim, " ", - "}", - ); - }; - derive_newtype!(@repr { schema } meta => inner_ty) - } - _ => unimplemented!(), - } + derive_newtype!(@repr self, meta => inner_ty { consts }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - derive_newtype!(@select meta => inner_ty) - // quote!() + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - // let val_ty = self.val_ty(); - // derive_newtype!(@select meta => val_ty) - quote!() + derive_newtype!(@conv @has_constructor self, meta) } } impl MapReprDefinition { - fn key_ty(&self) -> Type { + fn repr(&self) -> (TokenStream, TokenStream) { + match self { + Self::Basic { .. } => (quote!(Kind::Map), quote!(Strategy::Basic)), + Self::Listpairs { .. } => (quote!(Kind::List), quote!(Strategy::Listpairs)), + Self::Stringpairs { .. } => (quote!(Kind::String), quote!(Strategy::Stringpairs)), + _ => unimplemented!(), + } + } + + fn inner_ty(&self) -> Type { + let (key, _) = self.key(); + let (val, _) = self.val(); + Type::Verbatim(match self { + Self::Basic { .. } => quote!(Map<#key, #val>), + Self::Listpairs { .. } => quote!(ListpairsMap<#key, #val>), + Self::Stringpairs { .. } => quote!(StringpairsMap<#key, #val>), + _ => unimplemented!(), + }) + } + + fn key(&self) -> (Type, TokenStream) { match self { Self::Basic { key, .. } | Self::Listpairs { key, .. } - | Self::Stringpairs { key, .. } => key.clone(), + | Self::Stringpairs { key, .. } => { + (key.clone(), quote!(<#key as Representation>::NAME)) + } _ => unimplemented!(), } } - fn val_ty(&self) -> (Type, TokenStream) { + fn val(&self) -> (Type, TokenStream) { match self { Self::Basic { value, nullable, .. @@ -96,32 +107,14 @@ impl MapReprDefinition { value, nullable, .. } if *nullable => ( Type::Verbatim(quote!(Option<#value>)), - quote!("nullable ", stringify!(#value)), + quote!("nullable ", <#value as Representation>::NAME), ), Self::Basic { value, .. } | Self::Listpairs { value, .. } - | Self::Stringpairs { value, .. } => (value.clone(), quote!(stringify!(#value))), - Self::Advanced(..) => unimplemented!(), - } - } - - fn inner_ty(&self) -> Type { - let key_ty = self.key_ty(); - let (val_ty, _) = self.val_ty(); - match self { - Self::Basic { .. } => Type::Verbatim(quote!(Map<#key_ty, #val_ty>)), - Self::Listpairs { .. } => Type::Verbatim(quote!(ListPairsMap<#key_ty, #val_ty>)), - Self::Stringpairs { .. } => Type::Verbatim(quote!(StringPairsMap<#key_ty, #val_ty>)), + | Self::Stringpairs { value, .. } => { + (value.clone(), quote!(<#value as Representation>::NAME)) + } _ => unimplemented!(), } } - - fn repr_kind(&self) -> TokenStream { - match self { - Self::Basic { .. } => quote!(Kind::Map), - Self::Listpairs { .. } => quote!(Kind:::List), - Self::Stringpairs { .. } => quote!(Kind::String), - Self::Advanced(..) => unimplemented!(), - } - } } diff --git a/macros-internals/src/schema/compound/parse.rs b/macros-internals/src/schema/compound/parse.rs index 23e909a..a4de256 100644 --- a/macros-internals/src/schema/compound/parse.rs +++ b/macros-internals/src/schema/compound/parse.rs @@ -1,13 +1,13 @@ use super::*; use crate::dev::{ - common, impl_advanced_parse, parse_kwarg, + impl_advanced_parse, parse_kwarg, schema::{kw, parse}, *, }; use syn::{ braced, bracketed, parse::{Parse, ParseStream, Result as ParseResult}, - LitStr, Path, Token, Type, + Path, Token, Type, }; impl Parse for ListReprDefinition { diff --git a/macros-internals/src/schema/enum/expand.rs b/macros-internals/src/schema/enum/expand.rs index 7c180b6..db95bf9 100644 --- a/macros-internals/src/schema/enum/expand.rs +++ b/macros-internals/src/schema/enum/expand.rs @@ -7,6 +7,10 @@ use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; impl ExpandBasicRepresentation for EnumReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + Default::default() + } + fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let lib = &meta.lib; let attrs = &meta.attrs; @@ -35,16 +39,13 @@ impl ExpandBasicRepresentation for EnumReprDefinition { } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - expand::impl_repr( + self.impl_repr( meta, quote! { - const KIND: Kind = - Kind::Enum; + const KIND: Kind = Kind::Enum; // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); }, - // quote! { - // unimplemented!() - // }, + quote! {}, ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index cf4ae7c..619c6a7 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -3,6 +3,8 @@ use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_macro_input, parse_quote, Ident}; +impl SchemaMeta {} + impl SchemaDefinition { /// Expand this into a `TokenStream` of the IPLD Schema + Representation /// implementation. @@ -42,52 +44,21 @@ impl ToTokens for SchemaDefinition { fn to_tokens(&self, tokens: &mut TokenStream) { macro_rules! expand_basic { ($meta:ident, $def:ident) => {{ - let import_ipld = if $meta.internal { - quote!( - use crate as _ipld; - ) - } else { - let lib = &$meta.lib; - quote! { - // #[allow(clippy::useless_attribute)] - extern crate #lib as _ipld; - } - }; - + let imports = SchemaMeta::imports($meta.internal); + let scope = Ident::new(&format!("_IPLD_FOR_{}", &$meta.name), Span::call_site()); + let typedef = $def.define_type($meta); let defs = [ - ("IMPL_SERDE", $def.derive_serde($meta)), - ("IMPL_REPR", $def.derive_repr($meta)), - ("IMPL_SELECT", $def.derive_select($meta)), - ("IMPL_CONV", $def.derive_conv($meta)), + $def.derive_repr($meta), + $def.derive_select($meta), + $def.derive_conv($meta), ]; - let scoped_impls = defs - .iter() - .map(|(def_kind, def)| { - ( - Ident::new( - &format!("_IPLD_{}_FOR_{}", def_kind, &$meta.name), - Span::call_site(), - ), - def, - ) - }) - .map(|(ident, def)| { - quote! { - #[doc(hidden)] - const #ident: () = { - #import_ipld - #[allow(unused_imports)] - use _ipld::dev::*; - #def - }; - } - }); - - let typedef = $def.define_type($meta); quote! { #typedef - #(#scoped_impls)* + const #scope: () = { + #imports + #(#defs)* + }; } }}; } @@ -124,35 +95,78 @@ impl ToTokens for SchemaDefinition { /// Helper trait for expanding a `SchemaDefinition` into a type and it's trait impls. #[allow(unused_variables)] pub(crate) trait ExpandBasicRepresentation { + /// + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + Default::default() + } + /// Defines the type, and applies any provided attributes. fn define_type(&self, meta: &SchemaMeta) -> TokenStream; /// Derives `Representation` for the defined type. fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream; - /// Derive Serde impls for the defined type, as well as core-logic types like [`ipld::context::ContextSeed`]. - /// - /// Optional because many types can use `serde-derive`directly. - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } - /// Derives `Select` for the type. /// /// TODO: support conditionals - /// - `type ReprSelectorSeed = SelectorSeed` - /// `impl Visitor for `ReprSelectorSeed` - /// - `type IgnoredT = IgnoredRepr` - /// - defines a `NewSelector` for the type, wrapping `Selector` - /// `impl DeserializeSeed for NewSelector` - /// - `impl DeserializeSeed<'de, Value = Self> for Selector` - /// instantiates ReprSelectorSeed(selector, repr_visitor) - /// matches on selector, delegates to one deserializer method fn derive_select(&self, meta: &SchemaMeta) -> TokenStream; /// Derives conversions between the type and `Value`, as well as `ipfs::Ipld` /// (if `#[cfg(feature = "ipld/ipfs")]` is enabled) fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream; + + fn impl_repr( + &self, + meta: &SchemaMeta, + consts: TokenStream, + methods: TokenStream, + ) -> TokenStream { + let name = &meta.name; + let generics = meta.generics_tokens(); + + let name_str = meta.name_str(); + let schema = self.schema(meta); + quote! { + #[automatically_derived] + impl #generics Representation for #name #generics { + const NAME: &'static str = #name_str; + const SCHEMA: &'static str = concat!(#schema); + #consts + #methods + } + } + } + + fn impl_select(&self, meta: &SchemaMeta, rest: Option) -> TokenStream { + let methods = rest.unwrap_or(quote::quote! { + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + Seed::::from(seed).deserialize(deserializer) + } + }); + + let name = &meta.name; + // let (impl_gen, ty_gen, where_gen) = match &meta.generics { + // Some(generics) => generics.split_for_impl(), + // None => Generics::default().split_for_impl(), + // }; + quote::quote! { + #[automatically_derived] + impl Select for #name + where + Ctx: Context, + { + #methods + } + } + } } /// Helper trait for crates that want to provide auto-implementable @@ -218,40 +232,6 @@ impl SchemaKind { Span::call_site(), ) } - - pub(crate) fn selected_node_ident(&self) -> Ident { - Ident::new( - match *self { - Self::Null => "Null", - Self::Bool => "Bool", - Self::Int => "Int64", - Self::Int8 => "Int8", - Self::Int16 => "Int16", - Self::Int32 => "Int32", - Self::Int64 => "Int64", - Self::Int128 => "Int128", - Self::Uint8 => "Uint8", - Self::Uint16 => "Uint16", - Self::Uint32 => "Uint32", - Self::Uint64 => "Uint64", - Self::Uint128 => "Uint128", - Self::Float => "Float64", - Self::Float32 => "Float32", - Self::Float64 => "Float64", - Self::Bytes => "Bytes", - Self::String => "String", - Self::List => "List", - Self::Map => "Map", - Self::Link => "Link", - Self::Struct => todo!(), - Self::Union => todo!(), - Self::Enum => todo!(), - Self::Copy => todo!(), - _ => unreachable!(), - }, - Span::call_site(), - ) - } } // Helpers @@ -294,153 +274,95 @@ macro_rules! derive_newtype { #vis struct #name #generics (#$inner_ty); } }}; - // (@typedef_transparent $def:ident, $meta:ident => $inner_ty:ident) => {{ - // $crate::derive_newtype! { @typedef - // $def, $meta => $inner_ty - // #[derive(serde::Deserialize, serde::Serialize)] - // #[serde(transparent)] - // } - // }}; - (@repr { $tokens:tt } $meta:ident => $inner_ty:ident) => {{ - $crate::dev::impl_repr( - $meta, + (@repr $def:ident, $meta:ident => $inner_ty:ident { $consts:tt }) => {{ + $def.impl_repr($meta, quote::quote! { - type DataModelKind = <#$inner_ty as Representation>::DataModelKind; - type SchemaKind = <#$inner_ty as Representation>::SchemaKind; - type ReprKind = <#$inner_ty as Representation>::ReprKind; - - const DATA_MODEL_KIND: Kind = <#$inner_ty>::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = <#$inner_ty>::SCHEMA_KIND; - const IS_LINK: bool = <#$inner_ty>::IS_LINK; + #$consts const HAS_LINKS: bool = <#$inner_ty>::HAS_LINKS; - - #$tokens - - #[inline] - #[doc(hidden)] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - Representation::serialize::(&self.0, serializer) - } - - #[inline] - #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Self(Representation::deserialize::(deserializer)?)) - } + }, quote::quote! { + #[inline] + fn name(&self) -> &'static str { + Representation::name(&self.0) } - ) + #[inline] + fn has_links(&self) -> bool { + Representation::has_links(&self.0) + } + #[inline] + fn as_field(&self) -> Option> { + Representation::as_field(&self.0) + } + #[inline] + fn to_selected_node(&self) -> SelectedNode { + Representation::to_selected_node(&self.0) + } + #[inline] + fn serialize(&self, serializer: Se) -> Result + where + Se: Serializer, + { + Representation::serialize::(&self.0, serializer) + } + #[inline] + fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result + where + De: Deserializer<'de>, + { + Ok(Self(Representation::deserialize::(deserializer)?)) + } + }) }}; - (@select $meta:ident => $inner_ty:ident) => {{ - let lib = &$meta.lib; + (@select $def:ident, $meta:ident => $inner_ty:ident) => {{ let name = &$meta.name; - quote::quote! { - // #lib::dev::macros::repr_serde! { @selector_seed_codec_deseed_newtype {} {} #name as #$inner_ty - // } - // #lib::dev::macros::repr_serde! { - // @selector_seed_select {} {} #name - // } - - #lib::dev::macros::repr_serde! { - @select_newtype {} {} #name { #name => #$inner_ty } + $def.impl_select($meta, Some(quote::quote! { + #[doc(hidden)] + #[inline] + fn __select<'a>( + seed: SelectorSeed<'a, Ctx, Self>, + ) -> Result<(), Error> { + let seed = seed.wrap::<#$inner_ty, _>(#name); + <#$inner_ty as Select>::__select(seed) } - - } + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = seed.wrap::<#$inner_ty, _>(#name); + <#$inner_ty as Select>::__select_de::(seed, deserializer) + } + })) }}; - (@conv @has_constructor $def:ident, $meta:ident => - $dm_ty:ident $selected_node:ident) => {{ + (@conv @has_constructor $def:ident, $meta:ident) => {{ let name = &$meta.name; quote::quote! { + #[automatically_derived] impl From<#name> for SelectedNode { fn from(t: #name) -> Self { - Self::from(t.0) + t.0.into() } } - + #[automatically_derived] impl Into for #name { fn into(self) -> Any { self.0.into() } } - + #[automatically_derived] impl TryFrom for #name { type Error = Error; fn try_from(any: Any) -> Result { - match any { - Any::#$dm_ty(inner) => { - let any_variant = Representation::name(&inner); - let inner = inner.try_into() - .or_else(|_| Err(Error::failed_any_conversion::(any_variant)))?; - Ok(Self(inner)) - }, - _ => Err(Error::MismatchedAny) - } + let variant = Representation::name(&any); + let inner = TryFrom::try_from(any) + .map_err(|_| Error::failed_any_conversion::(variant))?; + Ok(Self(inner)) } } } - }}; -} - -pub(crate) fn impl_repr(meta: &SchemaMeta, consts_and_simple_methods: TokenStream) -> TokenStream { - let lib = &meta.lib; - let name = &meta.name; - let typedef_str = &meta.typedef_str; - let generics = meta.generics_tokens(); - quote! { - #[automatically_derived] - impl #generics #lib::dev::Representation for #name #generics { - const NAME: &'static str = ::std::stringify!(#name); - // const SCHEMA: &'static str = #typedef_str; - - #consts_and_simple_methods - } - } + }} } - -// pub(crate) fn impl_primtive_de_seed(meta: &SchemaMeta) -> TokenStream { -// let name = &meta.name; -// let lib = &meta.ipld_schema_lib; -// impl_de_seed( -// meta, -// quote! { -// match (&self).as_selector() { -// Selector::Matcher(sel) => <#name as de::Deserialize<'de>>::deserialize(deserializer), -// Selector::ExploreConditional(sel) => { -// use std::borrow::Borrow; -// let ExploreConditional { condition, next } = sel.borrow(); -// unimplemented!() -// }, -// sel => Err(de::Error::custom( -// #lib::Error::Selector::invalid_selector::<#name>(sel) -// )), -// } -// }, -// ) -// } - -// fn expand_try_from_visitor_methods(tokens: TokenStream) -> TokenStream { -// let tokens = tokens.into::(); -// let methods = parse_macro_input!(tokens as super::Methods); -// -// &methods.0.iter().map(|item_fn| { -// let sig = &item_fn.sig; -// let block = &item_fn.block; -// -// quote! { -// use ::std::convert::TryFrom; -// // let t = #try_from_ident::deserialize(deserializer)?; -// // Ok(#name::try_from(t).map_err(D::Error::custom)?) -// -// #sig { -// let -// } -// } -// }); -// tokens -// } diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index df8eedd..e3ac7d8 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -12,7 +12,7 @@ mod union; pub use compound::*; pub use expand::*; -pub use kind::{type_kinds, SchemaKind, TypedKind}; +pub use kind::SchemaKind; pub use parse::*; pub use primitive::*; pub use r#enum::*; @@ -47,6 +47,23 @@ pub struct SchemaMeta { } impl SchemaMeta { + /// Creates a `TokenStream` of the `ipld` lib used (either `crate` or the `ipld` crate name). + pub fn imports(is_internal: bool) -> TokenStream { + let lib = Self::lib(is_internal); + let r#extern = if is_internal { + quote!(use #lib as __ipld;) + } else { + quote!(extern crate #lib as __ipld;) + }; + + quote! { + #r#extern + #[allow(clippy::useless_attribute)] + use __ipld::dev::*; + __ipld::repr_serde!(@def_seed); + } + } + /// Creates a `TokenStream` of the `ipld` lib used (either `crate` or the `ipld` crate name). pub fn lib(is_internal: bool) -> TokenStream { if is_internal { @@ -63,7 +80,6 @@ impl SchemaMeta { .expect("`ipld` is not present in Cargo.toml") }, ); - quote!(#path) } @@ -74,6 +90,10 @@ impl SchemaMeta { .unwrap_or(TokenStream::default()) } + pub fn name_str(&self) -> String { + self.name.to_string() + } + // fn to_try_from_meta(&self) -> Self { // SchemaMeta { // typedef_str: String::new(), @@ -131,11 +151,8 @@ impl ReprDefinition { // #[macro_use] pub mod kind { // use super::*; - use std::ops::{BitAnd, BitOr}; - use type_kinds::*; - use typenum::*; - use typenum_macro::*; + /* /// /// TODO: BitAnd/BitOr dont work without fully-qualified syntax pub trait TypedKind @@ -164,6 +181,7 @@ pub mod kind { // + BitOr, { } + */ macro_rules! def_kind { ( $($name:ident = $b:expr;)*) => { @@ -215,17 +233,23 @@ pub mod kind { /// floating-point numbers. const TypedFloat = Self::Float32.bits | Self::Float64.bits; + const AnyInt = Self::Int.bits | Self::TypedInt.bits; + const AnyFloat = Self::Float.bits | Self::TypedFloat.bits; + + const TypedNum = Self::TypedInt.bits | Self::TypedFloat.bits; + + const Num = Self::AnyInt.bits | Self::AnyFloat.bits; + /// - const TypedScalar = Self::Scalar.bits - | Self::TypedInt.bits - | Self::TypedFloat.bits; + const TypedScalar = Self::Scalar.bits | Self::TypedNum.bits; } } + /* /// [`typenum`] types representing known [`SchemaKind`]s. /// /// [`typenum`]: typenum - pub mod type_kinds { + mod type_kinds { use super::*; $(pub type $name = tyuint!($b);)* @@ -251,6 +275,7 @@ pub mod kind { #[doc(hidden)] pub type Empty = U0; } + */ }; } @@ -320,13 +345,48 @@ pub mod kind { // } } + pub const fn is_nary(&self) -> bool { + N == self.bits.count_ones() + } + + /// dm pub const fn is_option(&self) -> bool { - self.bits.count_ones() == 2 && self.contains(Self::Null) + self.is_nary::<2>() && self.contains(Self::Null) } + // pub const fn is_int(&self) -> bool { + // self.is_nary::<1>() && (Self::Int.eq(self) || Self::TypedInt.contains(*self)) + // } + + // pub const fn is_num(&self) -> bool { + // self.is_nary::<1>() && Self::Num.contains(*self) + // } + + // pub const fn is_typed(&self) -> bool { + // self.is_nary::<1>() && Self::TypedNum.contains(*self) + // } + /// pub const fn is_link(&self) -> bool { - self.contains(Self::Link) + self.eq(&Self::Link) + } + + // /// + // pub const fn is_enum(&self) -> bool { + // match *self { + // Self::Enum | Self::String => true, + // s if s.is_nary::<1>() && Self::TypedInt.contains(s) => true, + // _ => false, + // } + // // self.is_nary::<1>() && (self.eq(&Self::String) || Self::TypedInt.contains(*self)) + // } + + pub const fn is_copy(&self) -> Option { + if self.contains(Self::Copy) { + Some(self.difference(Self::Copy)) + } else { + None + } } /// @@ -342,9 +402,9 @@ pub mod kind { // pub const fn is_ } - const fn is_unary() -> bool { - T::KIND.bits.count_ones() == 1 - } + // const fn is_unary() -> bool { + // T::KIND.is_nary::<1>() + // } // pub trait BitOps: BitAnd + BitOr {} // impl BitOps for T where T: BitAnd + BitOr {} diff --git a/macros-internals/src/schema/parse.rs b/macros-internals/src/schema/parse.rs index 62b89d2..4676826 100644 --- a/macros-internals/src/schema/parse.rs +++ b/macros-internals/src/schema/parse.rs @@ -31,7 +31,7 @@ impl Parse for SchemaMeta { let generics = input.parse::().map_or(None, Some); Ok(Self { - lib: Self::lib(internal), + lib: Default::default(), // TODO: fix this typedef_str: String::default(), internal, diff --git a/macros-internals/src/schema/primitive/expand.rs b/macros-internals/src/schema/primitive/expand.rs index 8cf5214..727ee2b 100644 --- a/macros-internals/src/schema/primitive/expand.rs +++ b/macros-internals/src/schema/primitive/expand.rs @@ -4,10 +4,7 @@ use super::{ }; use crate::{ derive_newtype, - dev::{ - schema::{expand, SchemaKind}, - SchemaMeta, - }, + dev::{schema::expand, SchemaMeta}, }; use proc_macro2::TokenStream; use quote::quote; @@ -77,14 +74,12 @@ macro_rules! derive_newtype_select { //////////////////////////////////////////////////////////////////////////////// -impl NullReprDefinition { - fn ty(meta: &SchemaMeta) -> Type { - let name = &meta.name; - Type::Verbatim(quote!(#name)) +impl expand::ExpandBasicRepresentation for NullReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} null", meta.name); + quote!(#schema) } -} -impl expand::ExpandBasicRepresentation for NullReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let attrs = &meta.attrs; let vis = &meta.vis; @@ -101,74 +96,85 @@ impl expand::ExpandBasicRepresentation for NullReprDefinition { } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; - crate::dev::impl_repr( + self.impl_repr( meta, - quote::quote! { - type DataModelKind = ::DataModelKind; - type SchemaKind = ::SchemaKind; - type ReprKind = ::ReprKind; - - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " null"); - const DATA_MODEL_KIND: Kind = ::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = ::SCHEMA_KIND; - const IS_LINK: bool = ::IS_LINK; - const HAS_LINKS: bool = ::HAS_LINKS; + quote! { + const DATA_MODEL_KIND: Kind = Kind::Null; + const SCHEMA_KIND: Kind = Kind::Null; + const REPR_KIND: Kind = Kind::Null; + }, + quote! { + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Null + } #[inline] - #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { - Representation::serialize::(&Null, serializer) + serializer.serialize_none() } - #[inline] - #[doc(hidden)] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - Null::deserialize::(deserializer)?; + <()>::deserialize(deserializer)?; Ok(Self) } }, ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { - let lib = &meta.lib; let name = &meta.name; quote::quote! { - #lib::dev::macros::repr_serde! { @select_for #name {} {} } + repr_serde! { @select for #name } + repr_serde! { @visitors for #name { + #[inline] + fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { + write!(f, "A nothing type {}", <#name>::NAME) + } + #[inline] + fn visit_none(self) -> Result + where + Er: de::Error, + { + self.into_inner() + .select_scalar::(#name) + .map_err(Er::custom) + } + #[inline] + fn visit_unit(self) -> Result + where + Er: de::Error, + { + self.visit_none() + } + }} } } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { let name = &meta.name; quote! { - impl From<()> for #name { - fn from(_: ()) -> Self { - Self - } - } - + #[automatically_derived] impl From<#name> for SelectedNode { fn from(t: #name) -> Self { Self::Null } } - + #[automatically_derived] impl Into for #name { fn into(self) -> Any { - Any::Null(Null) + Any::Null(Default::default()) } } - + #[automatically_derived] impl TryFrom for #name { type Error = Error; fn try_from(any: Any) -> Result { match any { - Any::Null(inner) => Ok(Self), + Any::Null(_) => Ok(Self), _ => Err(Error::MismatchedAny) } } @@ -186,77 +192,87 @@ impl BoolReprDefinition { } impl expand::ExpandBasicRepresentation for BoolReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} bool", meta.name); + quote!(#schema) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; let inner_ty = Self::inner_ty(); let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " bool"); + const DATA_MODEL_KIND: Kind = Kind::Bool; + const SCHEMA_KIND: Kind = Kind::Bool; + const REPR_KIND: Kind = Kind::Bool; }; - derive_newtype!(@repr { schema } meta => inner_ty) + derive_newtype!(@repr self, meta => inner_ty { schema }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = SchemaKind::Bool.data_model_kind(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty dm_ty) + derive_newtype!(@conv @has_constructor self, meta) } } //////////////////////////////////////////////////////////////////////////////// impl expand::ExpandBasicRepresentation for IntReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} int", meta.name); + quote!(#schema) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " int"); + const DATA_MODEL_KIND: Kind = <#inner_ty>::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = <#inner_ty>::SCHEMA_KIND; + const REPR_KIND: Kind = <#inner_ty>::REPR_KIND; }; - derive_newtype!(@repr { schema } meta => inner_ty) + derive_newtype!(@repr self, meta => inner_ty { schema }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = self.1.data_model_kind(); - let sn_ty = self.1.selected_node_ident(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty sn_ty) + derive_newtype!(@conv @has_constructor self, meta) } } //////////////////////////////////////////////////////////////////////////////// impl expand::ExpandBasicRepresentation for FloatReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} float", meta.name); + quote!(#schema) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " float"); + const DATA_MODEL_KIND: Kind = <#inner_ty>::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = <#inner_ty>::SCHEMA_KIND; + const REPR_KIND: Kind = <#inner_ty>::REPR_KIND; }; - derive_newtype!(@repr { schema } meta => inner_ty) + derive_newtype!(@repr self, meta => inner_ty { schema }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = self.1.data_model_kind(); - let sn_ty = self.1.selected_node_ident(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty sn_ty) + derive_newtype!(@conv @has_constructor self, meta) } } @@ -264,87 +280,64 @@ impl expand::ExpandBasicRepresentation for FloatReprDefinition { impl StringReprDefinition { fn inner_ty() -> Type { - Type::Verbatim(quote!(IpldString)) + Type::Verbatim(quote!(String)) } } impl expand::ExpandBasicRepresentation for StringReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} string", meta.name); + quote!(#schema) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; let inner_ty = Self::inner_ty(); let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " string"); + const DATA_MODEL_KIND: Kind = Kind::String; + const SCHEMA_KIND: Kind = Kind::String; + const REPR_KIND: Kind = Kind::String; }; - derive_newtype!(@repr { schema } meta => inner_ty) + derive_newtype!(@repr self, meta => inner_ty { schema }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = Self::inner_ty(); - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = SchemaKind::String.data_model_kind(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty dm_ty) + derive_newtype!(@conv @has_constructor self, meta) } } //////////////////////////////////////////////////////////////////////////////// impl expand::ExpandBasicRepresentation for CopyReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let start = format!("type {} = ", meta.name); + let inner_ty = &self.0; + quote!(concat!(#start, stringify!(#inner_ty))) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; let inner_ty = &self.0; let schema = quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(#name), " = ", stringify!(#inner_ty)); - - // #[inline] - // fn name(&self) -> &'static str { - // Representation::name(&self.0) - // } - #[inline] - fn data_model_kind(&self) -> Kind { - Representation::data_model_kind(&self.0) - } - #[inline] - fn schema_kind(&self) -> Kind { - Representation::schema_kind(&self.0) - } - #[inline] - fn repr_kind(&self) -> Kind { - Representation::repr_kind(&self.0) - } - #[inline] - fn has_links(&self) -> bool { - Representation::has_links(&self.0) - } + const DATA_MODEL_KIND: Kind = <#inner_ty>::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = <#inner_ty>::SCHEMA_KIND.union(Kind::Copy); + const REPR_KIND: Kind = <#inner_ty>::REPR_KIND; + const REPR_STRATEGY: Strategy = <#inner_ty>::REPR_STRATEGY; }; - derive_newtype!(@repr { schema } meta => inner_ty) + derive_newtype!(@repr self, meta => inner_ty { schema }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = &self.0; - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let ident = &meta.name; - quote! { - impl From<#ident> for SelectedNode { - fn from(t: #ident) -> Self { - t.0.into() - } - } - - impl Into for #ident { - fn into(self) -> Any { - self.0.into() - } - } - } + derive_newtype!(@conv @has_constructor self, meta) } } diff --git a/macros-internals/src/schema/primitive/expand_bytes.rs b/macros-internals/src/schema/primitive/expand_bytes.rs index 38b2cae..d015677 100644 --- a/macros-internals/src/schema/primitive/expand_bytes.rs +++ b/macros-internals/src/schema/primitive/expand_bytes.rs @@ -1,10 +1,7 @@ use super::BytesReprDefinition; use crate::{ derive_newtype, - dev::{ - schema::{expand, SchemaKind}, - SchemaMeta, - }, + dev::{schema::expand, SchemaMeta}, }; use proc_macro2::TokenStream; use quote::quote; @@ -21,25 +18,24 @@ impl BytesReprDefinition { impl expand::ExpandBasicRepresentation for BytesReprDefinition { fn define_type(&self, meta: &SchemaMeta) -> TokenStream { - let inner_type = self.inner_ty(); - derive_newtype!(@typedef self, meta => inner_type) + let inner_ty = self.inner_ty(); + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - expand::impl_repr( - meta, - quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " bytes"); - const DATA_MODEL_KIND: Kind = Kind::Bytes; - }, - ) + let inner_ty = self.inner_ty(); + // TODO + let consts = quote! { + const DATA_MODEL_KIND: Kind = Kind::Bytes; + const SCHEMA_KIND: Kind = Kind::Bytes; + const REPR_KIND: Kind = Kind::Bytes; + }; + derive_newtype!(@repr self, meta => inner_ty { consts }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = SchemaKind::Bytes.data_model_kind(); - let sn_ty = SchemaKind::Bytes.selected_node_ident(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty sn_ty) + derive_newtype!(@conv @has_constructor self, meta) } } diff --git a/macros-internals/src/schema/primitive/expand_link.rs b/macros-internals/src/schema/primitive/expand_link.rs index 0c2710f..a5330b9 100644 --- a/macros-internals/src/schema/primitive/expand_link.rs +++ b/macros-internals/src/schema/primitive/expand_link.rs @@ -1,10 +1,7 @@ use super::LinkReprDefinition; use crate::{ derive_newtype, - dev::{ - schema::{expand, SchemaKind}, - SchemaMeta, - }, + dev::{schema::expand, SchemaMeta}, }; use proc_macro2::TokenStream; use quote::quote; @@ -18,26 +15,28 @@ impl LinkReprDefinition { } impl expand::ExpandBasicRepresentation for LinkReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + let schema = format!("type {} link", meta.name_str()); + quote!(#schema) + } fn define_type(&self, meta: &SchemaMeta) -> TokenStream { - let inner_type = self.inner_ty(); - derive_newtype!(@typedef self, meta => inner_type) + let inner_ty = self.inner_ty(); + derive_newtype!(@typedef self, meta => inner_ty) } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - expand::impl_repr( - meta, - quote! { - const SCHEMA: &'static str = concat!("type ", stringify!(Self::NAME), " link"); - const DATA_MODEL_KIND: Kind = Kind::Link; - }, - ) + let inner_ty = self.inner_ty(); + let consts = quote! { + const DATA_MODEL_KIND: Kind = Kind::Link; + const SCHEMA_KIND: Kind = Kind::Link; + const REPR_KIND: Kind = Kind::Link; + }; + derive_newtype!(@repr self, meta => inner_ty { consts }) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { let inner_ty = self.inner_ty(); - derive_newtype!(@select meta => inner_ty) + derive_newtype!(@select self, meta => inner_ty) } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - let dm_ty = SchemaKind::Link.data_model_kind(); - let sn_ty = SchemaKind::Link.selected_node_ident(); - derive_newtype!(@conv @has_constructor self, meta => dm_ty sn_ty) + derive_newtype!(@conv @has_constructor self, meta) } } diff --git a/macros-internals/src/schema/primitive/parse.rs b/macros-internals/src/schema/primitive/parse.rs index f60574c..d0ff17b 100644 --- a/macros-internals/src/schema/primitive/parse.rs +++ b/macros-internals/src/schema/primitive/parse.rs @@ -1,6 +1,8 @@ use super::*; -use crate::dev::{common, impl_advanced_parse, parse, parse_kwarg, schema::kw}; -use proc_macro2::TokenStream; +use crate::dev::{ + impl_advanced_parse, parse_kwarg, + schema::{kw, parse}, +}; use syn::{ parse::{Parse, ParseStream, Result as ParseResult}, Path, diff --git a/macros-internals/src/schema/struct/expand.rs b/macros-internals/src/schema/struct/expand.rs index cc02182..798eaac 100644 --- a/macros-internals/src/schema/struct/expand.rs +++ b/macros-internals/src/schema/struct/expand.rs @@ -18,36 +18,14 @@ impl ExpandBasicRepresentation for StructReprDefinition { Self::Advanced(_) => unreachable!(), } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - match self { - Self::Map(repr) => repr.derive_serde(meta), - Self::Listpairs(repr) => repr.derive_serde(meta), - Self::Tuple(repr) => repr.derive_serde(meta), - Self::Stringpairs(repr) => repr.derive_serde(meta), - Self::Stringjoin(repr) => repr.derive_serde(meta), - Self::Advanced(_) => unreachable!(), - } - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; - // let lib = &meta.ipld_schema_lib; - // let repr_body = quote! { - // const KIND: Kind = Kind::Struct; - // }; - // expand::impl_repr(meta, repr_body) - let repr = match self { + match self { Self::Map(repr) => repr.derive_repr(meta), Self::Listpairs(repr) => repr.derive_repr(meta), Self::Tuple(repr) => repr.derive_repr(meta), Self::Stringpairs(repr) => repr.derive_repr(meta), Self::Stringjoin(repr) => repr.derive_repr(meta), Self::Advanced(_) => unreachable!(), - }; - - // TODO: - quote! { - #repr - // impl_root_select!(#name => Matcher); } } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { @@ -86,7 +64,6 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { quote! { #(#attrs)* - // #[derive(Deserialize, Serialize)] #vis struct #ident #generics { #(#fields,)* } @@ -99,7 +76,7 @@ impl ExpandBasicRepresentation for BasicStructReprDefinition { TokenStream::default() } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - quote!() + TokenStream::default() } } @@ -109,48 +86,6 @@ impl BasicStructReprDefinition { } } -pub(super) fn impl_repr<'a, D: Deref>( - fields: &D, - meta: &SchemaMeta, - repr_kind: &Ident, - repr_strategy: Option, -) -> TokenStream { - let lib = &meta.lib; - let name = &meta.name; - let repr_strategy = - repr_strategy.map(|strategy| quote!(const REPR_STRATEGY: Strategy = Strategy::#strategy;)); - // let fields = iter.map(|f| { - // let key = f.key.to_string(); - // let val = &f.value; - // let rename = f - // .rename - // .as_ref() - // .map(|s| s.value()) - // .unwrap_or_else(|| key.clone()); - // quote! { - // (#key, Field::new::<#val>(#rename)) - // } - // }); - - let repr_body = expand::impl_repr( - meta, - quote! { - type DataModelKind = type_kinds::Map; - type SchemaKind = type_kinds::Struct; - type ReprKind = type_kinds::#repr_kind; - - const SCHEMA: &'static str = ""; - const DATA_MODEL_KIND: Kind = Kind::Map; - const SCHEMA_KIND: Kind = Kind::Struct; - const REPR_KIND: Kind = Kind::#repr_kind; - #repr_strategy - // const FIELDS: Fields = Fields::Struct(&[#(#fields,)*]); - }, - ); - let selector_bodies = quote! {}; - repr_body -} - impl StructField { pub fn default_field_def(&self) -> TokenStream { let attrs = &self.attrs; @@ -172,11 +107,11 @@ impl StructField { let value = field_value(self); let generics = &self.generics; - let implicit_attr = self.implicit.as_ref().map(|_| quote!(#[serde(default)])); - let rename_attr = self - .rename - .as_ref() - .map(|name| quote!(#[serde(rename = #name)])); + // let implicit_attr = self.implicit.as_ref().map(|_| quote!(#[serde(default)])); + // let rename_attr = self + // .rename + // .as_ref() + // .map(|name| quote!(#[serde(rename = #name)])); quote! { #(#attrs)* @@ -187,6 +122,37 @@ impl StructField { } } +pub(super) fn impl_repr>( + repr_def: &R, + meta: &SchemaMeta, + repr_kind: &Ident, + repr_strategy: Option, +) -> TokenStream { + let static_fields = repr_def.iter().map(|f| { + let name = f + .rename + .as_ref() + .map(|s| s.value()) + .unwrap_or_else(|| f.key.to_string()); + quote!(#name) + }); + + let strategy = repr_strategy.map(|s| quote!(#s)).unwrap_or(quote!(Basic)); + repr_def.impl_repr( + meta, + quote! { + const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Struct; + const REPR_KIND: Kind = Kind::#repr_kind; + const REPR_STRATEGY: Strategy = Strategy::#strategy; + const FIELDS: &'static [&'static str] = &[ + #(#static_fields,)* + ]; + }, + Default::default(), + ) +} + pub(super) fn field_value(field: &StructField) -> TokenStream { let value = &field.value; if field.optional || field.nullable { diff --git a/macros-internals/src/schema/struct/expand_listpairs.rs b/macros-internals/src/schema/struct/expand_listpairs.rs index d3d68f0..b02a033 100644 --- a/macros-internals/src/schema/struct/expand_listpairs.rs +++ b/macros-internals/src/schema/struct/expand_listpairs.rs @@ -25,9 +25,6 @@ impl ExpandBasicRepresentation for ListpairsStructReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { super::expand::impl_repr( self, diff --git a/macros-internals/src/schema/struct/expand_stringjoin.rs b/macros-internals/src/schema/struct/expand_stringjoin.rs index 61779b2..cd325bd 100644 --- a/macros-internals/src/schema/struct/expand_stringjoin.rs +++ b/macros-internals/src/schema/struct/expand_stringjoin.rs @@ -26,9 +26,6 @@ impl ExpandBasicRepresentation for StringjoinStructReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { super::expand::impl_repr( self, diff --git a/macros-internals/src/schema/struct/expand_stringpairs.rs b/macros-internals/src/schema/struct/expand_stringpairs.rs index 263d012..23471d3 100644 --- a/macros-internals/src/schema/struct/expand_stringpairs.rs +++ b/macros-internals/src/schema/struct/expand_stringpairs.rs @@ -26,9 +26,6 @@ impl ExpandBasicRepresentation for StringpairsStructReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { super::expand::impl_repr( self, diff --git a/macros-internals/src/schema/struct/expand_tuple.rs b/macros-internals/src/schema/struct/expand_tuple.rs index fa45034..3b74bb6 100644 --- a/macros-internals/src/schema/struct/expand_tuple.rs +++ b/macros-internals/src/schema/struct/expand_tuple.rs @@ -26,9 +26,6 @@ impl ExpandBasicRepresentation for TupleStructReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { super::expand::impl_repr( self, diff --git a/macros-internals/src/schema/union/expand.rs b/macros-internals/src/schema/union/expand.rs index 66eb444..6407e19 100644 --- a/macros-internals/src/schema/union/expand.rs +++ b/macros-internals/src/schema/union/expand.rs @@ -60,55 +60,41 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { quote! { #(#attrs)* - // #[derive(Deserialize, Serialize)] #vis enum #ident { #(#fields,)* } } } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { - let lib = &meta.lib; let name_branches = self.iter().map(UnionStrField::name_branch); let kind_branches = self.iter().map(UnionStrField::kind_branch); let link_branches = self.iter().map(UnionStrField::link_branch); let serialize_branches = self.iter().map(UnionStrField::serialize_branch); // let deserialize_branches = self.iter().map(UnionStrField::deserialize_branch); - expand::impl_repr( + self.impl_repr( meta, quote! { - type DataModelKind = type_kinds::Map; - type SchemaKind = type_kinds::Union; - type ReprKind = type_kinds::Map; - - const SCHEMA: &'static str = ""; const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Union; const REPR_KIND: Kind = Kind::Map; const REPR_STRATEGY: Strategy = Strategy::Keyed; + // TODO // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); - + }, + quote! { #[inline] fn name(&self) -> &'static str { match self { #(#name_branches,)* } } - - // #[inline] - // fn kind(&self) -> Kind { - // match self { - // #(#kind_branches,)* - // } - // } - #[inline] fn has_links(&self) -> bool { match self { #(#link_branches,)* } } - - #[doc(hidden)] + #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -118,8 +104,7 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { // } unimplemented!() } - - #[doc(hidden)] + #[inline] fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -130,13 +115,38 @@ impl ExpandBasicRepresentation for KeyedUnionReprDefinition { ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { - // let name = &meta.name; - // let lib = &meta.ipld_schema_lib; - // quote!(impl_root_select!(#name => Matcher);) - TokenStream::default() + // self.impl_select(meta, None) + Default::default() } fn derive_conv(&self, meta: &SchemaMeta) -> TokenStream { - quote!() + let name = &meta.name; + quote! { + #[automatically_derived] + impl From<#name> for SelectedNode { + fn from(t: #name) -> Self { + // t.0.into() + unimplemented!() + } + } + #[automatically_derived] + impl Into for #name { + fn into(self) -> Any { + // self.0.into() + unimplemented!() + } + } + #[automatically_derived] + impl TryFrom for #name { + type Error = Error; + fn try_from(any: Any) -> Result { + // let variant = Representation::name(&any); + // let inner = TryFrom::try_from(any) + // .map_err(|_| Error::failed_any_conversion::(variant))?; + // Ok(Self(inner)) + unimplemented!() + } + } + } } } diff --git a/macros-internals/src/schema/union/expand_byte_prefix.rs b/macros-internals/src/schema/union/expand_byte_prefix.rs index 6ea2750..a459c92 100644 --- a/macros-internals/src/schema/union/expand_byte_prefix.rs +++ b/macros-internals/src/schema/union/expand_byte_prefix.rs @@ -19,9 +19,6 @@ impl ExpandBasicRepresentation for BytePrefixUnionReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { // impl_repr(self.iter(), meta) TokenStream::default() diff --git a/macros-internals/src/schema/union/expand_envelope.rs b/macros-internals/src/schema/union/expand_envelope.rs index 478ecf6..fcd79ab 100644 --- a/macros-internals/src/schema/union/expand_envelope.rs +++ b/macros-internals/src/schema/union/expand_envelope.rs @@ -19,9 +19,6 @@ impl ExpandBasicRepresentation for EnvelopeUnionReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { // impl_repr(self.iter(), meta) TokenStream::default() diff --git a/macros-internals/src/schema/union/expand_inline.rs b/macros-internals/src/schema/union/expand_inline.rs index a2b8c14..4215cd0 100644 --- a/macros-internals/src/schema/union/expand_inline.rs +++ b/macros-internals/src/schema/union/expand_inline.rs @@ -19,9 +19,6 @@ impl ExpandBasicRepresentation for InlineUnionReprDefinition { } } } - fn derive_serde(&self, meta: &SchemaMeta) -> TokenStream { - TokenStream::default() - } fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { // impl_repr(self.iter(), meta) TokenStream::default() diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index a168b90..fdb0c06 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -1,12 +1,17 @@ use super::*; -use crate::dev::schema::{ - expand::{impl_repr, ExpandBasicRepresentation}, - SchemaKind, SchemaMeta, -}; +use crate::dev::schema::{expand::ExpandBasicRepresentation, SchemaKind, SchemaMeta}; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens, TokenStreamExt}; impl ExpandBasicRepresentation for KindedUnionReprDefinition { + fn schema(&self, meta: &SchemaMeta) -> TokenStream { + // const SCHEMA: &'static str = concat!( + // "type ", #name_str, " union {", + // "}" + // ); + Default::default() + } + fn define_type(&self, meta: &SchemaMeta) -> TokenStream { let attrs = &meta.attrs; let vis = &meta.vis; @@ -27,108 +32,89 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { fn derive_repr(&self, meta: &SchemaMeta) -> TokenStream { let name = &meta.name; - let dm_ty = self.dm_ty(); - // let repr_kind = self.repr_kind(); - let name_branches = self.iter().map(UnionKindedField::name_branch); - // let kind_branches: Vec = self.iter().map(|f| f.kind_branch(&lib)).collect(); - let serialize_branches = self.iter().map(UnionKindedField::serialize_branch); - // let deserialize_branches = self.iter().map(UnionKindedField::deserialize_branch); + let dm_kind = self.dm_kind(); + let names = self.iter().map(UnionKindedField::name_branch); + let as_fields = self.iter().map(UnionKindedField::as_field_branch); + let to_selected_nodes = self.iter().map(UnionKindedField::to_selected_node_branch); + let serializes = self.iter().map(UnionKindedField::serialize_branch); + + let expecting = self.expecting(meta); let non_link_visitors = self.visitors(meta, false, false); let link_visitors = self.visitors(meta, true, false); - impl_repr( + + let consts = quote! { + const DATA_MODEL_KIND: Kind = #dm_kind; + const SCHEMA_KIND: Kind = Kind::Union; + const REPR_KIND: Kind = Kind::Any; + const REPR_STRATEGY: Strategy = Strategy::Kinded; + // TODO + // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); + }; + self.impl_repr( meta, + consts, quote! { - type DataModelKind = #dm_ty; - type SchemaKind = type_kinds::Union; - // FIXME: - // cannot be the literal union of the types, as that - // confuses the type checker - type ReprKind = type_kinds::Any; - - const SCHEMA: &'static str = ""; - const DATA_MODEL_KIND: Kind = <#dm_ty>::KIND; - const SCHEMA_KIND: Kind = Kind::Union; - const REPR_KIND: Kind = type_kinds::Any::KIND; - // const FIELDS: Fields = Fields::Keyed(&[#(#fields,)*]); - #[inline] fn name(&self) -> &'static str { match self { - #(#name_branches,)* + #(#names,)* } } - - // #[inline] - // fn kind(&self) -> Kind { - // match self { - // #(#kind_branches,)* - // } - // } - - #[doc(hidden)] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { + #[inline] + fn as_field(&self) -> Option> { match self { - #(#serialize_branches,)* + #(#as_fields,)* } } - - #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct KindedVisitor; - impl<'de, const C: u64> Visitor<'de> for KindedVisitor { + #[inline] + fn to_selected_node(&self) -> SelectedNode { + match self { + #(#to_selected_nodes,)* + } + } + #[inline] + fn serialize( + &self, serializer: Se + ) -> Result { + match self { + #(#serializes,)* + } + } + #[inline] + fn deserialize<'de, const MC: u64, De: Deserializer<'de>>(de: De) -> Result { + struct V; + impl<'de, const MC: u64> Visitor<'de> for V { type Value = #name; - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", stringify!(#name)) - } + #expecting #(#non_link_visitors)* } - impl<'de, const C: u64> LinkVisitor<'de> for KindedVisitor { + impl<'de, const MC: u64> LinkVisitor<'de, MC> for V { #(#link_visitors)* } - Multicodec::deserialize_any::(deserializer, KindedVisitor::) + Multicodec::deserialize_any::(de, V::) } }, ) } fn derive_select(&self, meta: &SchemaMeta) -> TokenStream { - let lib = &meta.lib; let name = &meta.name; - let dm_ty = self.dm_ty(); + let expecting = self.expecting(meta); let non_link_visitors = self.visitors(meta, false, true); let link_visitors = self.visitors(meta, true, true); - // TODO: add a method that does the delegation to the variant, rather than codegen each + let select = self.impl_select(meta, None); quote! { - #lib::dev::macros::repr_serde! { @visitors for #name => #name - { @dk (#dm_ty) @sk (type_kinds::Union) @rk (type_kinds::Any) } - {} {} - @serde { - #[inline] - fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { - write!(f, "A `{}`", <#name as Representation>::NAME) - } - #(#non_link_visitors)* - } - @link { - #(#link_visitors)* - } - } - - #lib::dev::macros::repr_serde! { @select_for #name => #name - { @dk (#dm_ty) @sk (type_kinds::Union) @rk (type_kinds::Any) } - {} {} - } + #select + repr_serde!(@visitors for #name where @serde { + #expecting + #(#non_link_visitors)* + } @link { + #(#link_visitors)* + }); } } @@ -138,20 +124,23 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { } impl KindedUnionReprDefinition { - // TODO: should be the union of all the actual type's data models (since they may not be the standard) - // fn dm_kind(&self) -> TokenStream { - // self.iter() - // .map(|f| f.dm_kind()) - // .fold(quote!(Kind::empty()), |ts, kind| quote!(#ts.union(#kind))) - // } - - fn dm_ty(&self) -> TokenStream { + fn dm_kind(&self) -> TokenStream { self.iter().map(|f| f.ty(true)).fold( - quote!(type_kinds::Empty), - |ts, ty| quote!(typenum::Or<#ts, <#ty as Representation>::DataModelKind>), + quote!(Kind::empty()), + |ts, ty| quote!(#ts.union(<#ty as Representation>::DATA_MODEL_KIND)), ) } + fn expecting(&self, meta: &SchemaMeta) -> TokenStream { + let name = &meta.name; + quote! { + #[inline] + fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { + write!(f, "A `{}`", stringify!(#name)) + } + } + } + fn visitors<'a>( &'a self, meta: &'a SchemaMeta, @@ -178,31 +167,13 @@ impl UnionKindedField { &self.value } - fn dm_kind(&self) -> TokenStream { - match self.key { - SchemaKind::Null => quote!(Kind::Null), - SchemaKind::Bool => quote!(Kind::Bool), - SchemaKind::Int => quote!(Kind::Int), - SchemaKind::Float => quote!(Kind::Float), - SchemaKind::String => quote!(Kind::String), - SchemaKind::Bytes => quote!(Kind::Bytes), - SchemaKind::List => quote!(Kind::List), - SchemaKind::Map => quote!(Kind::Map), - SchemaKind::Link => quote!(Kind::Link), - _ => unreachable!(), - } - } - fn ty(&self, with_wrapper: bool) -> TokenStream { + let name = self.name(); let generics = &self.generics; - let ty = match self.key { - SchemaKind::String => Ident::new("IpldString", Span::call_site()), - _ => self.value.clone(), - }; self.linked - .then(|| quote!(Link<#ty #generics>)) - .or_else(|| Some(quote!(#ty #generics))) + .then(|| quote!(Link<#name #generics>)) + .or_else(|| Some(quote!(#name #generics))) .map(|ty| match &self.wrapper { Some(wrapper) if with_wrapper => quote!(#wrapper <#ty>), _ => ty, @@ -235,28 +206,19 @@ impl UnionKindedField { fn name_branch(&self) -> TokenStream { let name = self.name(); - // let ty = &self.value; quote!(Self::#name(ty) => Representation::name(ty)) } - - fn dm_kind_branch(&self) -> TokenStream { - let name = self.name(); - quote!(Self::#name(ty) => Representation::data_model_kind(ty)) - } - - fn schema_kind_branch(&self) -> TokenStream { + fn as_field_branch(&self) -> TokenStream { let name = self.name(); - quote!(Self::#name(ty) => Representation::schema_kind(ty)) + quote!(Self::#name(ty) => Representation::as_field(ty)) } - - fn repr_kind_branch(&self) -> TokenStream { + fn to_selected_node_branch(&self) -> TokenStream { let name = self.name(); - quote!(Self::#name(ty) => Representation::repr_kind(ty)) + quote!(Self::#name(ty) => Representation::to_selected_node(ty)) } - fn serialize_branch(&self) -> TokenStream { let name = self.name(); - quote!(Self::#name(ty) => Representation::serialize::(ty, serializer)) + quote!(Self::#name(ty) => Representation::serialize::(ty, serializer)) } } @@ -315,7 +277,7 @@ impl UnionKindedField { for_seed: bool, ) -> impl Iterator + '_ { let name = &meta.name; - let field_name = self.name(); + let variant = self.name(); let ty = self.ty(false); let visit_impl = { // TODO: match key's REPR_KIND @@ -330,14 +292,15 @@ impl UnionKindedField { if for_seed { quote! { - let seed = self.0 - .wrap::<#ty, _>(|dag| #name::#field_name(dag.into())); - <#ty>::__select_de::(seed, #deserializer) + let seed = self + .into_inner() + .wrap::<#ty, _>(|dag: #ty| #name::#variant(dag.into())); + <#ty>::__select_de::(seed, #deserializer) } } else { quote! { - let inner = <#ty as Representation>::deserialize::(#deserializer)?; - Ok(#name::#field_name(inner.into())) + let dag = <#ty as Representation>::deserialize::(#deserializer)?; + Ok(#name::#variant(dag.into())) } } }; diff --git a/macros-internals/src/schema2/mod.rs b/macros-internals/src/schema2/mod.rs new file mode 100644 index 0000000..1d29b96 --- /dev/null +++ b/macros-internals/src/schema2/mod.rs @@ -0,0 +1,223 @@ +//! +//! Representation/Node/Select/Patch/Merge edge-ish cases: +//! - unit struct ==> Null +//! - newtypes ==> delegate to inner (copy) +//! - structs ==> structs +//! - enums w/ discrims ==> int/str enum +//! - enums ==> unions + +mod representation; +mod select; + +pub use representation::{DeriveRepresentation, ReprKind, SchemaKind}; + +use crate::dev::*; +use darling::{ + ast::{self, Data as Body, GenericParam, Style}, + util::{self, SpannedValue}, + Error, FromDeriveInput, FromField, FromMeta, FromVariant, +}; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::{ + parse::{Parse, ParseStream, Result as ParseResult}, + punctuated::Punctuated, + spanned::Spanned, + token::Add, + Attribute, Expr, Field, Generics, Ident, LitStr, Type, TypeParamBound, Variant, Visibility, +}; + +macro_rules! proc_macro_compat { + ($t:ident) => { + impl Parse for $t { + // todo: validation + fn parse(input: ParseStream) -> ParseResult { + // println!("{}", &input); + let input = syn::DeriveInput::parse(input)?; + // // println!("{:?}", &input); + Ok(Self::from_derive_input(&input)?) + } + } + + impl ToTokens for $t { + fn to_tokens(&self, tokens: &mut TokenStream) { + let imports = self.imports(); + let scope = self.scope(); + let derive_impl = self.derive(); + tokens.append_all(quote! { + // #typedef + const #scope: () = { + #imports + + #[automatically_derived] + #derive_impl + }; + }); + } + } + }; +} + +proc_macro_compat!(DeriveRepresentation); +// proc_macro_compat!({ 'S' as u64 }); + +// #[derive(Clone, Debug, FromDeriveInput)] +// #[darling( +// attributes(ipld), +// // forward_attrs(cfg), +// // supports(any) +// )] +// pub enum IpldDeriveInput { +// Null, +// Newtype, +// // TupleStruct, +// Struct, +// Enum +// } + +#[derive(Clone, Debug, FromDeriveInput)] +#[darling(attributes(ipld), forward_attrs(cfg, repr), supports(any))] +pub struct Ipld { + vis: Visibility, + ident: Ident, + // generics: ast::Generics, + generics: Generics, + data: Body, + attrs: Vec, + + // attrs + #[darling(default)] + internal: bool, + // TODO: figure out how to handle this + #[darling(default, rename = "repr")] + repr_kind: SpannedValue, + #[darling(default, rename = "where_ctx")] + where_ctx: Option>, + #[darling(default, rename = "merge")] + merge: Option, + // include: Option>, +} + +impl Ipld { + /// + pub fn expand(self) -> TokenStream + where + Self: ToTokens, + { + self.into_token_stream() + } + + fn discriminant(&self) -> Option<&Expr> { + self.data + .as_ref() + .take_enum() + .and_then(|v| v[0].discriminant.as_ref()) + } + + fn fields(&self) -> impl Iterator { + self.data.as_ref().take_struct().unwrap().into_iter() + } + + fn schema_kind(&self) -> Result { + use ReprKind::*; + use SchemaKind::*; + + let body = &self.data; + let repr_kind = *self.repr_kind.as_ref(); + match body { + Body::Struct(fields) => match (fields.style, repr_kind) { + // unit == null + (Style::Unit, Default) => Ok(Null), + // copy == newtype + (Style::Tuple, Default | Transparent) if fields.is_newtype() => Ok(Copy), + // tuple def or repr == tuple struct + (Style::Tuple, Default | Tuple) => Ok(Struct(Tuple)), + // struct == repr + (Style::Struct, Default | Tuple | Stringpairs | Stringjoin | Listpairs) => { + Ok(Struct(repr_kind)) + } + _ => Err(Error::unsupported_shape( + "invalid null, transparent/newtype (copy), or struct schema definition/representation", + )), + }, + Body::Enum(variants) => match (variants, repr_kind) { + // enum + (v, Default) if v.iter().all(|v| v.discriminant.is_some()) => Ok(Enum), + // union + (_, Default) => Ok(Union(Keyed)), + (_, Keyed | Kinded | Envelope | Inline | Bytesprefix | Stringprefix) => { + Ok(Union(repr_kind)) + } + _ => Err(Error::unsupported_shape( + "invalid enum or union schema definition/representation", + )), + }, + } + } +} + +impl Ipld { + fn imports(&self) -> TokenStream { + SchemaMeta::imports(self.internal) + } + + fn scope(&self) -> Ident { + Ident::new(&format!("_{}_FOR_{}", T, &self.ident), Span::call_site()) + } +} + +/// +#[derive(Clone, Debug, FromField)] +#[darling(attributes(ipld))] +pub struct IpldField { + vis: Visibility, + ident: Option, + ty: Type, + attrs: Vec, + + // attrs + #[darling(default)] + wrapper: Option, + #[darling(default)] + skip: bool, + // #[darling(default)] + // nullable: bool, + // #[darling(default)] + // optional: bool, + // #[darling(default)] + // implicit: bool, + // #[darling(default)] + // linked: bool, + #[darling(default)] + rename: Option, +} + +#[derive(Clone, Debug, FromVariant)] +#[darling(attributes(ipld))] +pub struct IpldVariant { + ident: Ident, + discriminant: Option, + fields: ast::Fields, + attrs: Vec, + + // attrs + #[darling(default)] + wrapper: Option, +} + +#[derive(Clone, Debug, FromMeta)] +#[darling(and_then = "Self::validate")] +pub struct IpldFieldCardinality { + // #[darling(default)] + // nullable: bool, + // #[darling(default)] + // optional: bool, + // #[darling(default)] + // implicit: bool, +} + +impl IpldFieldCardinality { + fn validate(self) -> Result { + Ok(self) + } +} diff --git a/macros-internals/src/schema2/representation.rs b/macros-internals/src/schema2/representation.rs new file mode 100644 index 0000000..9552020 --- /dev/null +++ b/macros-internals/src/schema2/representation.rs @@ -0,0 +1,246 @@ +use std::fmt; + +use super::Ipld; +use crate::dev::*; +use darling::{ + ast::{self, Data as Body, GenericParam}, + util, Error, FromDeriveInput, FromField, FromMeta, FromVariant, +}; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::{ + parse::{Parse, ParseStream, Result as ParseResult}, + parse_quote, + punctuated::Punctuated, + token::Add, + Attribute, Expr, Field, Generics, Ident, LitStr, Type, TypeParamBound, Variant, Visibility, +}; + +pub const CODE: u64 = 'R' as u64; + +pub type DeriveRepresentation = Ipld; + +/// Representation kinds for schema types. +#[derive(Copy, Clone, Debug, PartialEq, Eq, FromMeta)] +#[darling(rename_all = "snake_case")] +pub enum ReprKind { + // defaults for structs (maps), enums (int/str), and unions (??) + Default, + // copy (newtype) + Transparent, + Tuple, + Stringpairs, + Stringjoin, + Listpairs, + Keyed, + Kinded, + Envelope, + Inline, + Bytesprefix, + Stringprefix, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum SchemaKind { + Null, + Struct(ReprKind), + Enum, + Union(ReprKind), + Copy, +} + +// impl Kind { +// fn validate(&self, implied: Self) -> Option { +// use Kind::*; +// match (input.unwrap_or_default(), implied) { +// (r#in, im) if r#in == im => Some(im), +// (Default, _) => Some(implied), +// } +// } +// } + +impl Default for ReprKind { + fn default() -> Self { + Self::Default + } +} + +impl DeriveRepresentation { + fn validate(&self) -> ParseResult<()> { + Ok(()) + } + + pub(crate) fn derive(&self) -> TokenStream { + let name = &self.ident; + let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); + let body = match self.schema_kind().unwrap() { + SchemaKind::Null => self.expand_null(), + SchemaKind::Struct(_) => Default::default(), + SchemaKind::Enum => Default::default(), + SchemaKind::Union(_) => Default::default(), + SchemaKind::Copy => self.expand_newtype(), + }; + + quote! { + impl #impl_generics Representation for #name #ty_generics #where_clause { + #body + } + } + } + + pub(crate) fn expand_null(&self) -> TokenStream { + let name = &self.ident; + let schema = self.to_string(); + + quote! { + const NAME: &'static str = stringify!(#name); + const SCHEMA: &'static str = #schema; + const DATA_MODEL_KIND: Kind = Kind::Null; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Null + } + + #[doc(hidden)] + #[inline] + fn serialize(&self, serializer: __S) -> Result<__S::Ok, __S::Error> + where + __S: Serializer, + { + serializer.serialize_none() + } + + #[doc(hidden)] + #[inline] + fn deserialize<'de, const __C: u64, __D>(deserializer: __D) -> Result + where + __D: Deserializer<'de>, + { + <()>::deserialize(deserializer)?; + Ok(Self) + } + } + } + + pub(crate) fn expand_newtype(&self) -> TokenStream { + let name = &self.ident; + let inner = &self.fields().next().unwrap().ty; + let schema = self.to_string(); + + quote! { + const NAME: &'static str = stringify!(#name); + const SCHEMA: &'static str = #schema; + const DATA_MODEL_KIND: Kind = + <#inner as Representation>::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = + <#inner as Representation>::SCHEMA_KIND.union(Kind::Copy); + // TODO: + const REPR_KIND: Kind = + <#inner as Representation>::REPR_KIND; + const REPR_STRATEGY: Strategy = + <#inner as Representation>::REPR_STRATEGY; + const HAS_LINKS: bool = + <#inner as Representation>::HAS_LINKS; + + #[inline] + fn name(&self) -> &'static str { + Representation::name(&self.0) + } + #[inline] + fn has_links(&self) -> bool { + Representation::has_links(&self.0) + } + #[inline] + fn as_field(&self) -> Option> { + Representation::as_field(&self.0) + } + #[inline] + fn to_selected_node(&self) -> SelectedNode { + Representation::to_selected_node(&self.0) + } + #[inline] + fn serialize(&self, serializer: __S) -> Result<__S::Ok, __S::Error> + where + __S: Serializer, + { + Representation::serialize::<__C, __S>(&self.0, serializer) + } + #[inline] + fn deserialize<'de, const __C: u64, __D>(deserializer: __D) -> Result + where + __D: Deserializer<'de>, + { + Ok(Self(Representation::deserialize::<__C, __D>(deserializer)?)) + } + } + } + + fn expand_map(&self) -> TokenStream { + let name = &self.ident; + let inner = &self.fields().next().unwrap().ty; + let schema = { + let inner: Ident = parse_quote!(#inner); + format!("type {} = {}", name, &inner) + }; + + quote! { + const NAME: &'static str = stringify!(#name); + const SCHEMA: &'static str = #schema; + const DATA_MODEL_KIND: Kind = + <#inner as Representation>::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = + <#inner as Representation>::SCHEMA_KIND.union(Kind::Copy); + // TODO: + const REPR_KIND: Kind = + <#inner as Representation>::REPR_KIND; + const REPR_STRATEGY: Strategy = + <#inner as Representation>::REPR_STRATEGY; + const HAS_LINKS: bool = + <#inner as Representation>::HAS_LINKS; + + #[inline] + fn name(&self) -> &'static str { + Representation::name(&self.0) + } + #[inline] + fn has_links(&self) -> bool { + Representation::has_links(&self.0) + } + #[inline] + fn as_field(&self) -> Option> { + Representation::as_field(&self.0) + } + #[inline] + fn to_selected_node(&self) -> SelectedNode { + Representation::to_selected_node(&self.0) + } + #[inline] + fn serialize(&self, serializer: __S) -> Result<__S::Ok, __S::Error> + where + __S: Serializer, + { + Representation::serialize::<__C, __S>(&self.0, serializer) + } + #[inline] + fn deserialize<'de, const __C: u64, __D>(deserializer: __D) -> Result + where + __D: Deserializer<'de>, + { + Ok(Self(Representation::deserialize::<__C, __D>(deserializer)?)) + } + } + } +} + +impl fmt::Display for DeriveRepresentation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.schema_kind().or(Err(fmt::Error))? { + SchemaKind::Null => write!(f, "type {} null", &self.ident), + SchemaKind::Struct(repr) => unimplemented!(), + SchemaKind::Enum => unimplemented!(), + SchemaKind::Union(repr) => unimplemented!(), + SchemaKind::Copy => unimplemented!(), + _ => unimplemented!(), + } + } +} diff --git a/macros-internals/src/schema2/select.rs b/macros-internals/src/schema2/select.rs new file mode 100644 index 0000000..5378aee --- /dev/null +++ b/macros-internals/src/schema2/select.rs @@ -0,0 +1,34 @@ +use super::{representation::ReprKind, Ipld}; +use crate::dev::*; +use darling::{ + ast::{self, Data as Body, GenericParam}, + util, Error, FromDeriveInput, FromField, FromMeta, FromVariant, +}; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::{ + parse::{Parse, ParseStream, Result as ParseResult}, + punctuated::Punctuated, + token::Add, + Attribute, Expr, Field, Generics, Ident, LitStr, Type, TypeParamBound, Variant, Visibility, +}; + +pub const CODE: u64 = 'S' as u64; + +impl Ipld { + fn validate(&self) -> ParseResult<()> { + Ok(()) + } + + pub(crate) fn derive(&self) -> TokenStream { + Default::default() + } + + pub(crate) fn expand_null(&self) -> TokenStream { + Default::default() + } + + pub(crate) fn expand_newtype(&self) -> TokenStream { + Default::default() + } +} diff --git a/macros/src/lib.rs b/macros/src/lib.rs index bac598e..26627a3 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -4,11 +4,10 @@ //! - support pub/pub(crate) and additional #[derive(...)] statements //! - anything can have an advanced representation, so add support to all types +extern crate proc_macro; + use ipld_macros_internals::{ - // def_attributes, - RootSelectorDefinition, - // ValueDefinition, - SchemaDefinition, + schema2::DeriveRepresentation, RootSelectorDefinition, SchemaDefinition, }; use proc_macro::TokenStream; use syn::parse_macro_input; @@ -18,12 +17,13 @@ use syn::parse_macro_input; /// TODO: rename attrs to ipld_macros(), add a `wrap = Box/Rc/etc` attr #[proc_macro] pub fn schema(input: TokenStream) -> TokenStream { - let schema = parse_macro_input!(input as SchemaDefinition); - TokenStream::from(schema.expand()) + parse_macro_input!(input as SchemaDefinition) + .expand() + .into() } -/// A no-op macro, used to help the `schema!` and `selector!` macros capture -/// relevant arguments. +/// An attribute macro, used to help the `schema!` and `selector!` macros +/// capture relevant arguments. #[proc_macro_attribute] pub fn ipld_attr(_attr: TokenStream, items: TokenStream) -> TokenStream { items @@ -32,13 +32,32 @@ pub fn ipld_attr(_attr: TokenStream, items: TokenStream) -> TokenStream { /// #[proc_macro] pub fn selector(input: TokenStream) -> TokenStream { - let selector = parse_macro_input!(input as RootSelectorDefinition); - TokenStream::from(selector.expand()) + parse_macro_input!(input as RootSelectorDefinition) + .expand() + .into() +} + +// derive API + +/// +#[proc_macro_derive(Representation, attributes(ipld))] +pub fn derive_representation(input: TokenStream) -> TokenStream { + parse_macro_input!(input as DeriveRepresentation) + .expand() + .into() } -// def_attributes!( -// #[doc(hidden)] -// ipld_macros_internal -// ); -// def_attributes!(try_from); -// def_attributes!(wrap); +// #[proc_macro_derive(Select, attributes(ipld))] +// pub fn derive_select(input: TokenStream) -> TokenStream { +// parse_macro_input!(input as DeriveSelect).expand().into() +// } +// +// #[proc_macro_derive(Patch, attributes(ipld))] +// pub fn derive_patch(input: TokenStream) -> TokenStream { +// parse_macro_input!(input as DerivePatch).expand().into() +// } +// +// #[proc_macro_derive(Merge, attributes(ipld))] +// pub fn derive_merge(input: TokenStream) -> TokenStream { +// parse_macro_input!(input as DeriveMerge).expand().into() +// } diff --git a/src/cid.rs b/src/cid.rs index 22a1ed2..4911221 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -1,18 +1,22 @@ -use crate::dev::*; +use crate::dev::{macros::*, *}; +use arrayvec::ArrayVec; use cid::Error as CidError; use maybestd::{cmp, convert::TryFrom, fmt, hash, io, str::FromStr}; use multibase::Error as MultibaseError; +/// +pub const DEFAULT_CID_SIZE: usize = 64; + /// #[derive(Copy, Clone, Debug, Eq)] -pub struct Cid { - pub(crate) inner: cid::CidGeneric<{ Self::SIZE }>, +pub struct Cid { + pub(crate) inner: cid::CidGeneric, multibase: Multibase, } -impl Cid { +impl Cid { /// Allocated size of the [`Cid`]'s underlying [`Multihash`], in bytes. - pub const SIZE: usize = 64; + pub const SIZE: usize = S; /// The default [`Multibase`] to use when encoding a non-v0 [`Cid`] as a /// string. @@ -47,6 +51,19 @@ impl Cid { // } // } + /// + #[inline] + pub const fn multihash(&self) -> &DefaultMultihash { + // self.inner.hash() + unimplemented!() + } + + /// + #[inline] + pub const fn multibase(&self) -> Multibase { + self.multibase + } + /// #[inline] pub fn multicodec(&self) -> Result { @@ -55,14 +72,18 @@ impl Cid { /// #[inline] - pub const fn multihash(&self) -> &DefaultMultihash { - self.inner.hash() + pub fn multihasher(&self) -> Result { + Multihasher::try_from(self.multihash_code()) } /// #[inline] - pub const fn multibase(&self) -> Multibase { - self.multibase + pub fn generator(&self) -> Result { + Ok(CidGenerator::new( + self.version(), + self.multicodec_code(), + self.multihasher()?, + )) } /// @@ -81,6 +102,20 @@ impl Cid { // unimplemented!() // } + // #[inline] + // const fn len(version: Version, mc: u64, mh: u64, digest_len: usize) -> usize { + // // len( varints for version, mc, mh ) + len(digest) + // unimplemented!() + // } + + /// + pub fn to_writer(writer: W) -> Result<(), Error> { + // calculate total len + // write varints for cid version, mc, mh + // write digest + unimplemented!() + } + /// #[inline] pub fn to_bytes(&self) -> Vec { @@ -97,24 +132,31 @@ impl Cid { /// #[inline] pub const fn from(inner: DefaultCid) -> Self { - let multibase = Self::default_multibase(&inner); - Self { inner, multibase } + // let multibase = Self::default_multibase(&inner); + // Self { inner, multibase } + unimplemented!() } - /// Generates an [`Cid`] from a [`BufRead`] of a block's bytes. - pub fn new( + /// Generates an [`Cid`] from a [`io::Read`] of a block's bytes. + pub fn from_reader( cid_version: Version, multicodec_code: u64, multihash_code: u64, - block: R, + mut block: R, ) -> Result { - let hasher = Multihash::try_from(multihash_code)?; - CidGenerator::new(cid_version, multicodec_code, hasher).derive(block) + let mut generator = CidGenerator::new( + cid_version, + multicodec_code, + Multihasher::try_from(multihash_code)?, + ); + // io::copy(&mut block, &mut generator).map_err(CidError::Io)?; + // generator.try_finalize() + unimplemented!() } /// - pub fn derive_new(&self, block: R) -> Result { - Self::new( + pub fn derive_from_reader(&self, block: R) -> Result { + Self::from_reader( self.version(), self.multicodec_code(), self.multihash_code(), @@ -135,7 +177,7 @@ impl Cid { } } - const fn default_multibase(cid: &CidGeneric) -> Multibase { + const fn default_multibase(cid: &CidGeneric) -> Multibase { match cid.version() { Version::V0 => Multibase::Base58Btc, _ => Self::DEFAULT_MULTIBASE, @@ -143,29 +185,28 @@ impl Cid { } } -impl Representation for Cid { - type DataModelKind = type_kinds::Link; - type SchemaKind = type_kinds::Link; - type ReprKind = type_kinds::Link; - +/* +impl Representation for CidGeneric { const NAME: &'static str = "Cid"; const SCHEMA: &'static str = "type Cid &Any"; const DATA_MODEL_KIND: Kind = Kind::Link; - const SCHEMA_KIND: Kind = Kind::Link; - const REPR_KIND: Kind = Kind::Link; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Link(*self) + } /// #[inline] - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, serializer: Se) -> Result where - S: Serializer, + Se: Serializer, { - Multicodec::serialize_link::(self, serializer) + Multicodec::serialize_link::(self, serializer) } /// #[inline] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { @@ -174,7 +215,11 @@ impl Representation for Cid { type Value = Cid; #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "a Cid containing a Multihash of max {} bytes", Cid::SIZE) + write!( + f, + "a Cid containing a Multihash of max {} bytes", + S + ) } #[inline] fn visit_bytes(self, bytes: &[u8]) -> Result @@ -201,8 +246,77 @@ impl Representation for Cid { } } - if Multicodec::is_known::() { - Multicodec::deserialize_link::(deserializer, CidVisitor) + if Multicodec::is_known::() { + Multicodec::deserialize_link::(deserializer, CidVisitor) + } else { + Ok(Self::from(Deserialize::deserialize(deserializer)?)) + } + } +} + */ + +impl Representation for Cid { + const NAME: &'static str = "Cid"; + const SCHEMA: &'static str = "type Cid &Any"; + const DATA_MODEL_KIND: Kind = Kind::Link; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Link(*self) + } + + /// + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Multicodec::serialize_link::(self, serializer) + } + + /// + #[inline] + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CidVisitor; + impl<'de, const MC: u64> Visitor<'de> for CidVisitor { + type Value = Cid; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "a Cid containing a Multihash of max {} bytes", + ::SIZE + ) + } + #[inline] + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + self.visit_link_bytes(bytes) + } + #[inline] + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + self.visit_link_str(s) + } + } + impl<'de, const MC: u64> LinkVisitor<'de, MC> for CidVisitor { + // #[inline] + // fn visit_cid(self, cid: Cid) -> Result + // where + // E: de::Error, + // { + // Ok(cid) + // } + } + + if Multicodec::is_known::() { + Multicodec::deserialize_link::(deserializer, CidVisitor) } else { Ok(Self::from(Deserialize::deserialize(deserializer)?)) } @@ -220,21 +334,21 @@ impl Representation for Cid { // // impl_selector_seed_serde! { @selector_seed_codec_deseed {} {} Cid { // #[inline] -// fn deserialize(self, deserializer: D) -> Result<(), D::Error> +// fn deserialize(self, deserializer: D) -> Result<(), D::Error> // where // D: Deserializer<'de>, // { // cfg_if::cfg_if! { // if #[cfg(feature = "dag-json")] { -// if C == DagJson::CODE { -// DagJson::deserialize_link(deserializer, CodecSeed::(self)) +// if MC == DagJson::CODE { +// DagJson::deserialize_link(deserializer, CodecSeed::(self)) // } else { // // Deserialize::deserialize(deserializer) // unimplemented!() // } // } else if #[cfg(feature = "dag-cbor")] { -// if C == DagJson::CODE { -// DagCbor::deserialize_link(deserializer, CodecSeed::(self)) +// if MC == DagJson::CODE { +// DagCbor::deserialize_link(deserializer, CodecSeed::(self)) // } else { // // Deserialize::deserialize(deserializer) // unimplemented!() @@ -279,21 +393,22 @@ impl PartialOrd for Cid { } } -impl PartialEq for Cid { - fn eq(&self, other: &Self) -> bool { - self.eq(&other.inner) - } -} - -impl PartialEq> for Cid { +impl PartialEq> for Cid { #[inline] - fn eq(&self, other: &CidGeneric) -> bool { + fn eq(&self, other: &CidGeneric) -> bool { self.version() == other.version() && self.multicodec_code() == other.codec() && self.digest() == other.hash().digest() } } +impl PartialEq> for Cid { + #[inline] + fn eq(&self, other: &Cid) -> bool { + self.eq(&other.inner) + } +} + impl From for Cid { fn from(inner: DefaultCid) -> Self { Self::from(inner) @@ -354,7 +469,7 @@ impl fmt::Display for Cid { // self.inner.serialize(serializer) // } // } - +// // impl<'de> Deserialize<'de> for Cid { // fn deserialize(deserializer: D) -> Result // where @@ -364,56 +479,162 @@ impl fmt::Display for Cid { // } // } -/// A generator of [`Cid`]s. -#[derive(Debug)] -pub struct CidGenerator { - version: Version, - mc_code: u64, - hasher: Multihash, +/// A wrapper around an [`io::Write`] that can produce a [`Cid`] of the written +/// block bytes. +#[derive( + // Builder, + Debug, +)] +// #[builder(pattern = "owned")] +pub struct BlockWriter { + generator: CidGenerator, + writer: W, } -impl CidGenerator { +impl BlockWriter { + /// + #[inline] + pub const fn new(generator: CidGenerator, writer: W) -> Self { + Self { generator, writer } + } + + /// Tap the [`BlockWriter`] to generate a [`Cid`] from the current + /// [`Multihasher`], resetting it. + pub fn tap(&mut self) -> Result { + Ok(self.generator.try_finalize()?) + } + + // /// + // pub fn into_inner(self) -> impl io::Write { + // self.writer + // } +} + +impl io::Write for BlockWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + let len = self.writer.write(buf)?; + self.generator.multihasher.update(&buf[..len]); + Ok(len) + } + + fn flush(&mut self) -> io::Result<()> { + self.writer.flush() + } +} + +/// A wrapper around an [`io::Read`] that can produce a [`Cid`] of the read +/// block bytes, useful for pass-through verification. +#[derive( + // Builder, + Debug, +)] +// #[builder(pattern = "owned")] +pub struct BlockReader { + buf: ArrayVec, + generator: CidGenerator, + reader: R, +} + +impl BlockReader { /// - pub fn new(version: Version, multicodec_code: u64, hasher: Multihash) -> Self { + #[inline] + pub const fn new(generator: CidGenerator, reader: R) -> Self { Self { - version, - mc_code: multicodec_code, - hasher, + buf: ArrayVec::new_const(), + generator, + reader, } } - fn derive(mut self, mut block: R) -> Result { - io::copy(&mut block, &mut self).map_err(CidError::Io)?; - let inner = DefaultCid::new(self.version, self.mc_code, self.hasher.try_finalize()?)?; - Ok(Cid::from(inner)) + /// Tap the [`BlockReader`] to generate a [`Cid`] from the current + /// [`Multihasher`], resetting it. + pub fn tap(&mut self) -> Result { + Ok(self.generator.try_finalize()?) } + + // /// + // pub fn into_inner(self) -> impl io::Read { + // self.reader + // } } -impl multihash::Hasher for CidGenerator { - #[inline] - fn update(&mut self, input: &[u8]) { - self.hasher.update(input) +impl io::Read for BlockReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // let len = self.reader.read(buf)?; + // // FIXME: not recommend to read from buf + // self.generator.multihasher.update(&buf[..len]); + // Ok(len) + unimplemented!() } +} + +impl io::BufRead for BlockReader { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + // io::BufRead::fill_buf(&mut self.reader) + unimplemented!() + } + + fn consume(&mut self, amt: usize) { + // io::BufRead::consume(&mut self.reader, amt) + unimplemented!() + } +} + +/// A generator of [`Cid`]s. +#[derive( + // Builder, + Debug, +)] +// #[builder(pattern = "owned")] +pub struct CidGenerator { + pub version: Version, + pub mc_code: u64, + // #[builder(field(type = "u64", build = "self.multihasher.try_into()?"))] + pub(crate) multihasher: Multihasher, +} + +// impl From + +impl CidGenerator { + /// #[inline] - fn finalize(&mut self) -> &[u8] { - self.hasher.finalize() + pub const fn new(version: Version, multicodec_code: u64, multihasher: Multihasher) -> Self { + Self { + version, + mc_code: multicodec_code, + multihasher, + } } + + // pub const fn with_multihasher(self, multihasher: Multihasher) -> Self { + // self.multihasher = multihasher; + // self + // } + + /// #[inline] - fn reset(&mut self) { - self.hasher.reset() + pub fn try_finalize(&mut self) -> Result { + let inner = DefaultCid::new(self.version, self.mc_code, self.multihasher.try_finalize()?)?; + Ok(Cid::from(inner)) } } -impl std::io::Write for CidGenerator { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.hasher.write(buf) +impl io::Write for CidGenerator { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.multihasher.update(buf); + Ok(buf.len()) } - fn flush(&mut self) -> std::io::Result<()> { + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[cfg(feature = "dep:rkyv")] +mod rkyv {} + #[cfg(test)] mod tests { use super::*; diff --git a/src/codecs/dag_cbor.rs b/src/codecs/dag_cbor.rs index 52af964..21ae62d 100644 --- a/src/codecs/dag_cbor.rs +++ b/src/codecs/dag_cbor.rs @@ -16,12 +16,9 @@ use serde_cbor::{ // }, // serde::{Deserializer as CborDeserializer, Serializer as CborSerializer}, // }; -use delegate::delegate; use maybestd::{ - borrow::Cow, convert::TryFrom, - fmt, - io::{BufReader, Read, Write}, + io::{Read, Write}, }; /// The [DagCBOR](https://github.com/ipld/specs/blob/master/block-layer/codecs/dag-cbor.md) codec, that delegates to `serde_cbor`. @@ -51,13 +48,13 @@ impl DagCbor { /// /// TODO: #[inline] - pub(crate) fn deserialize_any<'de, D, V>( + pub(crate) fn deserialize_any<'de, const MC: u64, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: LinkVisitor<'de>, + V: LinkVisitor<'de, MC>, { // deserializer.deserialize_any(DagCborVisitor::<'a', _>(visitor)) unimplemented!() @@ -65,13 +62,13 @@ impl DagCbor { /// #[inline] - pub(crate) fn deserialize_link<'de, D, V>( + pub(crate) fn deserialize_link<'de, const MC: u64, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: LinkVisitor<'de>, + V: LinkVisitor<'de, MC>, { match Tagged::<&'de [u8]>::deserialize(deserializer)? { Tagged { @@ -97,7 +94,7 @@ impl DagCbor { R: Read, { let mut de = CborDeserializer::from_reader(reader); - T::__select_de::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) + T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) } // pub(crate) fn deserializer_from_reader( @@ -118,7 +115,7 @@ impl DagCbor { // { // let mut de = CborDeserializer::from_reader(reader); // // let mut de = CborDeserializer::new(IoReader::new(BufReader::new(reader))); - // seed.deserialize::<{ Self::CODE }, _>(&mut de) + // seed.deserialize::<{ ::CODE }, _>(&mut de) // .map_err(Error::decoder) // } @@ -126,52 +123,48 @@ impl DagCbor { // &mut self, // seed: T, // reader: R, - // ) -> Result< as DeserializeSeed<'de>>::Value, Error> + // ) -> Result<::CODE }, D, T> as DeserializeSeed<'de>>::Value, Error> // where // // S: CodecDeserializeSeed<'de>, - // CodecSeed<{ Self::CODE }, D, T>: DeserializeSeed<'de>, + // CodecSeed<{ ::CODE }, D, T>: DeserializeSeed<'de>, // R: Read, // { // let mut de = CborDeserializer::from_reader(reader); - // // seed.deserialize::<{ Self::CODE }, _>(&mut de) + // // seed.deserialize::<{ ::CODE }, _>(&mut de) // // .map_err(Error::decoder) - // CodecSeed::<{ Self::CODE }, D, T>(seed) + // CodecSeed::<{ ::CODE }, D, T>(seed) // .deserialize(&mut de) // .map_err(Error::decoder) // } } -impl Codec for DagCbor { +impl Codec for DagCbor { const NAME: &'static str = "dag-cbor"; const CODE: u64 = 0x71; - fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> + fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> where - T: Representation, W: Write, { let mut ser = CborSerializer::new(IoWrite::new(writer)); // let mut ser = CborSerializer::new(IoWriter::new(writer)); - Representation::serialize::<{ Self::CODE }, _>(dag, &mut ser).map_err(Error::encoder) + Representation::serialize::<{ ::CODE }, _>(dag, &mut ser) + .map_err(Error::encoder) } - fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result - where - T: Representation, - { + fn decode<'de>(&mut self, bytes: &'de [u8]) -> Result { let mut de = CborDeserializer::new(SliceRead::new(bytes)); // let mut de = CborDeserializer::new(SliceReader::new(bytes)); - Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) + Representation::deserialize::<{ ::CODE }, _>(&mut de).map_err(Error::decoder) } - fn read(&mut self, reader: R) -> Result + fn read(&mut self, reader: R) -> Result where - T: Representation, R: Read, { let mut de = CborDeserializer::new(IoRead::new(reader)); // let mut de = CborDeserializer::new(IoReader::new(BufReader::new(reader))); - Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) + Representation::deserialize::<{ ::CODE }, _>(&mut de).map_err(Error::decoder) } } @@ -179,7 +172,7 @@ impl TryFrom for DagCbor { type Error = Error; fn try_from(code: u64) -> Result { match code { - Self::CODE => Ok(Self), + ::CODE => Ok(Self), _ => Err(Error::UnknownMulticodecCode(code)), } } @@ -313,13 +306,14 @@ mod tag { #[cfg(test)] mod tests { - use super::super::test_utils::*; - use crate::prelude::*; + use crate::{codecs_::test_utils::*, *}; + + const C: u64 = ::CODE; #[test] fn test_null() { // let tests = &[(Null, "null")]; - // roundtrip_bytes_codec::(DagJson::CODE, tests); + // roundtrip_bytes_codec::(tests); } #[test] @@ -345,16 +339,16 @@ mod tests { // assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); // floats - let cases = &[(4000.5f32, b"\xfb\x40\xaf\x41\x00\x00\x00\x00\x00".as_ref())]; - roundtrip_bytes_codec::(DagCbor::CODE, cases); - let cases = &[(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a".as_ref())]; - roundtrip_bytes_codec::(DagCbor::CODE, cases); + let cases = &[(4000.5, b"\xfb\x40\xaf\x41\x00\x00\x00\x00\x00".as_ref())]; + roundtrip_bytes_codec::(cases); + let cases = &[(12.3, b"\xfb@(\x99\x99\x99\x99\x99\x9a".as_ref())]; + roundtrip_bytes_codec::(cases); } #[test] fn test_string() { - let cases = &[(IpldString::from("foobar"), b"ffoobar".as_ref())]; - roundtrip_bytes_codec::(DagCbor::CODE, cases); + let cases = &[(String::from("foobar"), b"ffoobar".as_ref())]; + roundtrip_bytes_codec::(cases); } #[test] @@ -366,7 +360,7 @@ mod tests { #[test] fn test_seq() { let cases = &[(vec![1, 2, 3], b"\x83\x01\x02\x03".as_ref())]; - roundtrip_bytes_codec::>(DagCbor::CODE, cases) + roundtrip_bytes_codec::>(cases) } #[test] diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index 29d99ff..fbc4583 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -62,40 +62,43 @@ impl DagJson { /// Deserialize any IPLD data type, mapping any encountered Serde type to the /// appropriate `Visitor` or `IpldVisitorExt` method. #[inline] - pub(crate) fn deserialize_any<'de, D, V>( + pub(crate) fn deserialize_any<'de, const MC: u64, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: LinkVisitor<'de>, + V: LinkVisitor<'de, MC>, { + debug_assert!(MC == ::CODE); deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } /// #[inline] - pub(crate) fn deserialize_bytes<'de, D, V>( + pub(crate) fn deserialize_bytes<'de, const MC: u64, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: LinkVisitor<'de>, + V: LinkVisitor<'de, MC>, { + debug_assert!(MC == ::CODE); deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } /// #[inline] - pub(crate) fn deserialize_link<'de, D, V>( + pub(crate) fn deserialize_link<'de, const MC: u64, D, V>( deserializer: D, visitor: V, ) -> Result where D: Deserializer<'de>, - V: LinkVisitor<'de>, + V: LinkVisitor<'de, MC>, { + debug_assert!(MC == ::CODE); deserializer.deserialize_any(visitor::DagJsonVisitor(visitor)) } @@ -108,38 +111,34 @@ impl DagJson { R: Read, { let mut de = JsonDeserializer::from_reader(reader); - T::__select_de::<{ Self::CODE }, _>(seed, &mut de).map_err(Error::decoder) + T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) } } -impl Codec for DagJson { +impl Codec for DagJson { const NAME: &'static str = "dag-json"; const CODE: u64 = 0x0129; - fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> + fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> where - T: Representation, W: Write, { let mut ser = JsonSerializer::new(writer); - Representation::serialize::<{ Self::CODE }, _>(dag, &mut ser).map_err(Error::encoder) + Representation::serialize::<{ ::CODE }, _>(dag, &mut ser) + .map_err(Error::encoder) } - fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result - where - T: Representation, - { + fn decode<'de>(&mut self, bytes: &'de [u8]) -> Result { let mut de = JsonDeserializer::from_slice(bytes); - Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) + Representation::deserialize::<{ ::CODE }, _>(&mut de).map_err(Error::decoder) } - fn read(&mut self, reader: R) -> Result + fn read(&mut self, reader: R) -> Result where - T: Representation, R: Read, { let mut de = JsonDeserializer::from_reader(reader); - Representation::deserialize::<{ Self::CODE }, _>(&mut de).map_err(Error::decoder) + Representation::deserialize::<{ ::CODE }, _>(&mut de).map_err(Error::decoder) } } @@ -147,7 +146,7 @@ impl TryFrom for DagJson { type Error = Error; fn try_from(code: u64) -> Result { match code { - Self::CODE => Ok(Self), + ::CODE => Ok(Self), _ => Err(Error::UnknownMulticodecCode(code)), } } @@ -157,16 +156,52 @@ mod visitor { use super::*; #[derive(Debug)] - pub(crate) struct DagJsonVisitor(pub(crate) V); + pub(crate) struct DagJsonVisitor(pub(crate) V); // visitor for any - impl<'de, V: LinkVisitor<'de>> Visitor<'de> for DagJsonVisitor { + impl<'de, const MC: u64, V> Visitor<'de> for DagJsonVisitor + where + // V: LinkVisitor<'de, { ::CODE }>, + V: LinkVisitor<'de, MC>, + { type Value = V::Value; #[inline] fn visit_map(self, mut map: A) -> Result where A: de::MapAccess<'de>, { + /// Wraps a `MapAccess` thats had it's first key removed. + struct MapAccessor<'a, A> { + first_key: Option>, + map: A, + } + + impl<'de, A: de::MapAccess<'de>> de::MapAccess<'de> for MapAccessor<'de, A> { + type Error = A::Error; + + #[inline] + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + use de::IntoDeserializer; + + if let Some(first_key) = self.first_key.take() { + seed.deserialize(first_key.into_deserializer()).map(Some) + } else { + self.map.next_key_seed(seed) + } + } + + delegate! { + to self.map { + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>; + } + } + } + let first_key: Option> = map.next_key()?; if Some(DagJson::IPLD_KEY) == first_key.as_deref() { match map.next_value::>()? { @@ -258,6 +293,8 @@ mod visitor { Ok(MapLikeVisitor::CidStr(s)) } + /// In the dag-json codec, CIDs are represented as + /// [`multibase`]()-encoded strings. #[inline] fn visit_str(self, s: &str) -> Result where @@ -276,7 +313,7 @@ mod visitor { /// In the dag-json codec, bytes are represented as maps, with the key /// always being the string "bytes" and the value always being the bytes - /// multibase-encoded as a string. + /// [`multibase`]()-encoded-encoded as a string. #[inline] fn visit_map(self, mut map: A) -> Result where @@ -303,63 +340,32 @@ mod visitor { } } } - - /// Wraps a `MapAccess` thats had it's first key removed. - struct MapAccessor<'a, A> { - first_key: Option>, - map: A, - } - - impl<'de, A: de::MapAccess<'de>> de::MapAccess<'de> for MapAccessor<'de, A> { - type Error = A::Error; - - #[inline] - fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> - where - K: de::DeserializeSeed<'de>, - { - use de::IntoDeserializer; - - if let Some(first_key) = self.first_key.take() { - seed.deserialize(first_key.into_deserializer()).map(Some) - } else { - self.map.next_key_seed(seed) - } - } - - delegate! { - to self.map { - fn next_value_seed(&mut self, seed: V) -> Result - where - V: de::DeserializeSeed<'de>; - } - } - } } #[cfg(test)] mod tests { - use super::super::test_utils::*; - use crate::prelude::*; + use crate::{codecs_::test_utils::*, *}; + + const C: u64 = ::CODE; #[test] fn test_null() { let cases = &[(Null, "null")]; - roundtrip_str_codec::(DagJson::CODE, cases); - let cases = &[(None as Option, "null")]; - roundtrip_str_codec::>(DagJson::CODE, cases); + roundtrip_str_codec::(cases); + let cases = &[(None, "null")]; + roundtrip_str_codec::>(cases); - let cases = &[(Any::Null(Null), "null")]; - roundtrip_str_codec::(DagJson::CODE, cases); + let cases = &[(Null.into(), "null")]; + roundtrip_str_codec::(cases); } #[test] fn test_bool() { let cases = &[(true, "true"), (false, "false")]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); - let cases = &[(Any::Bool(true), "true"), (Any::Bool(false), "false")]; - roundtrip_str_codec::(DagJson::CODE, cases); + let cases = &[(true.into(), "true"), (false.into(), "false")]; + roundtrip_str_codec::(cases); } #[test] @@ -370,44 +376,41 @@ mod tests { (65535, "65535"), (i64::MAX, &i64::MAX.to_string()), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); // floats let cases = &[(123.123, "123.123")]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); // any let cases = &[ - (Any::Int(123), "123"), - (Any::Int(65535), "65535"), - (Any::Int(Int::MAX), &Int::MAX.to_string()), - (Any::Float(123.123), "123.123"), + (123.into(), "123"), + (65535.into(), "65535"), + (Int::MAX.into(), &Int::MAX.to_string()), + (123.123.into(), "123.123"), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } #[test] fn test_string() { let cases = &[ // standard string - (IpldString::from("hello world"), "\"hello world\""), - (IpldString::default(), "\"\""), + (String::from("hello world"), "\"hello world\""), + (String::default(), "\"\""), // non-standard UTF-8 string TODO: - // (IpldString::from("ÅΩ"), "\"ÅΩ\""), + // (String::from("ÅΩ"), "\"ÅΩ\""), ]; - roundtrip_str_codec::<_>(DagJson::CODE, cases); + roundtrip_str_codec::(cases); let cases = &[ // standard string - ( - Any::String(IpldString::from("hello world")), - "\"hello world\"", - ), - (Any::String(IpldString::default()), "\"\""), + (String::from("hello world").into(), "\"hello world\""), + (String::default().into(), "\"\""), // non-standard UTF-8 string TODO: - // (Any::String(IpldString::from("ÅΩ")), "\"ÅΩ\""), + // (String::from("ÅΩ").into(), "\"ÅΩ\""), ]; - roundtrip_str_codec::<_>(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } #[test] @@ -420,42 +423,39 @@ mod tests { // TODO: empty bytes // (Bytes::from(&[]), r#"{"/":{"bytes":"m"}}"#), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); let cases = &[ ( - Any::Bytes(Bytes::from([1u8, 2, 3].as_ref())), + Bytes::from([1u8, 2, 3].as_ref()).into(), r#"{"/":{"bytes":"mAQID"}}"#, ), // TODO: empty bytes // (Bytes::from(&[]), r#"{"/":{"bytes":"m"}}"#), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } #[test] fn test_list() { // raw types let cases = &[(vec![], "[]"), (vec![1, 2], "[1,2]")]; - roundtrip_str_codec::>(DagJson::CODE, cases); + roundtrip_str_codec::>(cases); // any types let cases = &[ - (Any::List(vec![]), "[]"), - (Any::List(vec![Any::Int(1), Any::Int(2)]), "[1,2]"), + (vec![].into(), "[]"), + (vec![1.into(), 2.into()].into(), "[1,2]"), // ( // vec![Any::Link(Link::Cid(Default::default()).into())], // "[{\"/\": }]", // ), ( - Any::List(vec![ - Any::List(vec![]), - Any::List(vec![Any::Int(1), Any::Float(123.123)]), - ]), + vec![vec![].into(), vec![Any::Int(1), Any::Float(123.123)].into()].into(), "[[],[1,123.123]]", ), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } #[test] @@ -465,14 +465,14 @@ mod tests { (Default::default(), "{}"), ( { - let mut map: Map = Default::default(); + let mut map: Map = Default::default(); map.insert("abc".into(), 123i64); map }, "{\"abc\":123}", ), ]; - roundtrip_str_codec::>(DagJson::CODE, cases); + roundtrip_str_codec::>(cases); // any types let cases = &[ @@ -481,12 +481,12 @@ mod tests { { let mut map: Map = Default::default(); map.insert("abc".into(), Any::Int(123)); - Any::Map(map) + map.into() }, "{\"abc\":123}", ), ]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } #[test] @@ -498,13 +498,13 @@ mod tests { Link::from(Cid::try_from(s.as_str()).unwrap()), json.as_str(), )]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); // any let cases = &[( Any::Link(Link::from(Cid::try_from(s.as_str()).unwrap()).into()), json.as_str(), )]; - roundtrip_str_codec::(DagJson::CODE, cases); + roundtrip_str_codec::(cases); } } diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index 6168882..696db8f 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -1,14 +1,75 @@ //! IPLD codec interfaces. #[cfg(feature = "dag-cbor")] -pub mod dag_cbor; +mod dag_cbor; #[cfg(feature = "dag-json")] -pub mod dag_json; +mod dag_json; +// #[cfg(feature = "dag-rkyv")] +// pub mod dag_rkyv; // #[cfg(feature = "dag-pb")] // pub mod dag_pb; +// #[cfg(feature = "dag-jose")] +// pub mod dag_jose; +// #[cfg(feature = "raw")] +// pub mod raw; +// #[cfg(feature = "json")] +// pub mod json; + +#[cfg(feature = "dag-cbor")] +pub use dag_cbor::DagCbor; +#[cfg(feature = "dag-json")] +pub use dag_json::DagJson; use crate::dev::*; -use maybestd::convert::TryFrom; +use maybestd::{ + convert::TryFrom, + fmt, + io::{Read, Write}, +}; + +/// [Multicodec]() code for the identity codec. +/// +/// In this library, this codec is used to convert the type into its +/// (de)serializable representation (sans encoding) so that it can be +/// re-represented (aka converted) to another type, or reified for selection by +/// another type. +pub const IDENTITY: u64 = 0x00; + +/* +/// +/// keeps multiple counters and flags +/// - is_ignoring: reads 1 byte?, incremenets ignored bytes and start_idx +/// - is reading: +/// - +enum State { + Default, + Ignoring { start_idx: usize }, + Reading { start_idx: usize }, +} + +pub struct TranscoderCursor { + _t: PhantomData<(R, W)>, +} + +/// +/// impls Deserializer: +/// - on ignore: +/// - set reader to ignore mode +/// - call inner deserializer +/// - flush +/// - calls to types do the op, serializer to writer, tell reader to skip # written bytes +/// - calls to ignore end by telling reader to flush buffer to writer +/// FIXME: cant always tell which bytes were used +pub struct Transcoder<'a, D, S> { + _t: PhantomData<(D, S)>, +} + +impl<'de, D: Deserializer<'de>, S: Serializer> Transcoder { + fn from_rw(reader: R, writer: W) -> Self { + Self { _t: PhantomData } + } +} + */ // // pub trait Transcoder<'de> { @@ -19,54 +80,95 @@ use maybestd::convert::TryFrom; // fn deserializer(&mut self) -> &mut Self::Deserializer; // } +/// An unified trait for all IPLD +/// [Codec](https://github.com/ipld/specs/blob/master/block-layer/codecs/README.dsmd)s, +/// providing methods for reading and writing blocks. +pub trait Codec: TryFrom { + /// The standardized [`Multicodec`] name for this IPLD codec. + const NAME: &'static str; + + /// The standardized [`Multicodec`] code that identifies this IPLD codec. + const CODE: u64; + + /// Given a dag, serialize it to a `Vec`. + fn encode(&mut self, dag: &T) -> Result, Error> { + let mut vec = vec![]; + self.write(dag, &mut vec)?; + Ok(vec) + } + + /// Given a dag and a `Write`, encode it to the writer. + fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> + where + W: Write; + + /// Given some bytes, deserialize a dag. + fn decode<'de>(&mut self, bytes: &'de [u8]) -> Result { + self.read::<_>(bytes) + } + + /// Given a `Read`, deserialize a dag. + fn read(&mut self, reader: R) -> Result + where + R: Read; +} + /// An extension to the [`serde::de::Visitor`] trait for visiting /// [`Representation`]s that contain IPLD links. /// /// [`Representation`]: crate::prelude::Representation -pub trait LinkVisitor<'de>: Visitor<'de> { +pub trait LinkVisitor<'de, const MC: u64 = IDENTITY>: Visitor<'de> { + // /// The value produced by this visitor. + // type Value; + + // /// Format a message stating what data this Visitor expects to receive. + // fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; + /// The input contains the string of a [`Cid`]. /// /// The default implementation fails with a type error. - fn visit_link_str(self, cid_str: &str) -> Result + fn visit_link_str(self, s: &str) -> Result where E: serde::de::Error, { - let cid = Cid::try_from(cid_str).map_err(E::custom)?; - self.visit_cid(cid) + // let cid = Cid::try_from(s).map_err(E::custom)?; + // self.visit_cid(cid) + todo!() } /// The input contains the string of a [`Cid`]. /// - /// The default implementation delegates to [`visit_link_str`]. + /// The default implementation delegates to [`LinkVisitor::visit_link_str`]. #[inline] - fn visit_link_borrowed_str(self, cid_str: &'de str) -> Result + fn visit_link_borrowed_str(self, s: &'de str) -> Result where E: serde::de::Error, { - self.visit_link_str(cid_str) + self.visit_link_str(s) } /// The input contains a string representation of a [`Cid`]. /// /// The default implementation fails with a type error. #[inline] - fn visit_link_bytes(self, cid_bytes: &[u8]) -> Result + fn visit_link_bytes(self, b: &[u8]) -> Result where E: serde::de::Error, { - let cid = Cid::try_from(cid_bytes).map_err(E::custom)?; - self.visit_cid(cid) + // let cid = Cid::try_from(b).map_err(E::custom)?; + // self.visit_cid(cid) + todo!() } /// The input contains a string representation of a [`Cid`]. /// - /// The default implementation delegates to [`visit_link_bytes`]. + /// The default implementation delegates to [`LinkVisitor::visit_link_bytes`]. #[inline] - fn visit_link_borrowed_bytes(self, cid_bytes: &'de [u8]) -> Result + fn visit_link_borrowed_bytes(self, b: &'de [u8]) -> Result where E: serde::de::Error, { - self.visit_link_bytes(cid_bytes) + self.visit_link_bytes(b) } /// The input contains an already parsed [`Cid`]. @@ -76,18 +178,359 @@ pub trait LinkVisitor<'de>: Visitor<'de> { { Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) } + + //////////////////////////////////////////////////////////////////////// + // Visitor API from serde + //////////////////////////////////////////////////////////////////////// + + /* + /// See [`Visitor::visit_bool`]. + /// + /// [`Visitor::visit_bool`]: serde::Visitor::visit_bool + #[inline] + fn visit_bool(self, v: bool) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_bool(self, v) + } + /// See [`Visitor::visit_i8`]. + /// + /// [`Visitor::visit_i8`]: serde::Visitor::visit_i8 + #[inline] + fn visit_i8(self, v: i8) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_i64(v as i64) + } + /// See [`Visitor::visit_i16`]. + /// + /// [`Visitor::visit_i16`]: serde::Visitor::visit_i16 + #[inline] + fn visit_i16(self, v: i16) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_i64(v as i64) + } + /// See [`Visitor::visit_i32`]. + /// + /// [`Visitor::visit_i32`]: serde::Visitor::visit_i32 + #[inline] + fn visit_i32(self, v: i32) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_i64(v as i64) + } + /// See [`Visitor::visit_i64`]. + /// + /// [`Visitor::visit_i64`]: serde::Visitor::visit_i64 + #[inline] + fn visit_i64(self, v: i64) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_i64(self, v) + } + serde::serde_if_integer128! { + /// See [`Visitor::visit_i128`]. + /// + /// [`Visitor::visit_i128`]: serde::Visitor::visit_i128 + #[inline] + fn visit_i128(self, v: i128) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_i128(self, v) + } + } + /// See [`Visitor::visit_u8`]. + /// + /// [`Visitor::visit_u8`]: serde::Visitor::visit_u8 + #[inline] + fn visit_u8(self, v: u8) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_u64(v as u64) + } + /// See [`Visitor::visit_u16`]. + /// + /// [`Visitor::visit_u16`]: serde::Visitor::visit_u16 + #[inline] + fn visit_u16(self, v: u16) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_u64(v as u64) + } + /// See [`Visitor::visit_u32`]. + /// + /// [`Visitor::visit_u32`]: serde::Visitor::visit_u32 + #[inline] + fn visit_u32(self, v: u32) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_u64(v as u64) + } + /// See [`Visitor::visit_u64`]. + /// + /// [`Visitor::visit_u64`]: serde::Visitor::visit_u64 + #[inline] + fn visit_u64(self, v: u64) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_u64(self, v) + } + serde::serde_if_integer128! { + /// See [`Visitor::visit_u128`]. + /// + /// [`Visitor::visit_u128`]: serde::Visitor::visit_u128 + #[inline] + fn visit_u128(self, v: u128) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_u128(self, v) + } + } + /// See [`Visitor::visit_f32`]. + /// + /// [`Visitor::visit_f32`]: serde::Visitor::visit_f32 + #[inline] + fn visit_f32(self, v: f32) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_f64(v as f64) + } + /// See [`Visitor::visit_f64`]. + /// + /// [`Visitor::visit_f64`]: serde::Visitor::visit_f64 + #[inline] + fn visit_f64(self, v: f64) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_f64(self, v) + } + /// See [`Visitor::visit_char`]. + /// + /// [`Visitor::visit_char`]: serde::Visitor::visit_char + #[inline] + fn visit_char(self, v: char) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_char(self, v) + } + /// See [`Visitor::visit_str`]. + /// + /// [`Visitor::visit_str`]: serde::Visitor::visit_str + #[inline] + fn visit_str(self, v: &str) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_str(self, v) + } + /// See [`Visitor::visit_borrowed_str`]. + /// + /// [`Visitor::visit_borrowed_str`]: serde::Visitor::visit_borrowed_str + #[inline] + fn visit_borrowed_str(self, v: &'de str) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_str(v) + } + /// See [`Visitor::visit_string`]. + /// + /// [`Visitor::visit_string`]: serde::Visitor::visit_string + #[inline] + #[cfg(any(feature = "std", feature = "alloc"))] + fn visit_string(self, v: String) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_str(&v) + } + /// See [`Visitor::visit_bytes`]. + /// + /// [`Visitor::visit_bytes`]: serde::Visitor::visit_bytes + #[inline] + fn visit_bytes(self, v: &[u8]) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_bytes(self, v) + } + /// See [`Visitor::visit_borrowed_bytes`]. + /// + /// [`Visitor::visit_borrowed_bytes`]: serde::Visitor::visit_borrowed_bytes + #[inline] + fn visit_borrowed_bytes( + self, + v: &'de [u8], + ) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_bytes(v) + } + /// See [`Visitor::visit_byte_buf`]. + /// + /// [`Visitor::visit_byte_buf`]: serde::Visitor::visit_byte_buf + #[inline] + #[cfg(any(feature = "std", feature = "alloc"))] + fn visit_byte_buf(self, v: Vec) -> Result<>::Value, E> + where + E: de::Error, + { + self.visit_bytes(&v) + } + /// See [`Visitor::visit_none`]. + /// + /// [`Visitor::visit_none`]: serde::Visitor::visit_none + #[inline] + fn visit_none(self) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_none(self) + } + /// See [`Visitor::visit_some`]. + /// + /// [`Visitor::visit_some`]: serde::Visitor::visit_some + #[inline] + fn visit_some( + self, + deserializer: D, + ) -> Result<>::Value, D::Error> + where + D: Deserializer<'de>, + { + >::visit_some(self, deserializer) + } + /// See [`Visitor::visit_unit`]. + /// + /// [`Visitor::visit_unit`]: serde::Visitor::visit_unit + #[inline] + fn visit_unit(self) -> Result<>::Value, E> + where + E: de::Error, + { + >::visit_unit(self) + } + /// See [`Visitor::visit_newtype_struct`]. + /// + /// [`Visitor::visit_newtype_struct`]: serde::Visitor::visit_newtype_struct + #[inline] + fn visit_newtype_struct( + self, + deserializer: D, + ) -> Result<>::Value, D::Error> + where + D: Deserializer<'de>, + { + >::visit_newtype_struct(self, deserializer) + } + /// See [`Visitor::visit_seq`]. + /// + /// [`Visitor::visit_seq`]: serde::Visitor::visit_seq + #[inline] + fn visit_seq(self, seq: A) -> Result<>::Value, A::Error> + where + A: SeqAccess<'de>, + { + >::visit_seq(self, seq) + } + /// See [`Visitor::visit_map`]. + /// + /// [`Visitor::visit_map`]: serde::Visitor::visit_map + #[inline] + fn visit_map(self, map: A) -> Result<>::Value, A::Error> + where + A: MapAccess<'de>, + { + >::visit_map(self, map) + } + /// See [`Visitor::visit_enum`]. + /// + /// [`Visitor::visit_enum`]: serde::Visitor::visit_enum + #[inline] + fn visit_enum(self, data: A) -> Result<>::Value, A::Error> + where + A: EnumAccess<'de>, + { + >::visit_enum(self, data) + } + #[doc(hidden)] + fn __private_visit_untagged_option( + self, + deserializer: D, + ) -> Result<>::Value, ()> + where + D: Deserializer<'de>, + { + >::__private_visit_untagged_option(self, deserializer) + } + */ } +// pub struct MulticodecVisitor(V); +// impl> Visitor<'de> for MulticodecVisitor { +// type Value = V::Value; + +// delegate! { +// to self.0 { +// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; +// fn visit_bool(self, v: bool) -> Result<>::Value, E>; +// fn visit_i8(self, v: i8) -> Result; +// fn visit_i16(self, v: i16) -> Result; +// fn visit_i32(self, v: i32) -> Result; +// fn visit_i64(self, v: i64) -> Result; +// fn visit_i128(self, v: i128) -> Result; +// fn visit_u8(self, v: u8) -> Result; +// fn visit_u16(self, v: u16) -> Result; +// fn visit_u32(self, v: u32) -> Result; +// fn visit_u64(self, v: u64) -> Result; +// fn visit_u128(self, v: u128) -> Result; +// fn visit_f32(self, v: f32) -> Result; +// fn visit_f64(self, v: f64) -> Result; +// fn visit_char(self, v: char) -> Result; +// fn visit_str(self, v: &str) -> Result; +// fn visit_borrowed_str(self, v: &'de str) -> Result; +// fn visit_string(self, v: String) -> Result; +// fn visit_bytes(self, v: &[u8]) -> Result; +// fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result; +// fn visit_byte_buf(self, v: Vec) -> Result; +// fn visit_none(self) -> Result; +// fn visit_some>(self, deserializer: D) -> Result; +// fn visit_unit(self) -> Result; +// fn visit_newtype_struct>( +// self, +// deserializer: D +// ) -> Result; +// fn visit_seq>(self, seq: A) -> Result; +// fn visit_enum>(self, data: A) -> Result; +// } +// } +// } + pub(crate) mod test_utils { use crate::dev::*; + use maybestd::{convert::TryFrom, fmt::Debug}; - use std::{convert::TryFrom, fmt::Debug, io::Read, string::ToString}; - - pub fn roundtrip_bytes_codec<'de, T>(code: u64, cases: &[(T, &'de [u8])]) + pub fn roundtrip_bytes_codec<'de, const C: u64, T>(cases: &[(T, &'de [u8])]) where T: PartialEq + Debug + Representation, { - let mut codec = Multicodec::try_from(code).expect("should find codec"); + let mut codec = Multicodec::try_from(C).expect("should find codec"); for (ref dag, expected) in cases { // writing @@ -117,11 +560,11 @@ pub(crate) mod test_utils { } } - pub fn roundtrip_str_codec<'de, T>(code: u64, cases: &[(T, &'de str)]) + pub fn roundtrip_str_codec<'de, const C: u64, T>(cases: &[(T, &'de str)]) where T: PartialEq + Debug + Representation, { - let mut codec = Multicodec::try_from(code).expect("should find codec"); + let mut codec = Multicodec::try_from(C).expect("should find codec"); for (ref dag, expected) in cases { // writing diff --git a/src/compat/core.rs b/src/compat/core.rs index 61bdf1c..bb2b8b8 100644 --- a/src/compat/core.rs +++ b/src/compat/core.rs @@ -1,21 +1,29 @@ +//! +//! todo: +//! duration, systemtime, paths, atomics, nonzero +//! (ip/socket)addrs, (c/os)str + use crate::dev::*; -use macros::repr_serde; -use maybestd::{fmt, marker::PhantomData}; +use macros::{ + derive_more::{From, Into}, + repr_serde, +}; +use maybestd::{fmt, marker::PhantomData, num::Wrapping, rc::Rc, sync::Arc}; mod ignored { use super::*; impl Representation for IgnoredAny { - type DataModelKind = type_kinds::Null; - type SchemaKind = type_kinds::Union; - type ReprKind = type_kinds::Any; - const NAME: &'static str = "IgnoredAny"; const SCHEMA: &'static str = "type IgnoredAny = Any"; const DATA_MODEL_KIND: Kind = Kind::Null; const SCHEMA_KIND: Kind = Kind::Union; const REPR_KIND: Kind = Kind::Any; - const __IGNORED: bool = true; + const REPR_STRATEGY: Strategy = Strategy::Ignored; + + fn to_selected_node(&self) -> SelectedNode { + unreachable!() + } #[doc(hidden)] fn serialize(&self, _: S) -> Result @@ -34,95 +42,153 @@ mod ignored { } } - repr_serde! { @select_for IgnoredAny } - repr_serde! { @visitors for IgnoredAny => IgnoredAny - { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } - {} {} @serde { - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", IgnoredAny::NAME) - } - #[inline] - fn visit_unit(self) -> Result - where - E: de::Error, - { - Ok(()) - } + repr_serde! { @select for IgnoredAny } + repr_serde! { @visitors for IgnoredAny { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", IgnoredAny::NAME) } - } - - /// - pub type Ignored = PhantomData; - - impl Representation for Ignored { - type DataModelKind = type_kinds::Null; - type SchemaKind = type_kinds::Union; - type ReprKind = type_kinds::Any; + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(()) + } + }} - const NAME: &'static str = "Ignored"; - const SCHEMA: &'static str = "type Ignored = IgnoredAny"; + impl Representation for PhantomData { + const NAME: &'static str = "Phantom"; + const SCHEMA: &'static str = "type Phantom = Any"; const DATA_MODEL_KIND: Kind = Kind::Null; const SCHEMA_KIND: Kind = Kind::Union; const REPR_KIND: Kind = Kind::Any; - const __IGNORED: bool = true; + const REPR_STRATEGY: Strategy = Strategy::Ignored; + + fn to_selected_node(&self) -> SelectedNode { + unreachable!() + } #[doc(hidden)] fn serialize(&self, _: S) -> Result where S: Serializer, { - Err(S::Error::custom("unimplemented")) + // FIXME: call noop somehow + unimplemented!() } #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const C: u64, D>(_: D) -> Result where D: Deserializer<'de>, { - Err(D::Error::custom("unimplemented")) + Ok(PhantomData) } } - repr_serde! { @select_for Ignored => Ignored - { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } - { T } { T: Representation } - } - repr_serde! { @visitors for Ignored => Ignored - { @dk (type_kinds::Null) @sk (type_kinds::Union) @rk (type_kinds::Any) } - { T } { T: Representation + '_a } @serde { + repr_serde! { @select for PhantomData { T } { T: Representation }} + repr_serde! { @visitors for PhantomData { T } { T: Representation + '_a } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", T::NAME) } - // TODO: delegate } } } -// TODO: -mod option { +mod implicit { use super::*; - // ? define Optional and Nullable? + /// A type whose absence denotes the presence of the inner type's + /// [`Default`] value. + #[derive(Copy, Clone, Debug, Default, From)] + pub struct Implicit(T); - impl Representation for Option + impl Representation for Implicit where - T: Representation, + T: Default + Representation, { - type DataModelKind = T::DataModelKind; - type SchemaKind = T::SchemaKind; - type ReprKind = T::ReprKind; - // type ReprKind = type_kinds::Optional<::ReprKind>; - // type ReprKind = typenum::op!(type_kinds::Null | T::ReprKind); - // type ReprKind = typenum::Or; - - const NAME: &'static str = concat!("Optional", stringify!(T::NAME)); - const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); + const NAME: &'static str = "Implicit"; + const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " implicit"); const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; const SCHEMA_KIND: Kind = T::SCHEMA_KIND; const REPR_KIND: Kind = T::REPR_KIND; - const IS_LINK: bool = T::IS_LINK; + const REPR_STRATEGY: Strategy = T::REPR_STRATEGY; + const HAS_LINKS: bool = T::HAS_LINKS; + + fn as_field(&self) -> Option> { + self.0.as_field() + } + + fn to_selected_node(&self) -> SelectedNode { + self.0.to_selected_node() + } + + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + Representation::serialize::(&self.0, serializer) + } + + // TODO + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // struct OptionVisitor(PhantomData); + // impl<'de, const C: u64, T: Representation> Visitor<'de> for OptionVisitor { + // type Value = Option; + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "A nullable `{}`", T::NAME) + // } + // #[inline] + // fn visit_unit(self) -> Result { + // Ok(None) + // } + // #[inline] + // fn visit_none(self) -> Result { + // Ok(None) + // } + // #[inline] + // fn visit_some>( + // self, + // deserializer: D, + // ) -> Result { + // T::deserialize::(deserializer).map(Some) + // } + // fn __private_visit_untagged_option( + // self, + // deserializer: D, + // ) -> Result + // where + // D: Deserializer<'de>, + // { + // Ok(T::deserialize::(deserializer).ok()) + // } + // } + + // deserializer.deserialize_option(OptionVisitor::(PhantomData)) + + unimplemented!() + } + } +} + +// TODO: optional vs nullable? +mod option { + use super::*; + + impl Representation for Option { + const NAME: &'static str = "Nullable"; + const SCHEMA: &'static str = concat!("type ", stringify!(T::NAME), " nullable"); + const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND.union(Kind::Null); + const SCHEMA_KIND: Kind = T::SCHEMA_KIND.union(Kind::Null); + const REPR_KIND: Kind = T::REPR_KIND.union(Kind::Null); + const REPR_STRATEGY: Strategy = T::REPR_STRATEGY; const HAS_LINKS: bool = T::HAS_LINKS; fn name(&self) -> &'static str { @@ -132,13 +198,6 @@ mod option { } } - // fn kind(&self) -> Kind { - // match self { - // Self::None => Null::KIND, - // Self::Some(t) => t.kind(), - // } - // } - fn has_links(&self) -> bool { match self { Self::None => false, @@ -150,6 +209,13 @@ mod option { self.as_ref().and_then(Representation::as_field) } + fn to_selected_node(&self) -> SelectedNode { + match self { + Self::None => Null.to_selected_node(), + Self::Some(t) => t.to_selected_node(), + } + } + #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where @@ -169,8 +235,8 @@ mod option { struct OptionVisitor(PhantomData); impl<'de, const C: u64, T: Representation> Visitor<'de> for OptionVisitor { type Value = Option; - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("Optional") + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A nullable `{}`", T::NAME) } #[inline] fn visit_unit(self) -> Result { @@ -203,20 +269,70 @@ mod option { } } -mod wrapper { - use super::*; - use maybestd::{rc::Rc, sync::Arc}; - - macro_rules! impl_wrapper { - ($wrapper:ident) => { - impl Representation for $wrapper +macro_rules! derive { + ($self:ident @newtype_ref) => ($self.0); + (@newtype $wrapper:ident) => { derive!($wrapper $wrapper, @newtype_ref); }; + ($self:ident @from_ref) => ($self.as_ref()); + (@from $wrapper:ident) => { derive!($wrapper $wrapper::from, @from_ref); }; + ($wrapper:ident $constructor:expr, @$as_ref:ident) => { + impl Representation for $wrapper { + const NAME: &'static str = T::NAME; + const SCHEMA: &'static str = T::SCHEMA; + const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; + const SCHEMA_KIND: Kind = T::SCHEMA_KIND; + const REPR_KIND: Kind = T::REPR_KIND; + const REPR_STRATEGY: Strategy = T::REPR_STRATEGY; + const HAS_LINKS: bool = T::HAS_LINKS; + fn name(&self) -> &'static str { + derive!(self @$as_ref).name() + } + fn has_links(&self) -> bool { + derive!(self @$as_ref).has_links() + } + fn as_field(&self) -> Option> { + derive!(self @$as_ref).as_field() + } + fn to_selected_node(&self) -> SelectedNode { + derive!(self @$as_ref).to_selected_node() + } + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + derive!(self @$as_ref).serialize::(serializer) + } + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result where - T: Representation, + D: Deserializer<'de>, { - type DataModelKind = T::DataModelKind; - type SchemaKind = T::SchemaKind; - type ReprKind = T::ReprKind; + Ok($constructor(T::deserialize::<'de, C, _>(deserializer)?)) + } + } + impl Select for $wrapper + where + Ctx: Context, + T: Select + 'static, + { + #[doc(hidden)] + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + let seed = seed.wrap::($constructor); + T::__select_de::(seed, deserializer) + } + } + }; + /* + (@dyn $wrapper:ident) => { + impl Representation for $wrapper { const NAME: &'static str = T::NAME; const SCHEMA: &'static str = T::SCHEMA; const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; @@ -225,6 +341,7 @@ mod wrapper { const IS_LINK: bool = T::IS_LINK; const HAS_LINKS: bool = T::HAS_LINKS; + #[inline] fn name(&self) -> &'static str { self.as_ref().name() } @@ -245,16 +362,13 @@ mod wrapper { self.as_ref().has_links() } - fn as_field(&self) -> Option> { - self.as_ref().as_field() - } - #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { - self.as_ref().serialize::(serializer) + // self.as_ref().serialize::(serializer) + unimplemented!() } #[doc(hidden)] @@ -262,113 +376,15 @@ mod wrapper { where D: Deserializer<'de>, { - Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) - } - } - - impl Select for $wrapper - where - Ctx: Context, - T: Select + 'static, - { - // #[doc(hidden)] - // #[inline] - // fn __select<'a>(seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { - // T::__select(seed.wrap::($wrapper::from)) - // } - - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - T::__select_de::(seed.wrap::($wrapper::from), deserializer) - } - - #[doc(hidden)] - #[inline] - fn __select_seq<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - seq: A, - ) -> Result, A::Error> - where - A: SeqAccess<'de>, - { - T::__select_seq::(seed.wrap::($wrapper::from), seq) - } - - #[doc(hidden)] - #[inline] - fn __select_map<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - map: A, - is_key: bool, - ) -> Result, A::Error> - where - A: MapAccess<'de>, - { - T::__select_map::(seed.wrap::($wrapper::from), map, is_key) + // Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) + unimplemented!() } } - }; /* - (@dyn $wrapper:ident) => { - impl Representation for $wrapper { - const NAME: &'static str = T::NAME; - const SCHEMA: &'static str = T::SCHEMA; - const DATA_MODEL_KIND: Kind = T::DATA_MODEL_KIND; - const SCHEMA_KIND: Kind = T::SCHEMA_KIND; - const REPR_KIND: Kind = T::REPR_KIND; - const IS_LINK: bool = T::IS_LINK; - const HAS_LINKS: bool = T::HAS_LINKS; - - #[inline] - fn name(&self) -> &'static str { - self.as_ref().name() - } - - fn data_model_kind(&self) -> Kind { - self.as_ref().data_model_kind() - } - - fn schema_kind(&self) -> Kind { - self.as_ref().schema_kind() - } - - fn repr_kind(&self) -> Kind { - self.as_ref().repr_kind() - } - - fn has_links(&self) -> bool { - self.as_ref().has_links() - } - - #[doc(hidden)] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - // self.as_ref().serialize::(serializer) - unimplemented!() - } - - #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // Ok(Self::new(T::deserialize::<'de, C, _>(deserializer)?)) - unimplemented!() - } - } - }; - */ - } - - impl_wrapper!(Box); - impl_wrapper!(Rc); - impl_wrapper!(Arc); + }; + */ } + +derive!(@newtype Wrapping); +derive!(@from Box); +derive!(@from Rc); +derive!(@from Arc); diff --git a/src/compat/mod.rs b/src/compat/mod.rs index 9816037..3945061 100644 --- a/src/compat/mod.rs +++ b/src/compat/mod.rs @@ -1 +1,7 @@ mod core; +#[cfg(feature = "im")] +mod im; +#[cfg(feature = "libp2p")] +mod libp2p; +#[cfg(feature = "multiaddr")] +mod multiaddr; diff --git a/src/data_model/any.rs b/src/data_model/any.rs index 84d1a07..b2537cb 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -23,7 +23,7 @@ schema! { // TODO: impl from(forward) and try_into for all unions and enums pub type Any union { /// - #[from(ignore)] + // #[from(ignore)] | Null null /// | Bool bool @@ -48,138 +48,5 @@ schema! { // impl FromIterator for Any, (T: StringRepresentation, Any) -/* -/// TODO: convert these to a Node trait, that all types implement -impl Any { - /// LookupByString looks up a child object in this node and returns it. - /// The returned Node may be any of the Kind: - /// a primitive (string, int64, etc), a map, a list, or a link. - /// - /// If the Kind of this Node is not Kind_Map, a nil node and an error - /// will be returned. - /// - /// If the key does not exist, a nil node and an error will be returned. - pub fn lookup_by_string(&self, key: &str) -> Result<&Self, Error> { - // match self { - // Self::Map(inner) => unimplemented!(), - // _ => Err(Error::Value("Value must be a map")), - // } - unimplemented!() - } - - /// LookupByNode is the equivalent of LookupByString, but takes a reified Node - /// as a parameter instead of a plain string. - /// This mechanism is useful if working with typed maps (if the key types - /// have constraints, and you already have a reified `schema.TypedNode` value, - /// using that value can save parsing and validation costs); - /// and may simply be convenient if you already have a Node value in hand. - /// - /// (When writing generic functions over Node, a good rule of thumb is: - /// when handling a map, check for `schema.TypedNode`, and in this case prefer - /// the LookupByNode(Node) method; otherwise, favor LookupByString; typically - /// implementations will have their fastest paths thusly.) - pub fn lookup_by_node(&self, key: &T) -> Result<&Self, Error> { - unimplemented!() - } - - /// LookupByIndex is the equivalent of LookupByString but for indexing into a list. - /// As with LookupByString, the returned Node may be any of the Kind: - /// a primitive (string, int64, etc), a map, a list, or a link. - /// - /// If the Kind of this Node is not Kind_List, a nil node and an error - /// will be returned. - /// - /// If idx is out of range, a nil node and an error will be returned. - pub fn lookup_by_index(&self, idx: usize) -> Result<&Self, Error> { - unimplemented!() - } - - /// LookupBySegment is will act as either LookupByString or LookupByIndex, - /// whichever is contextually appropriate. - /// - /// Using LookupBySegment may imply an "atoi" conversion if used on a list node, - /// or an "itoa" conversion if used on a map node. If an "itoa" conversion - /// takes place, it may error, and this method may return that error. - pub fn lookup_by_segment(&self, seg: &Path) -> Result<&Self, Error> { - unimplemented!() - } - - // /// MapIterator returns an iterator which yields key-value pairs - // /// traversing the node. - // /// If the node kind is anything other than a map, nil will be returned. - // /// - // /// The iterator will yield every entry in the map; that is, it - // /// can be expected that itr.Next will be called node.Length times - // /// before itr.Done becomes true. - // pub fn map_iterator(&self) -> impl Iterator { - // unimplemented!() - // } - - // /// ListIterator returns an iterator which traverses the node and yields indicies and list entries. - // /// If the node kind is anything other than a list, nil will be returned. - // /// - // /// The iterator will yield every entry in the list; that is, it - // /// can be expected that itr.Next will be called node.Length times - // /// before itr.Done becomes true. - // /// - // /// List iteration is ordered, and indices yielded during iteration will range from 0 to Node.Length-1. - // /// (The IPLD Data Model definition of lists only defines that it is an ordered list of elements; - // /// the definition does not include a concept of sparseness, so the indices are always sequential.) - // pub fn list_iterator(&self) -> impl Iterator { - // unimplemented!() - // } - - /// Length returns the length of a list, or the number of entries in a map, - /// or -1 if the node is not of list nor map kind. - pub fn len(&self) -> usize { - unimplemented!() - } - - /// Absent nodes are returned when traversing a struct field that is - /// defined by a schema but unset in the data. (Absent nodes are not - /// possible otherwise; you'll only see them from `schema.TypedNode`.) - /// The absent flag is necessary so iterating over structs can - /// unambiguously make the distinction between values that are - /// present-and-null versus values that are absent. - /// - /// Absent nodes respond to `Kind()` as `ipld.Kind_Null`, - /// for lack of any better descriptive value; you should therefore - /// always check IsAbsent rather than just a switch on kind - /// when it may be important to handle absent values distinctly. - pub fn is_absent(&self) -> bool { - unimplemented!() - } - - pub fn as_bool(&self) -> Result { - unimplemented!() - } - pub fn as_int(&self) -> Result<&Int, Error> { - unimplemented!() - } - pub fn as_float(&self) -> Result<&Float, Error> { - unimplemented!() - } - pub fn as_string(&self) -> Result<&str, Error> { - unimplemented!() - } - pub fn as_bytes(&self) -> Result<&Bytes, Error> { - unimplemented!() - } - pub fn as_link(&self) -> Result, Error> { - unimplemented!() - } - - // Prototype returns a NodePrototype which can describe some properties of this node's implementation, - // and also be used to get a NodeBuilder, - // which can be use to create new nodes with the same implementation as this one. - // - // For typed nodes, the NodePrototype will also implement schema.Type. - // - // For Advanced Data Layouts, the NodePrototype will encapsulate any additional - // parameters and configuration of the ADL, and will also (usually) - // implement NodePrototypeSupportingAmend. - // - // Calling this method should not cause an allocation. - // Prototype() NodePrototype -} - */ +#[cfg(feature = "dep:rkyv")] +mod rkyv {} diff --git a/src/data_model/link.rs b/src/data_model/link.rs index b42d22d..bffda0f 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -2,6 +2,13 @@ use crate::dev::*; use macros::{derive_more::From, repr_serde}; use maybestd::fmt; +/// +pub trait LinkRepresentation: Representation { + // const_assert ::{DM_KIND, SCHEMA_KIND} == Link +} +// TODO +impl LinkRepresentation for Cid {} + /// #[derive( Copy, @@ -13,15 +20,15 @@ use maybestd::fmt; PartialEq, // todo // PartialOrd )] -pub enum Link { +pub enum Link { /// - Cid(Cid), + Id(I), /// #[from(ignore)] Resolved { /// - cid: Cid, + id: I, /// t: T, /// @@ -29,13 +36,13 @@ pub enum Link { }, } -impl Link { +impl Link { /// #[inline] - pub const fn cid(&self) -> &Cid { + pub const fn id(&self) -> &I { match self { - Self::Cid(cid) => cid, - Self::Resolved { cid, .. } => cid, + Self::Id(id) => id, + Self::Resolved { id, .. } => id, } } @@ -43,7 +50,7 @@ impl Link { #[inline] pub const fn is_dirty(&self) -> bool { match self { - Self::Cid(_) => false, + Self::Id(_) => false, Self::Resolved { dirty, .. } => *dirty, } } @@ -52,7 +59,7 @@ impl Link { #[inline] pub const fn as_ref(&self) -> Option<&T> { match self { - Self::Cid(_) => None, + Self::Id(_) => None, Self::Resolved { t, .. } => Some(t), } } @@ -73,31 +80,30 @@ impl Link { */ } +// TODO: restrict to some I impl Representation for Link { - type DataModelKind = type_kinds::Link; - type SchemaKind = type_kinds::Link; - type ReprKind = type_kinds::Link; - const NAME: &'static str = "Link"; const SCHEMA: &'static str = "type Link &Any"; const DATA_MODEL_KIND: Kind = Kind::Link; - const SCHEMA_KIND: Kind = Kind::Link; - const REPR_KIND: Kind = Kind::Link; fn name(&self) -> &'static str { match self { - Self::Cid(_) => Self::NAME, + Self::Id(_) => Self::NAME, Self::Resolved { t, .. } => t.name(), } } fn has_links(&self) -> bool { match self { - Self::Cid(_) => T::HAS_LINKS, + Self::Id(_) => T::HAS_LINKS, Self::Resolved { t, .. } => t.has_links(), } } + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Link(*self.id()) + } + /// #[inline] fn serialize(&self, serializer: S) -> Result @@ -109,7 +115,7 @@ impl Representation for Link { "cannot serialize dirty links; flush changes first", )) } else { - Representation::serialize::(self.cid(), serializer) + Representation::serialize::(self.id(), serializer) } } @@ -119,21 +125,16 @@ impl Representation for Link { where D: Deserializer<'de>, { - Ok(Self::Cid(Cid::deserialize::(deserializer)?)) + Ok(Self::Id(Cid::deserialize::(deserializer)?)) } } -repr_serde! { @select_for Link => T - { @dk (type_kinds::Link) @sk (type_kinds::Link) @rk (type_kinds::Link) } - { T } { T: Select + 'static } -} -repr_serde! { @visitors for S => T - { @dk (type_kinds::Link) @sk (type_kinds::Link) @rk (type_kinds::Link) } - { S, T } { S: 'static, T: Select + 'static } +repr_serde! { @select for Link { T } { T: Select + 'static }} +repr_serde! { @visitors for Link { T } { T: Select + 'static } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A link of type {} to a {}", S::NAME, T::NAME) + write!(f, "A link of type {} to a {}", >::NAME, T::NAME) } #[inline] fn visit_bytes(self, bytes: &[u8]) -> Result @@ -172,9 +173,9 @@ where if self.selector.is_matcher() { if self.is_dag_select() { - self.select_dag(Link::Cid(cid))?; + self.handle_dag(Link::Id(cid))?; } else { - self.select_node(cid.into())?; + self.handle_node(cid.into())?; } return Ok(()); @@ -188,12 +189,15 @@ where impl Into for Link { fn into(self) -> Cid { match self { - Self::Cid(cid) => cid, - Self::Resolved { cid, .. } => cid, + Self::Id(cid) => cid, + Self::Resolved { id: cid, .. } => cid, } } } +#[cfg(feature = "dep:rkyv")] +mod rkyv {} + // // TODO: dirty links? // impl Serialize for Link // where diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 51e52f9..0137ab2 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -7,7 +7,6 @@ use maybestd::{ ops::{Bound, RangeBounds}, vec::Vec, }; -use serde::de::value::SeqAccessDeserializer; pub use iterators::*; @@ -17,32 +16,32 @@ pub use iterators::*; pub type List = Vec; impl Representation for List { - type DataModelKind = type_kinds::List; - type SchemaKind = type_kinds::List; - type ReprKind = type_kinds::List; - const NAME: &'static str = "List"; const SCHEMA: &'static str = "type List [Any]"; const DATA_MODEL_KIND: Kind = Kind::List; - const SCHEMA_KIND: Kind = Kind::List; - const REPR_KIND: Kind = Kind::List; const HAS_LINKS: bool = T::HAS_LINKS; fn has_links(&self) -> bool { self.iter().any(Representation::has_links) } + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::List + } + #[inline] #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { + // #[cfg(feature = "dag-rkyv")] + use ser::SerializeSeq; let mut seq = serializer.serialize_seq(Some(self.len()))?; for elem in self { - seq.serialize_element(&SerializeWrapper::<'_, C, _>(elem))?; + seq.serialize_element(&SerializeRepr::<'_, C, _>(elem))?; } seq.end() } @@ -64,13 +63,17 @@ impl Representation for List { write!(f, "A list of `{}`", T::NAME) } #[inline] - fn visit_seq(self, seq: A) -> Result + fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); - let mut iter = SerdeListIterator::<'de, A>::from(seq); - while let Some(dag) = iter.next::().map_err(A::Error::custom)? { + // let mut iter = SerdeListIterator::<'de, A>::from(seq); + // while let Some(dag) = iter.next::().map_err(A::Error::custom)? { + // list.push(dag); + // } + + while let Some(dag) = seq.next_element_seed(DeserializeRepr::::new())? { list.push(dag); } Ok(list) @@ -81,93 +84,76 @@ impl Representation for List { } } -repr_serde! { @select_for List => T - { @dk (type_kinds::List) @sk (type_kinds::List) @rk (type_kinds::List) } - { T } { T: Select + 'static } -} -repr_serde! { @visitors for S => T - { @dk (type_kinds::List) @sk (type_kinds::List) @rk (type_kinds::List) } - { S, T } { S: Default + Extend + 'static, - T: Select + 'static } @serde { +repr_serde! { @select for List { T } { T: Select + 'static }} +repr_serde! { @visitors for List { T } { T: Select + 'static } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A list of type {} of {}", S::NAME, T::NAME) + write!(f, "A list of type {} of {}", >::NAME, T::NAME) } - #[inline] fn visit_seq(self, seq: A) -> Result where A: SeqAccess<'de>, { - if let Some(s) = self.0.selector.as_explore_union() { - if s.matches_first() { - let list = S::deserialize::(SeqAccessDeserializer::new(seq))?; + use de::value::SeqAccessDeserializer as De; + + match (self.mode(), self.selector()) { + (SelectionMode::Match, _) => { + let list = >::deserialize::(De::new(seq))?; + // todo: + self.into_inner().handle_dag(list).map_err(A::Error::custom) + } + (_, Selector::ExploreUnion(s)) if s.matches_first() => { + let list = >::deserialize::(De::new(seq))?; // todo: for each selector, __select_in - return list.__select_in(self.0).map_err(A::Error::custom); - } else { - // todo: support multiple non-overlapping ranges + list.__select_in(self.into_inner()).map_err(A::Error::custom) } - } - - let iter = SerdeListIterator::<'de, _>::from(seq); - match self.0.selector { - Selector::Matcher(_) => { - self.0.match_list::( - iter, - |_| RefCell::default(), - |dag| Box::new(|child, _| Ok(dag.borrow_mut().extend(iter::once(child)))), - RefCell::into_inner, - ).map_err(A::Error::custom) - }, - Selector::ExploreIndex(s) => self.0 - .explore_list_range::(iter, s.to_range()) - .map_err(A::Error::custom), - Selector::ExploreRange(s) => self.0 - .explore_list_range::(iter, s.to_range()) - .map_err(A::Error::custom), - Selector::ExploreAll(s) => self.0 - .explore_list_range::(iter, s.to_range()) - .map_err(A::Error::custom), - _ => Err(A::Error::custom(Error::unsupported_selector::( - self.0.selector, - ))), + _ => self.into_inner() + .select_list::(SerdeListIterator::from(seq)) + .map_err(A::Error::custom) } } }} -// repr_serde! { @visitor_ext S T { type_kinds::List } { S, T } -// { S: Default + Extend + 'static, -// T: Select + 'static } {} -// } -// repr_serde! { @link_visitor_blanket for S => T { type_kinds::List } -// { S, T } -// { S: Default + Extend + 'static, T: Select + 'static } {} -// } -// repr_serde! { @select List => T { T } { T: Select + 'static } } -// repr_serde! { @select_blanket S T { type_kinds::List } { S, T } -// { S: Default + Extend + 'static, T: Select + 'static } -// } - -// TODO: constrain to DM=List and SK=List, then blanket Select for them impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, - T: Representation + Select + 'static, + // T: Representation, + T: Select + 'static, { /// - pub fn select_list( + pub fn select_list( mut self, + mut iter: I, // dag: Either<&T2, I>, ) -> Result<(), Error> where U: Select, I: ListIterator, { - unimplemented!() + // match self.selector { + // Selector::Matcher(_) => self.match_list::(iter), + // Selector::ExploreIndex(s) => self.explore_list_range::(iter, s.to_range()), + // Selector::ExploreRange(s) => self.explore_list_range::(iter, s.to_range()), + // Selector::ExploreAll(s) => self.explore_list_range::(iter, s.to_range()), + // s => Err(Error::unsupported_selector::>(s)), + // } + + self.handle_node(SelectedNode::List)?; + loop { + if self.handle_index::(&mut iter, None)? { + break; + } + } + Ok(()) } /// - pub fn patch_list(mut self, dag: &mut T) -> Result<(), Error> + pub fn patch_list( + mut self, + mut iter: I, + // dag: Either<&T2, I>, + ) -> Result<(), Error> where U: Select, I: ListIterator, @@ -175,50 +161,46 @@ where unimplemented!() } + /* /// Executes a [`Matcher`] selector against a list (data model) type. /// todo could probably use a collection trait instead of multiple Fns - pub fn match_list( + pub fn match_list( mut self, mut iter: I, - init_new_dag: F1, - mut match_cb: F2, - into_dag: F3, + // init_new_dag: F1, + // mut match_cb: F2, + // into_dag: F3, ) -> Result<(), Error> where U: Select, I: ListIterator, - T2: Default, - F1: FnOnce(&I) -> T2, - for<'b> F2: FnMut(&'b T2) -> Box + 'b>, - F3: FnOnce(T2) -> T, + // T2: Default, + // F1: FnOnce(&I) -> T2, + // for<'b> F2: FnMut(&'b T2) -> Box + 'b>, + // F3: FnOnce(T2) -> T, { + // if self.is_dag_select() { + // self.handle_dag(T::deserialize(deserializer)) + // } + // select the matched list node, or setup the list - self.select_node(SelectedNode::List)?; - let new_dag = self - .is_dag_select() - .then(|| init_new_dag(&iter)) - .unwrap_or_default(); + self.handle_node(SelectedNode::List)?; + // let new_dag = self + // .is_dag_select() + // .then(|| init_new_dag(&iter)) + // .unwrap_or_default(); // select against each child - for idx in 0usize.. { - // FIXME: - // i think we do want to control the seed, ask to descend and ascend - // i think we can make this function support select, patch and flush - - // TODO: should be iter.next_element_seed(self.to_field_select_seed()) - if self.select_index::( - idx, - self.is_dag_select().then(|| match_cb(&new_dag)), - &mut iter, - )? { + loop { + if self.handle_index::(&mut iter, None)? { break; } } // finally, select the dag itself (if applicable) - if self.is_dag_select() { - self.select_dag(into_dag(new_dag))?; - } + // if self.is_dag_select() { + // self.handle_dag(into_dag(new_dag))?; + // } Ok(()) } @@ -245,7 +227,7 @@ where let is_unbounded = ignore_end_idx.is_none(); // select the list node - self.select_node(SelectedNode::List)?; + self.handle_node(SelectedNode::List)?; // ignore everything before the start (unless 0) // if empty, return an err @@ -260,7 +242,7 @@ where // explore any/all indices in the range for index in range { // TODO: should be iter.next_element_seed(self.to_field_select_seed()) - let is_empty = self.select_index::(index, None, &mut iter)?; + let is_empty = self.handle_index::(&mut iter, None)?; // if unbounded and empty, then we're done exploring // if bounded and empty, then we failed to explore everything @@ -282,10 +264,12 @@ where Ok(()) } + */ } mod iterators { use super::*; + use serde::de::IntoDeserializer; /* // /// A [`Select`]able list iterator over a serde sequence representation. @@ -344,19 +328,12 @@ mod iterators { /// A [`Select`]able list iterator over a serde sequence representation. #[doc(hidden)] #[derive(Debug)] - pub struct SerdeListIterator<'de, A> - where - A: SeqAccess<'de>, - { + pub struct SerdeListIterator<'de, A> { inner: A, index: usize, _t: PhantomData<&'de ()>, } - - impl<'de, A> From for SerdeListIterator<'de, A> - where - A: SeqAccess<'de>, - { + impl<'de, A> From for SerdeListIterator<'de, A> { fn from(inner: A) -> Self { Self { inner, @@ -365,19 +342,15 @@ mod iterators { } } } - impl<'de, T, A> ListIterator for SerdeListIterator<'de, A> where + T: Representation, A: SeqAccess<'de>, { fn size_hint(&self) -> Option { self.inner.size_hint() } - - fn field(&self) -> Field<'_> { - Field::Index(self.index) - } - + /* fn next_ignored(&mut self) -> Result { let is_empty = self .inner @@ -389,14 +362,10 @@ mod iterators { } Ok(is_empty) } - - fn next(&mut self) -> Result, Error> - where - T: Representation, - { + fn next(&mut self) -> Result, Error> { let dag = self .inner - .next_element_seed(DeserializeWrapper::::new()) + .next_element_seed(DeserializeRepr::::new()) .map_err(|_| Error::explore_index_failure::(self.index))?; if dag.is_none() { @@ -406,7 +375,6 @@ mod iterators { Ok(dag) } } - fn next_seed<'a, const C: u64, Ctx: Context>( &mut self, seed: SelectorSeed<'a, Ctx, T>, @@ -414,7 +382,9 @@ mod iterators { where T: Select, { - let is_empty = T::__select_seq::(seed, &mut self.inner) + let is_empty = self + .inner + .next_element_seed(DeserializeSelect::::from(seed)) .map_err(|_| Error::explore_index_failure::(self.index))? .is_none(); if !is_empty { @@ -422,8 +392,46 @@ mod iterators { } Ok(is_empty) } + */ + + fn next_element_seed<'a, const C: u64, Ctx: Context + 'a, F>( + &mut self, + seeder: F, + ) -> Result + where + T: Select, + F: FnOnce(usize) -> Result>, Error>, + { + let was_empty = match seeder(self.index)? { + None => self + .inner + .next_element::() + .map(|opt| opt.map(|_| ())), + Some(seed) => self + .inner + .next_element_seed(DeserializeSelect::::from(seed)), + } + .map_err(|_| Error::explore_index_failure::(self.index))? + .is_none(); + + if !was_empty { + self.index += 1; + } + Ok(was_empty) + } } + // impl<'de, A> IntoDeserializer<'de, A::Error> for SerdeListIterator<'de, A> + // where + // A: SeqAccess<'de>, + // { + // type Deserializer = SeqAccessDeserializer; + // fn into_deserializer(self) -> Self::Deserializer { + // SeqAccessDeserializer::new(self.inner) + // } + // } + + /* /// A [`Select`]able list iterator over an underlying iterator. pub struct MemoryListIterator<'a, T, I> { iter: I, @@ -469,12 +477,13 @@ mod iterators { Ok(self.len == self.index) } } + */ } #[cfg(test)] mod tests { use super::*; - use crate::prelude::*; + use crate::*; #[test] fn test_match() {} diff --git a/src/data_model/map.rs b/src/data_model/map.rs index 6df9bcf..848a7a5 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -11,7 +11,7 @@ pub use iterators::*; /// /// [`BTreeMap`]: crate::maybestd::collections::BTreeMap /// TODO: indexmap? -pub type Map = BTreeMap; +pub type Map = BTreeMap; impl Representation for Map where @@ -21,20 +21,18 @@ where // K: AsRef> V: Representation, { - type DataModelKind = type_kinds::Map; - type SchemaKind = type_kinds::Map; - type ReprKind = type_kinds::Map; - const NAME: &'static str = "Map"; const SCHEMA: &'static str = "type Map {String:Any}"; const DATA_MODEL_KIND: Kind = Kind::Map; - const SCHEMA_KIND: Kind = Kind::Map; - const REPR_KIND: Kind = Kind::Map; fn has_links(&self) -> bool { self.iter().any(|(k, v)| k.has_links() || v.has_links()) } + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Map + } + #[inline] #[doc(hidden)] fn serialize(&self, serializer: S) -> Result @@ -46,8 +44,8 @@ where let mut map = serializer.serialize_map(Some(self.len()))?; for (key, val) in self { map.serialize_entry( - &SerializeWrapper::<'_, C, _>(key), - &SerializeWrapper::<'_, C, _>(val), + &SerializeRepr::<'_, C, _>(key), + &SerializeRepr::<'_, C, _>(val), )?; } map.end() @@ -62,7 +60,8 @@ where struct MapVisitor(PhantomData<(K, V)>); impl<'de, const C: u64, K, V> Visitor<'de> for MapVisitor where - K: Representation + Ord, + K: StringRepresentation, + ::Err: fmt::Display, V: Representation, { type Value = Map; @@ -76,22 +75,25 @@ where A: MapAccess<'de>, { let mut new_map = Map::new(); + + // while let Some(key) = iter.next_key::()? { + // new_map.insert(key, iter.next_value::()?) + // } + let mut iter = SerdeMapIterator::<'de, A>::from(map); - while let Some(key) = - as MapIterator>::next_key::(&mut iter, None) - .map_err(A::Error::custom)? + while let Some(key) = <_ as MapIterator>::next_key::(&mut iter, None) + .map_err(A::Error::custom)? { let val = key .as_field() .ok_or_else(|| Error::explore_key_failure::(None)) .and_then(|field| { - as MapIterator>::next_value::( - &mut iter, &field, - ) + <_ as MapIterator>::next_value::(&mut iter, &field) }) .map_err(A::Error::custom)?; new_map.insert(key, val); } + Ok(new_map) } } @@ -100,40 +102,39 @@ where } } -repr_serde! { @select_for Map => (K, V) - { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::Map) } +repr_serde! { @select for Map { K, V } { K: Select + StringRepresentation + 'static, ::Err: fmt::Display, V: Select + 'static } } -repr_serde! { @visitors for T => (K, V) - { @dk (type_kinds::Map) @sk (type_kinds::Map) @rk (type_kinds::Map) } - { T, K, V } { T: Default + Extend<(K, V)> + 'static, - K: Select + StringRepresentation + 'static, - ::Err: fmt::Display, - V: Select + 'static } @serde { +repr_serde! { @visitors for Map + { K, V } { K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A map of type {} of {} to {}", T::NAME, K::NAME, V::NAME) + write!(f, "A map of type {} of {} to {}", >::NAME, K::NAME, V::NAME) } - #[inline] fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { - if let Some(s) = self.0.selector.as_explore_union() { + if let Some(s) = self.as_ref().selector.as_explore_union() { if s.matches_first() { // TODO: transform the seed to a phantom seed, then recurse - let map = T::deserialize::(MapAccessDeserializer::new(map))?; - return map.__select_in(self.0).map_err(A::Error::custom); + let map = >::deserialize::(MapAccessDeserializer::new(map))?; + return map.__select_in(self.into_inner()).map_err(A::Error::custom); } } - let iter = SerdeMapIterator::<'de, _>::from(map); - match self.0.selector { + self.into_inner() + .select_map::(SerdeMapIterator::from(map)) + .map_err(A::Error::custom) + /* + match self.as_ref().selector { Selector::Matcher(_) => { - self.0.match_map::( + self.into_inner().match_map::( iter, |_| RefCell::default(), |key, dag| Box::new(|child, _| { @@ -143,174 +144,50 @@ repr_serde! { @visitors for T => (K, V) RefCell::into_inner, ).map_err(A::Error::custom) }, - Selector::ExploreFields(_) => self.0 + Selector::ExploreFields(_) => self.into_inner() .explore_map_fields::(iter) .map_err(A::Error::custom), - Selector::ExploreAll(_) => self.0 + Selector::ExploreAll(_) => self.into_inner() .explore_map_fields::(iter) .map_err(A::Error::custom), - _ => Err(A::Error::custom(Error::unsupported_selector::( - self.0.selector, + _ => Err(A::Error::custom(Error::unsupported_selector::>( + self.as_ref().selector, ))), } + */ } }} -// repr_serde! { @visitor_ext T (K, V) { type_kinds::Map } { T, K, V } -// { T: Default + Extend<(K, V)> + 'static, -// K: Select + StringRepresentation + 'static, -// ::Err: fmt::Display, -// V: Select + 'static } -// {} -// } -// repr_serde! { @link_visitor_blanket for T => (K, V) { type_kinds::Map } { T, K, V } -// { T: Default + Extend<(K, V)> + 'static, -// K: Select + StringRepresentation + 'static, -// ::Err: fmt::Display, -// V: Select + 'static } -// {} -// } - -// repr_serde! { @select Map => (K, V) { K, V } -// { K: Select + StringRepresentation + 'static, -// ::Err: fmt::Display, -// V: Select + 'static } -// } - -impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> -where - Ctx: Context, - T: Select + 'static, -{ - /// - pub fn match_map( - mut self, - mut iter: I, - init_new_dag: F1, - mut match_cb: F2, - into_dag: F3, - ) -> Result<(), Error> - where - K: Select + StringRepresentation, - ::Err: fmt::Display, - V: Select, - I: MapIterator, - T2: Default + 'static, - F1: FnOnce(&I) -> T2, - for<'b> F2: FnMut(&'b K, &'b T2) -> Box + 'b>, - F3: FnOnce(T2) -> T, - { - // select the matched node, or set up the dag - self.select_node(SelectedNode::Map)?; - let new_dag = self - .is_dag_select() - .then(|| init_new_dag(&iter)) - .unwrap_or_default(); - - // select against each child - while let Some(key) = iter.next_key::(None)? { - self.select_field::( - self.is_dag_select().then(|| match_cb(&key, &new_dag)), - &mut iter, - )?; - } - - // // let mut seed = self; - // // let match_cb = &mut match_cb; - // loop { - // // let seed = self.to_field_select_seed(field, match_cb) - // // let mut seed = self; - // if iter.next_entry_seed::(|key| { - // let field = key - // .as_field() - // .ok_or_else(|| Error::explore_key_failure::(None))?; - // self.to_field_select_seed( - // &field, - // self.is_dag_select().then(|| match_cb(&key, &new_dag)), - // ) - // })? { - // break; - // } - // } - - // TODO: should be iter.next_entry_seed(|key| self.to_field_select_seed()) - // while !iter.next_entry_seed::(&mut self)? {} - - // finally, select the matched dag - if self.is_dag_select() { - self.select_dag(into_dag(new_dag))?; - } - - Ok(()) - } - - /// - pub(crate) fn explore_map_fields(self, mut iter: I) -> Result<(), Error> - where - K: Select + StringRepresentation + 'static, - ::Err: fmt::Display, - V: Select + 'static, - I: MapIterator, - { - unimplemented!() - } -} - -// pub(crate) fn match_map(seed: SelectorSeed<'_, Ctx, T>, mut iter: I) -> Result<(), Error> -// where -// I: MapReprIterator, -// { - -// } - mod iterators { use super::*; /// #[doc(hidden)] #[derive(Debug)] - pub struct SerdeMapIterator<'de, A> - where - A: MapAccess<'de>, - { - inner: A, - _t: PhantomData<&'de ()>, - } - - impl<'de, A> From for SerdeMapIterator<'de, A> - where - A: MapAccess<'de>, - { + pub struct SerdeMapIterator<'de, A>(A, PhantomData<&'de ()>); + impl<'de, A> From for SerdeMapIterator<'de, A> { fn from(inner: A) -> Self { - Self { - inner, - _t: PhantomData, - } + Self(inner, PhantomData) } } - impl<'de, K, V, A> MapIterator for SerdeMapIterator<'de, A> where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, A: MapAccess<'de>, { fn size_hint(&self) -> Option { - self.inner.size_hint() - } - - fn field(&self) -> Field<'_> { - unimplemented!() + self.0.size_hint() } fn next_key( &mut self, expected_field_name: Option<&'static str>, - ) -> Result, Error> - where - K: Representation, - { + ) -> Result, Error> { let key = self - .inner - .next_key_seed(DeserializeWrapper::::new()) + .0 + .next_key_seed(DeserializeRepr::::new()) .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; // TODO: assert that key == expected_field_name @@ -318,18 +195,15 @@ mod iterators { } fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { - self.inner + self.0 .next_value::() .or_else(|_| Err(Error::explore_value_failure::(field)))?; Ok(()) } - fn next_value(&mut self, field: &Field<'_>) -> Result - where - V: Representation, - { - self.inner - .next_value_seed(DeserializeWrapper::::new()) + fn next_value(&mut self, field: &Field<'_>) -> Result { + self.0 + .next_value_seed(DeserializeRepr::::new()) .or_else(|_| Err(Error::explore_value_failure::(field))) } @@ -339,7 +213,6 @@ mod iterators { // field: &Field<'_>, ) -> Result<(), Error> where - K: Representation, V: Select, { // let key = >::key(self); @@ -355,6 +228,7 @@ mod iterators { } } + /* struct MemoryMapIterator<'a, K, V, I> { iter: I, // index: usize, @@ -437,4 +311,113 @@ mod iterators { unimplemented!() } } + */ +} + +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> +where + Ctx: Context, + T: Select + 'static, +{ + /// + pub fn select_map( + mut self, + mut iter: I, + // dag: Either<&T2, I>, + ) -> Result<(), Error> + where + K: Select + StringRepresentation, + ::Err: fmt::Display, + V: Select, + I: MapIterator, + { + unimplemented!() + } + + /// + pub fn patch_map( + mut self, + mut iter: I, + // dag: Either<&T2, I>, + ) -> Result<(), Error> + where + K: Select + StringRepresentation, + ::Err: fmt::Display, + V: Select, + I: MapIterator, + { + unimplemented!() + } + + /// + pub fn match_map( + mut self, + mut iter: I, + init_new_dag: F1, + mut match_cb: F2, + into_dag: F3, + ) -> Result<(), Error> + where + K: Select + StringRepresentation, + ::Err: fmt::Display, + V: Select, + I: MapIterator, + T2: Default + 'static, + F1: FnOnce(&I) -> T2, + for<'b> F2: FnMut(&'b K, &'b T2) -> Box + 'b>, + F3: FnOnce(T2) -> T, + { + // select the matched node, or set up the dag + self.handle_node(SelectedNode::Map)?; + let new_dag = self + .is_dag_select() + .then(|| init_new_dag(&iter)) + .unwrap_or_default(); + + // select against each child + while let Some(key) = iter.next_key::(None)? { + self.handle_field::( + &mut iter, + self.is_dag_select().then(|| match_cb(&key, &new_dag)), + )?; + } + + // // let mut seed = self; + // // let match_cb = &mut match_cb; + // loop { + // // let seed = self.to_field_select_seed(field, match_cb) + // // let mut seed = self; + // if iter.next_entry_seed::(|key| { + // let field = key + // .as_field() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // self.to_field_select_seed( + // &field, + // self.is_dag_select().then(|| match_cb(&key, &new_dag)), + // ) + // })? { + // break; + // } + // } + // TODO: should be iter.next_entry_seed(|key| self.to_field_select_seed()) + // while !iter.next_entry_seed::(&mut self)? {} + + // finally, select the matched dag + if self.is_dag_select() { + self.handle_dag(into_dag(new_dag))?; + } + + Ok(()) + } + + /// + pub(crate) fn explore_map_fields(self, mut iter: I) -> Result<(), Error> + where + K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static, + I: MapIterator, + { + unimplemented!() + } } diff --git a/src/data_model/mod.rs b/src/data_model/mod.rs index f86d7d7..e6388c9 100644 --- a/src/data_model/mod.rs +++ b/src/data_model/mod.rs @@ -2,6 +2,7 @@ use crate::dev::*; use macros::derive_more::From; +use maybestd::{borrow::Borrow, marker::PhantomData}; mod any; // pub mod borrowed; @@ -9,6 +10,8 @@ mod any; mod link; mod list; mod map; +// mod node; +#[macro_use] mod primitive; // mod recursive; @@ -16,14 +19,20 @@ pub use any::Any; pub use link::Link; pub use list::List; pub use map::Map; +// pub use node::Node; pub use primitive::*; /// Wrapper type to connect [`serde::Serialize`] to the underlying type's /// [`Representation::serialize`] codec-specific implementation. #[doc(hidden)] #[derive(Debug, From)] -pub struct SerializeWrapper<'a, const C: u64, T>(pub &'a T); -impl<'a, const C: u64, T> Serialize for SerializeWrapper<'a, C, T> +pub struct SerializeRepr<'a, const C: u64, T>(pub &'a T); +// impl<'a, const C: u64, T> SerializeWrapper { +// pub const fn new(dag: &'a T) -> Self { +// Self(dag) +// } +// } +impl<'a, const C: u64, T> Serialize for SerializeRepr<'a, C, T> where T: Representation, { @@ -36,17 +45,24 @@ where } } +// pub struct SWrapper<'a, const C: u64, T: Borrow, Q>(pub &'a Q, PhantomData); +// impl<'a, const C: u64, T: Representation + Borrow, Q> Borrow> for T { +// fn borrow(&self) -> &SWrapper<'a, C, T, Q> { +// &SWrapper::<'a, C, T, Q>(self.borrow(), PhantomData) +// } +// } + /// Wrapper type to connect [`serde::Deserialize`] to the underlying type's /// [`Representation::deserialize`] codec-specific implementation. #[doc(hidden)] #[derive(Debug)] -pub struct DeserializeWrapper(std::marker::PhantomData); -impl DeserializeWrapper { +pub struct DeserializeRepr(PhantomData); +impl DeserializeRepr { pub const fn new() -> Self { - Self(std::marker::PhantomData) + Self(PhantomData) } } -impl<'de, const C: u64, T> DeserializeSeed<'de> for DeserializeWrapper +impl<'de, const C: u64, T> DeserializeSeed<'de> for DeserializeRepr where T: Representation, { @@ -59,3 +75,30 @@ where ::deserialize::(deserializer) } } + +/// Wrapper type to connect [`serde::DeserializeSeed`]s to the underlying type's +/// [`Select::__select_de`] codec-specific implementation. +#[doc(hidden)] +#[derive(Debug)] +pub struct DeserializeSelect(S, PhantomData<(Ctx, T)>); +impl DeserializeSelect { + pub const fn from(seed: S) -> Self { + Self(seed, PhantomData) + } +} +impl<'a, 'de, const C: u64, Ctx, T> DeserializeSeed<'de> + for DeserializeSelect, T> +where + Ctx: Context, + // S: SeedType, TODO: + T: Select, +{ + type Value = (); + #[inline(always)] + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::__select_de::(self.0, deserializer) + } +} diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index 490c941..06061e3 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -3,13 +3,13 @@ use macros::{ derive_more::{AsMut, AsRef, Deref, DerefMut, From, Index, IndexMut, Into, IntoIterator}, repr_serde, }; -use maybestd::{borrow::Cow, fmt, ops::RangeBounds, str::FromStr}; +use maybestd::{borrow::Cow, fmt, ops, str::FromStr}; pub use self::bool::Bool; pub use self::bytes::Bytes; pub use self::null::Null; pub use self::num::*; -pub use self::string::IpldString; +// pub use self::string::IpldString; /// Default type for IPLD integers, which aliases to [`i64`]. pub type Int = i64; @@ -21,63 +21,48 @@ mod null { use super::*; /// A nothing type. - #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] + #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq, Representation)] + #[ipld(internal)] pub struct Null; - impl Representation for Null { - type DataModelKind = type_kinds::Null; - type SchemaKind = type_kinds::Null; - type ReprKind = type_kinds::Null; - - const NAME: &'static str = "Null"; - const SCHEMA: &'static str = "type Null null"; - const DATA_MODEL_KIND: Kind = Kind::Null; - const SCHEMA_KIND: Kind = Kind::Null; - const REPR_KIND: Kind = Kind::Null; - - #[doc(hidden)] - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_none() - } - - #[doc(hidden)] - #[inline] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Self::from(<()>::deserialize(deserializer)?)) - } - } - - repr_serde! { @select_for Null } - repr_serde! { @visitors for T => T - { @dk (type_kinds::Null) @sk (type_kinds::Null) @rk (type_kinds::Null) } - { T } { T: From<()> + 'static } @serde { + repr_serde! { @select for Null } + repr_serde! { @visitors for Null { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A nothing type {}", T::NAME) + write!(f, "A nothing type `{}`", ::NAME) } #[inline] - fn visit_none(self) -> Result + fn visit_none(self) -> Result where - E: de::Error, + Er: de::Error, { - self.0.select_scalar::(T::from(())).map_err(E::custom) + self.into_inner() + .select_scalar::(Null) + .map_err(Er::custom) } #[inline] - fn visit_unit(self) -> Result + fn visit_unit(self) -> Result where - E: de::Error, + Er: de::Error, { self.visit_none() } }} + // impl Select for Null { + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const C: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // AstWalk::<'a, C, _, Self>(seed).deserialize(deserializer) + // } + // } + impl From<()> for Null { #[inline] fn from(_: ()) -> Self { @@ -89,21 +74,19 @@ mod null { mod bool { use super::*; - /// A boolean type, represented as a [`bool`]. + /// Type alias for [`bool`]. /// /// [`bool`]: crate::maybestd::primitive::bool pub type Bool = bool; impl Representation for bool { - type DataModelKind = type_kinds::Bool; - type SchemaKind = type_kinds::Bool; - type ReprKind = type_kinds::Bool; - const NAME: &'static str = "Bool"; const SCHEMA: &'static str = "type Bool bool"; const DATA_MODEL_KIND: Kind = Kind::Bool; - const SCHEMA_KIND: Kind = Kind::Bool; - const REPR_KIND: Kind = Kind::Bool; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Bool(*self) + } #[doc(hidden)] #[inline] @@ -124,23 +107,19 @@ mod bool { } } - repr_serde! { @select_for bool } - repr_serde! { @visitors for T => T - { @dk (type_kinds::Bool) @sk (type_kinds::Bool) @rk (type_kinds::Bool) } - { T } { T: TryFrom + 'static, - >::Error: fmt::Display } @serde { + repr_serde! { @select for bool } + repr_serde! { @visitors for bool { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A boolean type {}", T::NAME) + f.write_str("A boolean type") } #[inline] - fn visit_bool(self, v : bool) -> Result + fn visit_bool(self, v : bool) -> Result where - E: de::Error, + Er: de::Error, { - let b = T::try_from(v).map_err(E::custom)?; - self.0.select_scalar::(b).map_err(E::custom) + self.into_inner().select_scalar::(v).map_err(Er::custom) } }} } @@ -156,17 +135,13 @@ mod num { @conv { $($other_ty:ty : $other_visit_fn:ident)* } } ) => { - // #[doc = concat!("Type alias for [`", stringify!($ty), "`]s.")] - // /// - // #[doc = concat!("[`", stringify!($ty), "`]: ")] - // #[doc = concat!("crate::maybestd::primitive::", stringify!($ty))] - // pub type $name = $ty; + #[doc = concat!("Type alias for [`", stringify!($ty), "`]s.")] + /// + #[doc = concat!("[`", stringify!($ty), "`]: ")] + #[doc = concat!("crate::maybestd::primitive::", stringify!($ty))] + pub type $name = $ty; impl Representation for $ty { - type DataModelKind = type_kinds::$dm_kind; - type SchemaKind = type_kinds::$name; - type ReprKind = type_kinds::$name; - const NAME: &'static str = stringify!($name); const SCHEMA: &'static str = concat!("type ", stringify!($name), " int"); const DATA_MODEL_KIND: Kind = Kind::$dm_kind; @@ -175,6 +150,10 @@ mod num { impl_ipld_num!(@field $dm_kind $ty); + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::$name(*self) + } + #[doc(hidden)] #[inline] fn serialize(&self, serializer: S) -> Result @@ -194,32 +173,29 @@ mod num { } } - repr_serde! { @select_for $ty } - repr_serde! { @visitors for T => T - { @dk (type_kinds::$dm_kind) @sk (type_kinds::$name) @rk (type_kinds::$name) } - { T } { T: TryFrom<$ty> + 'static, - >::Error: fmt::Display } @serde { + repr_serde! { @select for $ty } + repr_serde! { @visitors for $ty { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, - "{}, a fixed-length number type represented as a(n) {}", - <$ty>::NAME, stringify!($ty), + "`{}`, a fixed-length number type represented as a(n) {}", + stringify!($name), stringify!($ty), ) } #[inline] - fn $visit_fn(self, v: $ty) -> Result + fn $visit_fn(self, v: $ty) -> Result where - E: de::Error, + Er: de::Error, { - let n = T::try_from(v).map_err(E::custom)?; - self.0.select_scalar::(n).map_err(E::custom) + self.into_inner().select_scalar::(v).map_err(Er::custom) } $( #[inline] - fn $other_visit_fn(self, v: $other_ty) -> Result + fn $other_visit_fn(self, v: $other_ty) -> Result where - E: de::Error, + Er: de::Error, { - let n = <$ty as Representation>::deserialize::(v.into_deserializer())?; + let de = v.into_deserializer(); + let n: $ty = Representation::deserialize::(de)?; self.$visit_fn(n) } )* @@ -282,59 +258,58 @@ mod string { use super::*; use unicode_normalization::*; + // ? Cow<'a, str> // struct NfcChars<'a>(Recompositions>); // impl<'a> ToOwned for <'a> { // type Owned = String; // fn to_owned(&self) -> Self::Owned { - + // + // } + // } + // + // /// + // #[derive( + // AsRef, + // AsMut, + // Clone, + // Debug, + // Default, + // Deref, + // DerefMut, + // Eq, + // Hash, + // Into, + // Index, + // IndexMut, + // // IntoIterator, + // Ord, + // PartialEq, + // PartialOrd, + // )] + // #[as_ref(forward)] + // #[as_mut(forward)] + // #[deref(forward)] + // #[deref_mut(forward)] + // pub struct IpldString(String); + // + // impl IpldString { + // /// + // pub fn as_str(&self) -> &str { + // self.0.as_str() // } // } - /// - #[derive( - AsRef, - AsMut, - Clone, - Debug, - Default, - Deref, - DerefMut, - Eq, - Hash, - Into, - Index, - IndexMut, - // IntoIterator, - Ord, - PartialEq, - PartialOrd, - )] - #[as_ref(forward)] - #[as_mut(forward)] - #[deref(forward)] - #[deref_mut(forward)] - pub struct IpldString(String); - - impl IpldString { - /// - pub fn as_str(&self) -> &str { - self.0.as_str() - } - } - - impl Representation for IpldString { - type DataModelKind = type_kinds::String; - type SchemaKind = type_kinds::String; - type ReprKind = type_kinds::String; - + impl Representation for String { const NAME: &'static str = "String"; const SCHEMA: &'static str = "type String string"; const DATA_MODEL_KIND: Kind = Kind::String; - const SCHEMA_KIND: Kind = Kind::String; - const REPR_KIND: Kind = Kind::String; fn as_field(&self) -> Option> { - Some(self.0.as_str().into()) + Some(self.as_str().into()) + } + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::String(self.nfc().collect()) } #[doc(hidden)] @@ -343,7 +318,7 @@ mod string { where S: Serializer, { - Serialize::serialize(&self.0, serializer) + serializer.collect_str(&self.as_str().nfc()) } #[doc(hidden)] @@ -352,89 +327,86 @@ mod string { where D: Deserializer<'de>, { - Ok(Self::from(>::deserialize(deserializer)?)) + let s = >::deserialize(deserializer)?; + Ok(s.nfc().collect()) } } - repr_serde! { @select_for IpldString } - repr_serde! { @visitors for T => T - { @dk (type_kinds::String) @sk (type_kinds::String) @rk (type_kinds::String) } - { T } { T: TryFrom + 'static, - >::Error: fmt::Display } @serde { + repr_serde! { @select for String } + repr_serde! { @visitors for String { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A string of type {}", T::NAME) + f.write_str("A string of UTF-8 characters") } #[inline] - fn visit_str(self, s: &str) -> Result + fn visit_str(self, s: &str) -> Result where - E: de::Error, + Er: de::Error, { - let s = T::try_from(IpldString::from(s)).map_err(E::custom)?; - self.0.select_scalar::(s).map_err(E::custom) + self.into_inner() + .select_scalar::(s.nfc().collect()) + .map_err(Er::custom) } #[inline] - fn visit_string(self, s: String) -> Result + fn visit_string(self, s: String) -> Result where - E: de::Error, + Er: de::Error, { self.visit_str(s.as_ref()) } }} - impl From<&str> for IpldString { - #[inline] - fn from(s: &str) -> Self { - Self(s.nfc().collect::()) - } - } - impl From<&mut str> for IpldString { - fn from(s: &mut str) -> Self { - Self::from(&*s) - } - } - impl From> for IpldString { - fn from(s: Box) -> Self { - Self::from(s.as_ref()) - } - } - impl<'a> From> for IpldString { - fn from(s: Cow<'a, str>) -> Self { - Self::from(s.as_ref()) - } - } - impl From for IpldString { - fn from(s: String) -> Self { - Self::from(s.as_str()) - } - } - - impl FromStr for IpldString { - type Err = Error; - fn from_str(s: &str) -> Result { - Ok(Self::from(s)) - } - } - - impl fmt::Display for IpldString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } - } + // impl From<&str> for IpldString { + // #[inline] + // fn from(s: &str) -> Self { + // Self(s.nfc().collect::()) + // } + // } + // impl From<&mut str> for IpldString { + // fn from(s: &mut str) -> Self { + // Self::from(&*s) + // } + // } + // impl From> for IpldString { + // fn from(s: Box) -> Self { + // Self::from(s.as_ref()) + // } + // } + // impl<'a> From> for IpldString { + // fn from(s: Cow<'a, str>) -> Self { + // Self::from(s.as_ref()) + // } + // } + // impl From for IpldString { + // fn from(s: String) -> Self { + // Self::from(s.as_str()) + // } + // } + // + // impl FromStr for IpldString { + // type Err = Error; + // fn from_str(s: &str) -> Result { + // Ok(Self::from(s)) + // } + // } + // + // impl fmt::Display for IpldString { + // fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // self.0.fmt(f) + // } + // } } mod bytes { use super::*; - - // /// A bytes type. - // pub type Bytes = crate::dev::bytes::Bytes; + use crate::dev::bytes::Bytes as InnerBytes; /// A `bytes` type, which thinly wraps [`bytes::Bytes`]. /// /// TODO: mutability - /// [`Bytes`]: bytes::Bytes + /// [`bytes::Bytes`]: bytes::Bytes #[derive( AsRef, // AsMut, @@ -454,17 +426,17 @@ mod bytes { )] #[as_ref(forward)] #[deref(forward)] - pub struct Bytes(crate::dev::bytes::Bytes); + pub struct Bytes(InnerBytes); impl Bytes { /// pub const fn new() -> Self { - Self(crate::dev::bytes::Bytes::new()) + Self(InnerBytes::new()) } /// pub fn copy_from_slice(bytes: &[u8]) -> Self { - Self(crate::dev::bytes::Bytes::copy_from_slice(bytes)) + Self(InnerBytes::copy_from_slice(bytes)) } /// @@ -478,7 +450,7 @@ mod bytes { } /// - pub fn slice(&self, range: impl RangeBounds) -> Self { + pub fn slice(&self, range: impl ops::RangeBounds) -> Self { Self(self.0.slice(range)) } @@ -495,39 +467,32 @@ mod bytes { } impl From> for Bytes { fn from(bytes: Vec) -> Self { - Self(crate::dev::bytes::Bytes::from(bytes)) + Self(InnerBytes::from(bytes)) } } // impl> ops::Index for Bytes { - // type Output = Self; + // type Output = InnerBytes; // fn index(&self, index: R) -> &Self::Output { - // Self(self.0.slice(index)) + // self.0.slice(index) // } // } impl Representation for Bytes { - type DataModelKind = type_kinds::Bytes; - type SchemaKind = type_kinds::Bytes; - type ReprKind = type_kinds::Bytes; - const NAME: &'static str = "Bytes"; const SCHEMA: &'static str = "type Bytes bytes"; const DATA_MODEL_KIND: Kind = Kind::Bytes; - const SCHEMA_KIND: Kind = Kind::Bytes; - const REPR_KIND: Kind = Kind::Bytes; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Bytes(self.clone()) + } #[doc(hidden)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::serialize_bytes(self.as_ref(), serializer); - } - - Serialize::serialize(self.as_ref(), serializer) + Multicodec::serialize_bytes::(self.as_ref(), serializer) } #[doc(hidden)] @@ -557,21 +522,17 @@ mod bytes { Ok(Self::Value::from(bytes)) } } - impl<'de> LinkVisitor<'de> for BytesVisitor {} + impl<'de, const MC: u64> LinkVisitor<'de, MC> for BytesVisitor {} - Multicodec::deserialize_bytes::(deserializer, BytesVisitor) + Multicodec::deserialize_bytes::(deserializer, BytesVisitor) } } - repr_serde! { @select_for Bytes } - repr_serde! { @visitors for T => T - { @dk (type_kinds::Bytes) @sk (type_kinds::Bytes) @rk (type_kinds::Bytes) } - { T } { T: TryFrom> + for<'a> TryFrom<&'a [u8]> + 'static, - >>::Error: fmt::Display, - for<'a> >::Error: fmt::Display } @serde { + repr_serde! { @select for Bytes } + repr_serde! { @visitors for Bytes { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Bytes of type {}", T::NAME) + write!(f, "bytes of type `{}`", ::NAME) } #[inline] fn visit_bytes(self, bytes: &[u8]) -> Result @@ -593,6 +554,82 @@ mod bytes { } }} + // impl Representation for [u8; N] { + // const NAME: &'static str = "Bytes"; + // const SCHEMA: &'static str = "type Bytes bytes"; + // const DATA_MODEL_KIND: Kind = Kind::Bytes; + + // fn to_selected_node(&self) -> SelectedNode { + // SelectedNode::Bytes(self.clone()) + // } + + // #[doc(hidden)] + // fn serialize(&self, serializer: S) -> Result + // where + // S: Serializer, + // { + // Multicodec::serialize_bytes::(self.as_ref(), serializer) + // } + + // #[doc(hidden)] + // fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + // where + // D: Deserializer<'de>, + // { + // struct BytesVisitor; + // impl<'de> Visitor<'de> for BytesVisitor { + // type Value = Bytes; + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "A slice of bytes of type {}", Self::Value::NAME) + // } + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::copy_from_slice(bytes)) + // } + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::from(bytes)) + // } + // } + // impl<'de> LinkVisitor<'de> for BytesVisitor {} + + // Multicodec::deserialize_bytes::(deserializer, BytesVisitor) + // } + // } + + // repr_serde! { @select for Bytes } + // repr_serde! { @visitors for Bytes { + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "bytes of type `{}`", ::NAME) + // } + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // // let bytes = T::try_from(bytes).map_err(E::custom)?; + // // self.0.select_bytes::(bytes).map_err(E::custom) + // unimplemented!() + // } + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // // let bytes = T::try_from(bytes).map_err(E::custom)?; + // // self.0.select_bytes::(bytes).map_err(E::custom) + // unimplemented!() + // } + // }} + // TODO: be generic over T // impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> // where @@ -621,9 +658,9 @@ mod bytes { .unwrap_or(bytes); if self.is_node_select() { - self.select_node(bytes.into())?; + self.handle_node(bytes.into())?; } else if self.is_dag_select() { - self.select_dag(bytes)?; + self.handle_dag(bytes)?; }; return Ok(()); @@ -660,9 +697,9 @@ where self.selector.try_as_matcher()?; if self.is_node_select() { - self.select_node(dag.to_selected_node())?; + self.handle_node(dag.to_selected_node())?; } else if self.is_dag_select() { - self.select_dag(dag)?; + self.handle_dag(dag)?; }; Ok(()) @@ -672,11 +709,11 @@ where #[cfg(test)] mod tests { use super::*; - use crate::prelude::*; + use crate::*; fn setup(dag: &T) -> MemoryContext { - const DEFAULT_MC: u64 = DagJson::CODE; - const DEFAULT_MH: u64 = Multihash::SHA2_256; + const DEFAULT_MC: u64 = Multicodec::DAG_JSON; + const DEFAULT_MH: u64 = Multihasher::SHA2_256; let mut ctx = MemoryContext::default(); ctx.add_block(Version::V1, DEFAULT_MC, DEFAULT_MH, vec![]) diff --git a/src/error.rs b/src/error.rs index 88f0664..e7701e9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,8 @@ use cid::Error as CidError; use maybestd::{ error::Error as StdError, fmt::Display, num::TryFromIntError, string::FromUtf8Error, }; +#[cfg(feature = "multiaddr")] +use multiaddr::Error as MultiaddrError; use multibase::Error as MultibaseError; use multihash::Error as MultihashError; use serde::{de, ser}; @@ -10,14 +12,18 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum Error { - #[error("Cid error: {0}")] - Cid(#[from] CidError), + #[cfg(feature = "multiaddr")] + #[error("Multiaddr error: {0}")] + Multiaddr(#[from] MultiaddrError), + + #[error("Multibase error: {0}")] + Multibase(#[from] MultibaseError), #[error("Multihash error: {0}")] Multihash(#[from] MultihashError), - #[error("Multibase error: {0}")] - Multibase(#[from] MultibaseError), + #[error("Cid error: {0}")] + Cid(#[from] CidError), #[error("Mismatched `Any` data model type")] MismatchedAny, @@ -128,7 +134,8 @@ pub enum Error { } impl Error { - pub(crate) fn failed_any_conversion(any_variant: &'static str) -> Self + #[doc(hidden)] + pub fn failed_any_conversion(any_variant: &'static str) -> Self where T: Representation, { @@ -138,7 +145,8 @@ impl Error { } } - pub(crate) fn unsupported_selector(selector: &Selector) -> Self + #[doc(hidden)] + pub fn unsupported_selector(selector: &Selector) -> Self where T: Representation, { @@ -149,14 +157,13 @@ impl Error { } } - pub(crate) fn missing_next_selector(selector: &Selector) -> Self { + #[doc(hidden)] + pub fn missing_next_selector(selector: &Selector) -> Self { Self::MissingNextSelector(Representation::name(selector)) } - pub(crate) fn explore_list_failure( - selector: &Selector, - index: usize, - ) -> Self { + #[doc(hidden)] + pub fn explore_list_failure(selector: &Selector, index: usize) -> Self { match selector { Selector::ExploreIndex(_) => Self::ExploreIndexFailure { type_name: E::NAME, @@ -172,7 +179,8 @@ impl Error { } } - pub(crate) fn explore_map_failure(selector: &Selector) -> Self { + #[doc(hidden)] + pub fn explore_map_failure(selector: &Selector) -> Self { match selector { // Selector::ExploreIndex(s) => Self::ExploreIndexFailure(current_index), // Selector::ExploreRange(s) => Self::ExploreRangeFailure(current_index, s.start, s.end), @@ -180,28 +188,32 @@ impl Error { } } - pub(crate) fn explore_index_failure(index: usize) -> Self { + #[doc(hidden)] + pub fn explore_index_failure(index: usize) -> Self { Self::ExploreIndexFailure { type_name: E::NAME, index, } } - pub(crate) fn explore_key_failure(field_name: Option<&'static str>) -> Self { + #[doc(hidden)] + pub fn explore_key_failure(field_name: Option<&'static str>) -> Self { Self::ExploreFieldKeyFailure { key_type_name: K::NAME, field_name: field_name.unwrap_or("anonymous key"), } } - pub(crate) fn explore_value_failure(field: impl Display) -> Self { + #[doc(hidden)] + pub fn explore_value_failure(field: impl Display) -> Self { Self::ExploreFieldValueFailure { value_type_name: V::NAME, key: field.to_string(), } } - pub(crate) fn downcast_failure(msg: &'static str) -> Self { + #[doc(hidden)] + pub fn downcast_failure(msg: &'static str) -> Self { Self::DowncastFailure { type_name: T::NAME, msg, diff --git a/src/lib.rs b/src/lib.rs index 2cee9b2..f89925b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,107 +8,97 @@ //! TODO: //! - utf-8 string handling/normalization //! - replace boxed callbacks with a ref +//! - TryFrom delegation, if custom types want value-checking #![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)] #[cfg_attr(not(feature = "std"), no_std)] -#[forbid(unsafe_code)] -// +// #[cfg(feature = "std")] extern crate std; +#[doc(hidden)] +extern crate self as __ipld; + +// #[forbid(unsafe_code)] +mod advanced; #[path = "cid.rs"] mod cid_; #[path = "codecs/mod.rs"] -mod codecs_; +pub(crate) mod codecs_; mod compat; mod data_model; mod error; +// todo support fmt::Display / writing to a fmt::Formatter for multibase/hash/addr mod multicodec; #[path = "multihash.rs"] mod multihash_; mod representation; mod select; -pub use cid; -#[doc(inline)] pub use error::Error; -pub use multibase; -pub use multihash; - -pub use specs::*; +#[cfg(feature = "multiaddr")] +pub use multiaddr::{self, Multiaddr}; -mod specs { - use super::*; +// specification implementations +pub use { + // cid + cid::{self, Cid as DefaultCid, CidGeneric, Version}, + cid_::Cid, // codecs - #[cfg(feature = "dag-cbor")] - pub use crate::codecs_::dag_cbor::DagCbor; - #[cfg(feature = "dag-json")] - pub use crate::codecs_::dag_json::DagJson; - pub use crate::multicodec::{Codec, Multicodec}; + codecs_::*, - // multiformats - pub use multibase::Base as Multibase; - #[doc(hidden)] - pub use multihash::{Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}; - pub use multihash_::Multihash; + // data model, schemas and representations + data_model::*, + ipld_macros::{ + ipld_attr, + schema, + // selector + Representation, + // Select, Patch + }, - // cid - pub use crate::cid_::Cid; - #[doc(hidden)] - pub use cid::{Cid as DefaultCid, CidGeneric, Version}; + // multiformats + // multiaddr::Multiaddr, + multibase::{self, Base as Multibase}, + multicodec::Multicodec, + multihash::{self, Hasher as _, Multihash as DefaultMultihash, MultihashDigest as _}, + multihash_::Multihasher, - // data model, schemas and representations - pub use crate::data_model::*; - #[doc(hidden)] - pub use crate::representation::TypedKind as _; - pub use crate::representation::{strategies::Strategy, Kind, Representation}; - pub use ipld_macros::{ipld_attr, schema}; + // representations + representation::{Kind, Representation, Strategy}, // selectors - pub use crate::select::{Context, Params, Select, Selector}; - // pub use ipld_macros::selector; -} + select::{Context, Params, Select, Selector}, +}; -/// All the exports and re-exports necessary for using `ipld`. -pub mod prelude { - #[doc(hidden)] - pub use crate::representation::strategies::*; - #[doc(inline)] - pub use crate::{codecs_::LinkVisitor, specs::*, Error}; - #[doc(hidden)] - pub use serde::{Deserialize, Deserializer, Serialize, Serializer}; +/// Useful macros for implementing IPLD traits. +mod macros { + pub use crate::repr_serde; + // pub use derive_builder::Builder; + // pub use const_format::*; + pub use ipld_macros_internals::dev::*; } /// All exports from `ipld::prelude`, plus re-exports of first- and third-party /// dependencies to aid developers wanting to implement or extend `ipld` behaviour. #[cfg_attr(not(feature = "dev"), doc(hidden))] pub mod dev { - #[doc(hidden)] pub use crate::maybestd; - pub use crate::{prelude::*, representation::*, select::*}; + pub use crate::{cid_::*, macros::*, representation::*, select::*, *}; // dependency re-exports for macro convenience #[doc(hidden)] pub use anyhow; #[doc(hidden)] pub use bytes; - /// Useful macros for aiding in providing bespoke IPLD support. - pub mod macros { - pub use crate::repr_serde; - // pub use const_format::*; - pub use ipld_macros_internals::dev::*; - } - #[doc(hidden)] - pub use ipld_macros_internals::dev::typenum; - #[doc(hidden)] - pub use ipld_macros_internals::dev::typenum_macro; #[doc(hidden)] pub use serde::{ self, de::{ - self, DeserializeOwned, DeserializeSeed, EnumAccess, Error as _, IgnoredAny, - IntoDeserializer as _, MapAccess, SeqAccess, VariantAccess, Visitor, + self, DeserializeOwned, DeserializeSeed, Deserializer, EnumAccess, Error as _, + IgnoredAny, IntoDeserializer as _, MapAccess, SeqAccess, VariantAccess, Visitor, }, - ser::{self, Error as _}, + ser::{self, Error as _, Serializer}, + Deserialize, Serialize, }; } @@ -116,22 +106,19 @@ pub mod dev { #[cfg(not(feature = "std"))] #[doc(hidden)] pub mod maybestd { + #[cfg(feature = "alloc")] extern crate alloc; - + #[cfg(feature = "alloc")] pub use alloc::{boxed, collections, rc, vec}; - pub use core::{ - borrow, cell, cmp, convert, fmt, hash, iter, marker, num, ops, primitive, str, string, sync, - }; + + pub use core::{error as _, io as _, *}; pub use core2::{error, io}; + // todo: replace this pub use std::path; } #[cfg(feature = "std")] #[doc(hidden)] pub mod maybestd { pub use core2::{error, io}; - pub use std::path; - pub use std::{ - borrow, boxed, cell, cmp, collections, convert, fmt, hash, iter, marker, num, ops, - primitive, rc, str, string, sync, vec, - }; + pub use std::{error as _, io as _, *}; } diff --git a/src/multicodec.rs b/src/multicodec.rs index ece497a..f4e7b13 100644 --- a/src/multicodec.rs +++ b/src/multicodec.rs @@ -1,3 +1,4 @@ +use super::Codec; use crate::dev::*; use maybestd::{ convert::TryFrom, @@ -6,47 +7,6 @@ use maybestd::{ pub use multicodec::Multicodec; -/// An unified trait for all IPLD -/// [Codec](https://github.com/ipld/specs/blob/master/block-layer/codecs/README.dsmd)s, -/// providing methods for reading and writing blocks. -pub trait Codec: TryFrom { - /// The standardized [`Multicodec`] name for this IPLD codec. - const NAME: &'static str; - - /// The standardized [`Multicodec`] code that identifies this IPLD codec. - const CODE: u64; - - /// Given a dag, serialize it to a `Vec`. - fn encode(&mut self, dag: &T) -> Result, Error> - where - T: Representation, - { - let mut vec = vec![]; - self.write(dag, &mut vec)?; - Ok(vec) - } - - /// Given a dag and a `Write`, encode it to the writer. - fn write(&mut self, dag: &T, writer: W) -> Result<(), Error> - where - T: Representation, - W: Write; - - /// Given some bytes, deserialize a dag. - fn decode<'de, T>(&mut self, bytes: &'de [u8]) -> Result - where - T: Representation, - { - self.read::(bytes) - } - - /// Given a `Read`, deserialize a dag. - fn read(&mut self, reader: R) -> Result - where - T: Representation, - R: Read; -} - mod multicodec { use super::*; @@ -54,26 +14,34 @@ mod multicodec { ($( #[cfg(feature = $feature:expr)] $(#[$meta:meta])* - $variant:ident -> $ty:ty, + $path:path => $variant:ident $code_name:ident, )*) => { /// A generic [multicodec]() enum. - #[derive(Clone, Debug)] + #[derive(Debug)] #[non_exhaustive] pub enum Multicodec { $( #[cfg(feature = $feature)] $(#[$meta])* - $variant($ty), + $variant($path), )* } impl Multicodec { + $( + #[doc = "[Multicodec]() code for the `"] + #[doc = stringify!($variant)] + #[doc = "` codec."] + pub const $code_name: u64 = <$path as Codec>::CODE; + )* + + /// #[inline] - pub const fn is_known() -> bool { - match C { + pub const fn is_known() -> bool { + match MC { $( #[cfg(feature = $feature)] - <$ty>::CODE => true, + <$path as Codec>::CODE => true, )* _ => false, } @@ -85,7 +53,7 @@ mod multicodec { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$ty>::NAME, + Self::$variant(_) => <$path as Codec>::NAME, )* // _ => unimplemented!() } @@ -97,7 +65,7 @@ mod multicodec { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$ty>::CODE, + Self::$variant(_) => <$path as Codec>::CODE, )* // _ => unimplemented!() } @@ -109,7 +77,7 @@ mod multicodec { match name { $( #[cfg(feature = $feature)] - <$ty>::NAME => Ok(Self::$variant(<$ty>::new())), + <$path as Codec>::NAME => Ok(Self::$variant(<$path>::new())), )* name => Err(Error::UnknownMulticodecName(name.to_string())) } @@ -117,11 +85,11 @@ mod multicodec { /// #[inline] - pub const fn from_code() -> Result { - match C { + pub const fn from_code() -> Result { + match MC { $( #[cfg(feature = $feature)] - <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), + <$path as Codec>::CODE => Ok(Self::$variant(<$path>::new())), )* code => Err(Error::UnknownMulticodecCode(code)) } @@ -199,105 +167,10 @@ mod multicodec { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$ty>::read_with_seed(seed, reader), + Self::$variant(_) => <$path>::read_with_seed(seed, reader), )* } } - - #[inline] - #[doc(hidden)] - pub fn serialize_bytes( - dag: impl AsRef<[u8]>, - serializer: S, - ) -> Result - where - S: Serializer, - { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::serialize_bytes(dag, serializer); - } - serializer.serialize_bytes(dag.as_ref()) - } - - #[inline] - #[doc(hidden)] - pub fn serialize_link( - cid: &Cid, - serializer: S, - ) -> Result - where - S: Serializer, - { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::serialize_link(cid, serializer); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::serialize_link(cid, serializer); - } - Serialize::serialize(&cid.inner, serializer) - } - - #[inline] - #[doc(hidden)] - pub fn deserialize_any<'de, const C: u64, D, V>( - deserializer: D, - visitor: V, - ) -> Result - where - D: Deserializer<'de>, - V: LinkVisitor<'de>, - { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_any(deserializer, visitor); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::deserialize_any(deserializer, visitor); - } - deserializer.deserialize_any(visitor) - } - - #[inline] - #[doc(hidden)] - pub fn deserialize_bytes<'de, const C: u64, D, V>( - deserializer: D, - visitor: V, - ) -> Result - where - D: Deserializer<'de>, - V: LinkVisitor<'de>, - { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_bytes(deserializer, visitor); - } - deserializer.deserialize_bytes(visitor) - } - - #[inline] - #[doc(hidden)] - pub fn deserialize_link<'de, const C: u64, D, V>( - deserializer: D, - visitor: V, - ) -> Result - where - D: Deserializer<'de>, - V: LinkVisitor<'de>, - { - #[cfg(feature = "dag-json")] - if C == DagJson::CODE { - return DagJson::deserialize_link(deserializer, visitor); - } - #[cfg(feature = "dag-cbor")] - if C == DagCbor::CODE { - return DagCbor::deserialize_link(deserializer, visitor); - } - deserializer.deserialize_any(visitor) - } } impl TryFrom for Multicodec { @@ -307,7 +180,7 @@ mod multicodec { match code { $( #[cfg(feature = $feature)] - <$ty>::CODE => Ok(Self::$variant(<$ty>::new())), + <$path as Codec>::CODE => Ok(Self::$variant(<$path>::new())), )* _ => Err(Error::UnknownMulticodecCode(code)), } @@ -321,7 +194,7 @@ mod multicodec { match s { $( #[cfg(feature = $feature)] - <$ty>::NAME => Ok(Self::$variant(<$ty>::new())), + <$path as Codec>::NAME => Ok(Self::$variant(<$path>::new())), )* _ => Err(Error::UnknownMulticodecName(s.into())), } @@ -332,13 +205,110 @@ mod multicodec { impl_multicodec! { #[cfg(feature = "dag-cbor")] /// - DagCbor -> DagCbor, + crate::DagCbor => DagCbor DAG_CBOR, #[cfg(feature = "dag-json")] /// - DagJson -> DagJson, + crate::DagJson => DagJson DAG_JSON, + // #[cfg(feature = "dag-rkyv")] + // /// + // DagRkyv DAG_RKYV, // Custom(Box), } + impl Multicodec { + #[inline] + #[doc(hidden)] + pub fn serialize_bytes( + dag: impl AsRef<[u8]>, + serializer: S, + ) -> Result + where + S: Serializer, + { + #[cfg(feature = "dag-json")] + if MC == ::CODE { + return crate::DagJson::serialize_bytes(dag, serializer); + } + serializer.serialize_bytes(dag.as_ref()) + } + + #[inline] + #[doc(hidden)] + pub fn serialize_link(cid: &Cid, serializer: S) -> Result + where + S: Serializer, + { + #[cfg(feature = "dag-cbor")] + if MC == ::CODE { + return crate::DagCbor::serialize_link(cid, serializer); + } + #[cfg(feature = "dag-json")] + if MC == ::CODE { + return crate::DagJson::serialize_link(cid, serializer); + } + Serialize::serialize(&cid.inner, serializer) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_any<'de, const MC: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de, MC>, + { + #[cfg(feature = "dag-cbor")] + if MC == ::CODE { + return crate::DagCbor::deserialize_any(deserializer, visitor); + } + #[cfg(feature = "dag-json")] + if MC == ::CODE { + return crate::DagJson::deserialize_any(deserializer, visitor); + } + deserializer.deserialize_any(visitor) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_bytes<'de, const MC: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de, MC>, + { + #[cfg(feature = "dag-json")] + if MC == ::CODE { + return crate::DagJson::deserialize_bytes(deserializer, visitor); + } + deserializer.deserialize_bytes(visitor) + } + + #[inline] + #[doc(hidden)] + pub fn deserialize_link<'de, const MC: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de, MC>, + { + #[cfg(feature = "dag-cbor")] + if MC == ::CODE { + return crate::DagCbor::deserialize_link(deserializer, visitor); + } + #[cfg(feature = "dag-json")] + if MC == ::CODE { + return crate::DagJson::deserialize_link(deserializer, visitor); + } + deserializer.deserialize_any(visitor) + } + } + impl<'a, const S: usize> TryFrom<&'a CidGeneric> for Multicodec { type Error = Error; fn try_from(cid: &CidGeneric) -> Result { @@ -432,7 +402,7 @@ mod autoref { assert!(false) } - trait Tag {} + trait Tag {} trait ViaDagJson { type Ok; @@ -509,7 +479,7 @@ mod tagged { } } - trait Tag {} + trait Tag {} struct Encoder(S); @@ -657,11 +627,14 @@ mod autoref2 { // if > } } - trait SerdeCodec: Serializer {} - // impl SerdeCodec for S {} - impl SerdeCodec<{ DagJson::CODE }> for &mut serde_json::Serializer {} + trait SerdeCodec: Serializer {} + // impl SerdeCodec for S {} + impl SerdeCodec<{ ::CODE }> + for &mut serde_json::Serializer + { + } - // trait SerdeCodec: Serializer {} + // trait SerdeCodec: Serializer {} // Requires one extra autoref to call! Lower priority than XXXEncoderKind. trait GenericEncoderKind { @@ -825,10 +798,10 @@ mod specialize { } } - trait SerdeCodec: Serializer { - const CODE: Option = if F { Some(C) } else { None }; + trait SerdeCodec: Serializer { + const CODE: Option = if F { Some(MC) } else { None }; } - impl SerdeCodec for S {} + impl SerdeCodec for S {} impl SerdeCodec for &mut serde_json::Serializer {} // struct Encoder(S); @@ -959,7 +932,7 @@ mod autoref3 { assert!(false) } - trait Tag: Serializer {} + trait Tag: Serializer {} impl<'a, W: std::io::Write> Tag<{ DagJson::CODE }> for &'a mut serde_json::Serializer {} trait ViaDagJson { diff --git a/src/multihash.rs b/src/multihash.rs index 79a9d5b..73cfa80 100644 --- a/src/multihash.rs +++ b/src/multihash.rs @@ -3,6 +3,8 @@ use macros::derive_more::From; use maybestd::io; use multihash::Hasher; +pub type Code = u64; + macro_rules! impl_multihasher { (@multihash $( $(#[$meta:meta])* @@ -11,22 +13,22 @@ macro_rules! impl_multihasher { /// A generic [multihash]()-er enum. #[derive(Debug, From)] #[non_exhaustive] - pub enum Multihash { + pub enum Multihasher { $( $(#[$meta])* $variant($ty), )* } - impl Multihash { + impl Multihasher { $( /// - pub const $const: u64 = $code; + pub const $const: Code = $code; )* /// #[inline] - pub fn from_code() -> Result { + pub fn from_code() -> Result { Ok(match C { $($code => Ok(Self::$variant(<$ty>::default())),)* code => Err(multihash::Error::UnsupportedCode(code)) @@ -35,7 +37,7 @@ macro_rules! impl_multihasher { /// #[inline] - pub const fn is_supported() -> bool { + pub const fn is_supported() -> bool { match C { $($code => true,)* _ => false, @@ -44,7 +46,7 @@ macro_rules! impl_multihasher { /// #[inline] - pub const fn code(&self) -> u64 { + pub const fn code(&self) -> Code { match self { $(Self::$variant(_) => $code,)* } @@ -67,6 +69,7 @@ macro_rules! impl_multihasher { } /// + #[inline] pub fn try_finalize(&mut self) -> Result { let mh = DefaultMultihash::wrap(self.code(), multihash::Hasher::finalize(self))?; self.reset(); @@ -74,7 +77,7 @@ macro_rules! impl_multihasher { } } - impl multihash::Hasher for Multihash { + impl multihash::Hasher for Multihasher { #[inline] fn update(&mut self, input: &[u8]) { match self { @@ -95,7 +98,7 @@ macro_rules! impl_multihasher { } } - impl io::Write for Multihash { + impl io::Write for Multihasher { fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf); Ok(buf.len()) @@ -111,11 +114,11 @@ macro_rules! impl_multihasher { // use super::*; // use digest::{Digest, OutputSizeUser, FixedOutputReset, generic_array::{typenum::U64, GenericArray}}; // - // impl OutputSizeUser for Multihash { + // impl OutputSizeUser for Multihasher { // type OutputSize = GenericArray; // } // - // impl Multihash { + // impl Multihasher { // const OUTPUT_SIZE: usize = U64::USIZE; // // fn finalize_to_digest(&mut self, digest: &mut Output) { @@ -123,7 +126,7 @@ macro_rules! impl_multihasher { // } // } // - // impl Digest for Multihash { + // impl Digest for Multihasher { // fn new() -> Self { // unimplemented!() // } @@ -176,9 +179,9 @@ macro_rules! impl_multihasher { // } // }; - impl TryFrom for Multihash { + impl TryFrom for Multihasher { type Error = Error; - fn try_from(multihash_code: u64) -> Result { + fn try_from(multihash_code: Code) -> Result { Ok(match multihash_code { $($code => Ok(Self::$variant(<$ty>::default())),)* mh_code => Err(multihash::Error::UnsupportedCode(mh_code)) @@ -235,3 +238,41 @@ impl_multihasher! {@multihash Blake3_256 (BLAKE3_256: "blake3": 0x1e) -> multihash::Blake3Hasher::<32> [32], } + +// impl Default for Multihasher { +// fn default() -> Self { +// Self:: +// } +// } + +impl Representation for DefaultMultihash { + const NAME: &'static str = "Multihash"; + const SCHEMA: &'static str = "type Multihash bytes"; + const DATA_MODEL_KIND: Kind = Kind::Bytes; + const SCHEMA_KIND: Kind = Kind::Bytes; + const REPR_KIND: Kind = Kind::Bytes; + + fn to_selected_node(&self) -> SelectedNode { + SelectedNode::Bytes(self.to_bytes().into()) + } + + /// + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // TODO: bytes / base58 str + unimplemented!() + } + + /// + #[inline] + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // TODO: bytes / base58 str + unimplemented!() + } +} diff --git a/src/representation/mod.rs b/src/representation/mod.rs index 60bedc9..a5f00a5 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -10,26 +10,25 @@ //! defining for the type it's `Context` requirements for these operations. #[doc(hidden)] -pub mod strategies; +mod strategies; use crate::dev::*; use downcast_rs::{impl_downcast, Downcast}; use macros::derive_more::From; use maybestd::{fmt, marker::PhantomData, str::FromStr}; -pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKind}; +pub use ipld_macros_internals::schema::SchemaKind as Kind; +#[doc(hidden)] +pub use strategies::*; // /// // #[derive(Debug, Eq, Hash, PartialEq)] -// pub struct Field { +// pub struct Field { // /// Name of the `Representation` type contained within this field. // pub type_name: &'static str, // // /// `Representation::Kind` of the field type. -// pub value: Kind, -// -// /// The serialized field name of this type. -// pub alias: A, +// pub ty: PhantomData // } // // impl Field { @@ -46,7 +45,7 @@ pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKin // #[derive(Debug, Eq, Hash, PartialEq)] // pub enum Fields { // None, -// List(Field<()>), +// List, // Map { // key: Field<()>, // value: Field<()>, @@ -70,18 +69,6 @@ pub use ipld_macros_internals::schema::{type_kinds, SchemaKind as Kind, TypedKin // Byteprefix(&'static [Field<&'static [u8; 1]>]), // } -// trait IsAny {} -// impl IsAny<{ Kind::Any.bits() }> for Kind {} -// impl IsAny<{ Kind::Null.bits() }> for Kind {} -// impl IsAny<{ Kind::Bool.bits() }> for Kind {} -// impl IsAny<{ Kind::Int.bits() }> for Kind {} -// impl IsAny<{ Kind::Float.bits() }> for Kind {} -// impl IsAny<{ Kind::String.bits() }> for Kind {} -// impl IsAny<{ Kind::Bytes.bits() }> for Kind {} -// impl IsAny<{ Kind::List.bits() }> for Kind {} -// impl IsAny<{ Kind::Map.bits() }> for Kind {} -// impl IsAny<{ Kind::Link.bits() }> for Kind {} - #[doc(hidden)] pub struct Label { label: Field<'static>, @@ -108,80 +95,66 @@ pub trait Representation: Sized { /// The IPLD [Data Model Kind](https://ipld.io/docs/data-model/kinds/) of /// the type, which denotes the access API and executable [`Selector`]s. - const DATA_MODEL_KIND: Kind = Self::DataModelKind::KIND; + const DATA_MODEL_KIND: Kind; /// The IPLD [Schema Kind](https://ipld.io/docs/schemas/features/typekinds/) /// of the type, which denotes how the type is defined by its schema. - const SCHEMA_KIND: Kind = Self::SchemaKind::KIND; + const SCHEMA_KIND: Kind = Self::DATA_MODEL_KIND; /// The IPLD [Representation Kind]() of the type, which, in combination with /// the [`Representation::REPR_STRATEGY`], denotes how the type is /// represented on-disk by any given codec. - const REPR_KIND: Kind = Self::ReprKind::KIND; + const REPR_KIND: Kind = Self::DATA_MODEL_KIND; /// The IPLD specific [Representation]() [`Strategy`] used to encode this /// type. - const REPR_STRATEGY: Strategy = Strategy::DataModel; + const REPR_STRATEGY: Strategy = Strategy::Basic; - /// Marker for types that can have any representation *and* should be - /// ignored entirely during selection/deserialization. - #[doc(hidden)] - const __IGNORED: bool = false; - - /// Marker type for exact `u32` value of the type's - /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket - /// implementations of various traits. - #[doc(hidden)] - type DataModelKind: TypedKind; + /// Whether or not the type contains IPLD links. + const HAS_LINKS: bool = Self::DATA_MODEL_KIND.contains(Kind::Link); - /// Marker type for exact `u32` value of the type's - /// [`Representation::SCHEMA_KIND`], needed for internal blanket - /// implementations of various traits. - #[doc(hidden)] - type SchemaKind: TypedKind; - - /// Marker type for exact `u32` value of the type's - /// [`Representation::REPR_KIND`], needed for internal blanket - /// implementations of various traits. - #[doc(hidden)] - type ReprKind: TypedKind; + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::DATA_MODEL_KIND`], needed for internal blanket + // /// implementations of various traits. + // #[doc(hidden)] + // type DataModelKind: TypedKind; - /// - /// todo deprecate - const IS_LINK: bool = Self::DATA_MODEL_KIND.is_link(); + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::SCHEMA_KIND`], needed for internal blanket + // /// implementations of various traits. + // #[doc(hidden)] + // type SchemaKind: TypedKind; - /// todo deprecate - const HAS_LINKS: bool = Self::IS_LINK; + // /// Marker type for exact `u32` value of the type's + // /// [`Representation::REPR_KIND`], needed for internal blanket + // /// implementations of various traits. + // #[doc(hidden)] + // type ReprKind: TypedKind; /// The type's `Select`able static field names and their IPLD Schema kinds. #[doc(hidden)] const FIELDS: &'static [&'static str] = &[]; /// - /// for unions, this ?should delegate to the variant's type name' - /// TODO what is this really for - fn name(&self) -> &'static str { - Self::NAME - } - - /// - fn data_model_kind(&self) -> Kind { - Self::DATA_MODEL_KIND - } - - /// - fn schema_kind(&self) -> Kind { - Self::SCHEMA_KIND - } + #[doc(hidden)] + const __SERDE_SCHEMA_KIND: Kind = match Self::SCHEMA_KIND.is_copy() { + Some(raw_sk) => raw_sk, + None => Self::SCHEMA_KIND, + }; /// - fn repr_kind(&self) -> Kind { - Self::REPR_KIND - } + #[doc(hidden)] + const __SERDE_REPR_KIND: Kind = match Self::REPR_KIND { + Kind::Int => Int::REPR_KIND, + Kind::Float => Float::REPR_KIND, + rk => rk, + }; /// - fn is_link(&self) -> bool { - Self::IS_LINK + /// ? The name of the reified type? + /// for unions, this ?should delegate to the variant's type name' + fn name(&self) -> &'static str { + Self::NAME } /// @@ -194,6 +167,7 @@ pub trait Representation: Sized { None } + /// fn to_selected_node(&self) -> SelectedNode { unimplemented!() } @@ -207,7 +181,7 @@ pub trait Representation: Sized { /// TODO: rename to encode? as in, just encode this type (up to links) #[inline] #[doc(hidden)] - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, serializer: S) -> Result where S: Serializer, { @@ -224,14 +198,39 @@ pub trait Representation: Sized { /// TODO: rename to decode? as in, just decode this type (up to links) #[inline] #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { // >::deserialize(deserializer) + // ::__select_de::(EmptySeed, deserializer) + + // deserialize_with_visitor::( + // deserializer, + // Self::Walker::<'de, '_, MC>::default(), + // ) + unimplemented!() } + // AstWalk<'a, Ctx, Self> + // /// + // #[doc(hidden)] + // type Walker<'de, 'a: 'de, const MC: u64>: Walk<'de, 'a, MC, Self>; + + #[inline] + #[doc(hidden)] + fn deserialize_with_visitor<'de, const MC: u64, D, V>( + deserializer: D, + visitor: V, + ) -> Result + where + D: Deserializer<'de>, + V: LinkVisitor<'de, MC>, + { + deserialize_with_visitor::(deserializer, visitor) + } + // /// // #[inline] // #[doc(hidden)] @@ -324,22 +323,86 @@ pub trait Representation: Sized { // fn links(c: Codec, reader: &mut R, ) } +#[inline] +#[doc(hidden)] +fn deserialize_with_visitor<'de, const MC: u64, D, V, T>( + deserializer: D, + visitor: V, +) -> Result +where + D: Deserializer<'de>, + V: LinkVisitor<'de, MC>, + T: Representation, +{ + match (T::__SERDE_SCHEMA_KIND, T::__SERDE_REPR_KIND) { + _ if T::REPR_STRATEGY.is_ignored() => deserializer.deserialize_ignored_any(visitor), + _ if T::DATA_MODEL_KIND.is_option() => deserializer.deserialize_option(visitor), + + // union keyed (ref), envelope (tag + ref), inline (tag + inline) + (Kind::Union, Kind::Map) => deserializer.deserialize_enum(T::NAME, T::FIELDS, visitor), + // union (kinded => any, stringprefix => str, bytesprefix => bytes) + + // struct map + (Kind::Struct, Kind::Map) => deserializer.deserialize_struct(T::NAME, T::FIELDS, visitor), + // struct tuple, listpairs + (Kind::Struct, Kind::List) => { + deserializer.deserialize_tuple_struct(T::NAME, T::FIELDS.len(), visitor) + } + // structs stringpair, stringjoin => Kind::String + + // enum + (Kind::Enum, _) => deserializer.deserialize_identifier(visitor), + + // basic + (_, Kind::Null) => deserializer.deserialize_unit(visitor), + (_, Kind::Bool) => deserializer.deserialize_bool(visitor), + (_, Kind::Int8) => deserializer.deserialize_i8(visitor), + (_, Kind::Int16) => deserializer.deserialize_i16(visitor), + (_, Kind::Int32) => deserializer.deserialize_i32(visitor), + (_, Kind::Int64) => deserializer.deserialize_i64(visitor), + (_, Kind::Int128) => deserializer.deserialize_i128(visitor), + (_, Kind::Uint8) => deserializer.deserialize_u8(visitor), + (_, Kind::Uint16) => deserializer.deserialize_u16(visitor), + (_, Kind::Uint32) => deserializer.deserialize_u32(visitor), + (_, Kind::Uint64) => deserializer.deserialize_u64(visitor), + (_, Kind::Uint128) => deserializer.deserialize_u128(visitor), + (_, Kind::Float32) => deserializer.deserialize_f32(visitor), + (_, Kind::Float64) => deserializer.deserialize_f64(visitor), + (_, Kind::String) => deserializer.deserialize_str(visitor), + (_, Kind::Bytes) => Multicodec::deserialize_bytes::(deserializer, visitor), + (_, Kind::List) => deserializer.deserialize_seq(visitor), + (_, Kind::Map) => deserializer.deserialize_map(visitor), + (_, Kind::Link) => Multicodec::deserialize_link::(deserializer, visitor), + // anything else + _ => Multicodec::deserialize_any::(deserializer, visitor), + } +} + /// -pub trait StringRepresentation: Representation +pub trait StringRepresentation where + // Self: Representation, + Self: Representation, Self: Clone + FromStr + fmt::Display + Ord, ::Err: fmt::Display, { } impl StringRepresentation for T where - T: Representation + Clone + FromStr + fmt::Display + Ord, + // T: Representation, + Self: Representation, + T: Clone + FromStr + fmt::Display + Ord, ::Err: fmt::Display, { } /// -pub trait BytesRepresentation: Representation {} +pub trait BytesRepresentation +where + // Self: Representation + Self: Representation, +{ +} /// pub trait AdvancedRepresentation: Representation + Select {} @@ -353,15 +416,6 @@ pub(crate) trait ErasedRepresentation: Downcast { /// fn name(&self) -> &'static str; - /// - fn data_model_kind(&self) -> Kind; - - /// - fn schema_kind(&self) -> Kind; - - /// - fn repr_kind(&self) -> Kind; - /// fn has_links(&self) -> bool; } @@ -375,23 +429,11 @@ where T: Representation + 'static, { fn name(&self) -> &'static str { - T::NAME - } - - fn data_model_kind(&self) -> Kind { - T::DATA_MODEL_KIND - } - - fn schema_kind(&self) -> Kind { - T::SCHEMA_KIND - } - - fn repr_kind(&self) -> Kind { - T::REPR_KIND + Representation::name(self) } fn has_links(&self) -> bool { - T::HAS_LINKS + Representation::has_links(self) } } @@ -598,21 +640,21 @@ pub(crate) fn type_cast_mut(inner: } */ -/// Helper fn for constraining and safely transmuting a generic selection output -pub(crate) fn type_cast_selection( - inner: F, -) -> Result, E> -where - F: FnOnce() -> Result, E>, -{ - // if !type_eq::() { - // unreachable!("should only do this for types known to be identical") - // } - - let mut inner = inner()?; - let outer = (&mut inner as &mut dyn std::any::Any) - .downcast_mut::>() - .unwrap() - .take(); - Ok(outer) -} +// /// Helper fn for constraining and safely transmuting a generic selection output +// pub(crate) fn type_cast_selection( +// inner: F, +// ) -> Result, E> +// where +// F: FnOnce() -> Result, E>, +// { +// // if !type_eq::() { +// // unreachable!("should only do this for types known to be identical") +// // } +// +// let mut inner = inner()?; +// let outer = (&mut inner as &mut dyn std::any::Any) +// .downcast_mut::>() +// .unwrap() +// .take(); +// Ok(outer) +// } diff --git a/src/representation/strategies/bytesprefix.rs b/src/representation/strategies/bytesprefix.rs index 8770d6e..78aaeb8 100644 --- a/src/representation/strategies/bytesprefix.rs +++ b/src/representation/strategies/bytesprefix.rs @@ -1,3 +1,3 @@ use crate::dev::*; -const STRATEGY: Strategy = Strategy::BytesPrefix; +const STRATEGY: Strategy = Strategy::Bytesprefix; diff --git a/src/representation/strategies/listpairs.rs b/src/representation/strategies/listpairs.rs index 987eea6..ba4fccc 100644 --- a/src/representation/strategies/listpairs.rs +++ b/src/representation/strategies/listpairs.rs @@ -5,7 +5,7 @@ use macros::{ }; use maybestd::{fmt, marker::PhantomData, str::FromStr}; -const STRATEGY: Strategy = Strategy::ListPairs; +const STRATEGY: Strategy = Strategy::Listpairs; /* // Blanket impl for maps. @@ -62,230 +62,258 @@ repr_serde! { @visitors for T => (K, V) }} */ -// /// -// #[derive( -// AsRef, -// AsMut, -// Clone, -// Debug, -// Deref, -// // DerefMut, -// Eq, -// Hash, -// Index, -// IndexMut, -// IntoIterator, -// Ord, -// PartialEq, -// PartialOrd, -// )] -// #[as_ref(forward)] -// #[deref(forward)] -// pub struct ListPairsMap(Map); - -// impl Default for ListPairsMap { -// fn default() -> Self { -// Self(Map::new()) -// } -// } - -// type ListPair = StructTuple2<(K, V), K, V>; -// type ListPairRef<'a, K, V> = StructTupleRef2<'a, (K, V), K, V>; - -// impl Representation for ListPairsMap -// where -// // TODO: remove clone requirement by switching up callbacks -// K: Representation + AsRef + Clone + Ord, -// V: Representation, -// { -// type ReprKind = type_kinds::List; - -// const NAME: &'static str = "Map"; -// const SCHEMA: &'static str = concat!( -// "type Map {", -// stringify!(K::NAME), -// ":", -// stringify!(V::NAME), -// "} representation listpairs", -// ); -// const DATA_MODEL_KIND: Kind = Kind::Map; -// // const REPR_KIND: Kind = Kind::List; - -// fn has_links(&self) -> bool { -// self.0.has_links() -// } - -// #[inline] -// #[doc(hidden)] -// fn serialize(&self, serializer: S) -> Result -// where -// S: Serializer, -// { -// use ser::SerializeSeq; - -// let mut seq = serializer.serialize_seq(Some(self.0.len()))?; -// for listpair in self.0.iter().map(ListPairRef::::from) { -// seq.serialize_element(&SerializeWrapper::<'_, C, _>(&listpair))?; -// } -// seq.end() -// } - -// #[inline] -// #[doc(hidden)] -// fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// struct ListPairsMapVisitor(PhantomData<(K, V)>); -// impl<'de, const C: u64, K, V> Visitor<'de> for ListPairsMapVisitor -// where -// K: Representation + Ord, -// V: Representation, -// { -// type Value = ListPairsMap; -// #[inline] -// fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// write!(f, "A map of `{}` to `{}` listpairs", K::NAME, V::NAME) -// } -// #[inline] -// fn visit_seq(self, mut seq: A) -> Result -// where -// A: SeqAccess<'de>, -// { -// let mut map = ListPairsMap::default(); -// while let Some(listpair) = -// seq.next_element_seed(DeserializeWrapper::>::new())? -// { -// map.0.insert(listpair.0, listpair.1); -// } -// Ok(map) - -// // let mut new_map = Map::new(); -// // let mut iter = SerdeListPairsIterator::<'de, A>::from(map); -// // while let Some(key) = -// // as MapIterator>::next_key::(&mut iter, None) -// // .map_err(A::Error::custom)? -// // { -// // let val = key -// // .as_field() -// // .ok_or_else(|| Error::explore_key_failure::(None)) -// // .and_then(|field| { -// // as MapIterator>::next_value::( -// // &mut iter, &field, -// // ) -// // }) -// // .map_err(A::Error::custom)?; -// // new_map.insert(key, val); -// // } -// // Ok(new_map) -// } -// } - -// deserializer.deserialize_seq(ListPairsMapVisitor::(PhantomData)) -// } -// } +/// +#[derive( + AsRef, + AsMut, + Clone, + Debug, + Deref, + // DerefMut, + Eq, + Hash, + Index, + IndexMut, + IntoIterator, + Ord, + PartialEq, + PartialOrd, +)] +#[as_ref(forward)] +#[deref(forward)] +pub struct ListpairsMap(Map) +where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation; + +impl Default for ListpairsMap +where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, +{ + fn default() -> Self { + Self(Map::new()) + } +} + +type ListpairRef<'a, K, V> = TupleRef2<'a, ListpairsMap, K, V>; + +impl Representation for ListpairsMap +where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, +{ + const NAME: &'static str = "Map"; + const SCHEMA: &'static str = concat!( + "type Map {", + stringify!(K::NAME), + ":", + stringify!(V::NAME), + "} representation listpairs", + ); + const DATA_MODEL_KIND: Kind = Kind::Map; + const SCHEMA_KIND: Kind = Kind::Map; + const REPR_KIND: Kind = Kind::List; + const REPR_STRATEGY: Strategy = Strategy::Listpairs; + + #[inline] + #[doc(hidden)] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use ser::SerializeSeq; + + let mut seq = serializer.serialize_seq(Some(self.0.len()))?; + for listpair in self.0.iter().map(ListpairRef::<'_, K, V>::from) { + seq.serialize_element(&SerializeRepr::<'_, C, _>(&listpair))?; + } + seq.end() + } + + #[inline] + #[doc(hidden)] + fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ListpairsMapVisitor(PhantomData<(K, V)>); + impl<'de, const C: u64, K, V> Visitor<'de> for ListpairsMapVisitor + where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, + { + type Value = ListpairsMap; + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A map of `{}` to `{}` listpairs", K::NAME, V::NAME) + } + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut map = ListpairsMap::default(); + while let Some((key, val)) = + seq.next_element_seed(DeserializeRepr::::new())? + { + map.0.insert(key, val); + } + Ok(map) + } + } + + deserializer.deserialize_seq(ListpairsMapVisitor::(PhantomData)) + } +} + +repr_serde! { @select for ListpairsMap + { K, V } { K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } +} +repr_serde! { @visitors for ListpairsMap + { K, V } { K: Select + StringRepresentation + 'static, + ::Err: fmt::Display, + V: Select + 'static } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A map of type {} of {} to {}", >::NAME, K::NAME, V::NAME) + } + #[inline] + fn visit_seq(self, seq: A) -> Result + where + A: SeqAccess<'de>, + { + /* + if let Some(s) = self.as_ref().selector.as_explore_union() { + if s.matches_first() { + // TODO: transform the seed to a phantom seed, then recurse + let map = >::deserialize::(SeqAccessDeserializer::new(map))?; + return map.__select_in(self.into_inner()).map_err(A::Error::custom); + } + } + + self.into_inner() + .select_map::(SerdeMapIterator::from(map)) + .map_err(A::Error::custom) + match self.as_ref().selector { + Selector::Matcher(_) => { + self.into_inner().match_map::( + iter, + |_| RefCell::default(), + |key, dag| Box::new(|child, _| { + dag.borrow_mut().extend(iter::once((key.clone(), child))); + Ok(()) + }), + RefCell::into_inner, + ).map_err(A::Error::custom) + }, + Selector::ExploreFields(_) => self.into_inner() + .explore_map_fields::(iter) + .map_err(A::Error::custom), + Selector::ExploreAll(_) => self.into_inner() + .explore_map_fields::(iter) + .map_err(A::Error::custom), + _ => Err(A::Error::custom(Error::unsupported_selector::>( + self.as_ref().selector, + ))), + } + */ + + unimplemented!() + } +}} mod iterators { use super::*; use de::value::SeqAccessDeserializer; - // /// An iterator over a key-value pair represented as a serde list. - // #[derive(Debug)] - // pub struct SerdeListPairIterator<'de, A> - // where - // A: SeqAccess<'de>, - // { - // inner: A, - // _t: PhantomData<&'de ()>, - // } - - // impl<'de, T, A> ListIterator for SerdeListPairIterator<'de, A> where A: SeqAccess<'de> {} - /// #[doc(hidden)] - #[derive(Debug)] - pub struct SerdeListPairsIterator<'de, A> + // #[derive(Debug)] + pub struct SerdeListpairsIterator<'de, A> where A: SeqAccess<'de>, { inner: A, + index: usize, // key: Option>, - // pair_de: Option>, + // value_de: Option>>, _t: PhantomData<&'de ()>, } - impl<'de, A> From for SerdeListPairsIterator<'de, A> + impl<'de, A> SerdeListpairsIterator<'de, A> where A: SeqAccess<'de>, { - fn from(inner: A) -> Self { + pub fn new(inner: A) -> Self { Self { inner, + index: 0, // key: None, - // pair_de: None, + // value_de: None, _t: PhantomData, } } } - impl<'de, K, V, A> MapIterator for SerdeListPairsIterator<'de, A> + /// + /// call to next_key: + /// - next_element -> (key(_str), Box) + /// call to next_value: + /// - creates Visitor.visit_seq that plucks one V from the seq + /// - value_de.deserialize_seq -> + impl<'de, K, V, A> MapIterator for SerdeListpairsIterator<'de, A> where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, A: SeqAccess<'de>, { fn size_hint(&self) -> Option { self.inner.size_hint() } - fn field(&self) -> Field<'_> { - unimplemented!() - } - /// - /// pass a visitor that deserializes the key, and if the field_name matches, deserializes the value + /// if name is provided fn next_key( &mut self, expected_field_name: Option<&'static str>, - ) -> Result, Error> - where - K: Representation, - { - // let key = self - // .inner - // .next_key_seed(DeserializeWrapper::::default()) - // .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; - - // // TODO: assert that key == expected_field_name - // Ok(key) + ) -> Result, Error> { unimplemented!() } fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { - // self.inner - // .next_value::() - // .or_else(|_| Err(Error::explore_value_failure::(field)))?; - // Ok(()) unimplemented!() } - fn next_value(&mut self, field: &Field<'_>) -> Result + fn next_value_seed<'a, const C: u64, Ctx: Context>( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + // field: &Field<'_>, + ) -> Result<(), Error> where - V: Representation, + V: Select, { - // self.inner - // .next_value_seed(DeserializeWrapper::::default()) - // .or_else(|_| Err(Error::explore_value_failure::(field))) unimplemented!() } - fn next_value_seed<'a, const C: u64, Ctx: Context>( + fn next_entry_seed<'a, const C: u64, Ctx: Context + 'a, F>( &mut self, - seed: SelectorSeed<'a, Ctx, V>, - // field: &Field<'_>, - ) -> Result<(), Error> + seeder: F, + ) -> Result where - K: Representation, V: Select, + F: FnOnce(&str) -> Result>, Error>, { + // + + unimplemented!() // let key = >::key(self); // let field = Representation::as_field(key); // let field = self.field(); @@ -295,9 +323,61 @@ mod iterators { // .ok() // .flatten() // .ok_or_else(|| Error::explore_value_failure::(field)) + } + } + + struct EntryVisitor { + expected_field_name: Option<&'static str>, + _t: PhantomData<(K, V)>, + } + impl EntryVisitor { + fn new(expected_field_name: Option<&'static str>) -> Self { + Self { + expected_field_name, + _t: PhantomData, + } + } + } + impl<'de, const C: u64, K, V> Visitor<'de> for EntryVisitor + where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, + { + // type Value = (K, Box>); + type Value = (); + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "A listpairs map key-value pair of {} to {}", + K::NAME, + V::NAME + ) + } + #[inline] + fn visit_seq(self, seq: A) -> Result + where + A: SeqAccess<'de>, + { unimplemented!() } } + impl<'de, const C: u64, K, V> DeserializeSeed<'de> for EntryVisitor + where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, + { + // type Value = (K, Box>); + type Value = (); + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_seq(self) + } + } } #[doc(hidden)] diff --git a/src/representation/strategies/mod.rs b/src/representation/strategies/mod.rs index 34f06f5..c2ebce0 100644 --- a/src/representation/strategies/mod.rs +++ b/src/representation/strategies/mod.rs @@ -11,133 +11,149 @@ mod tuple; pub use tuple::*; use crate::dev::*; -use maybestd::marker::PhantomData; +use maybestd::{fmt, str::FromStr}; /// +#[derive(Copy, Clone, Debug)] #[repr(u8)] pub enum Strategy { - DataModel = 'd' as u8, - BytesPrefix = 'b' as u8, + // map/struct + Listpairs = 'l' as u8, + Stringjoin = 'j' as u8, + Stringpairs = 'p' as u8, + Tuple = 't' as u8, + // union Envelope = 'e' as u8, Inline = 'i' as u8, - Keyed = 'k' as u8, - ListPairs = 'l' as u8, - StringJoin = 'j' as u8, - StringPairs = 'p' as u8, - StringPrefix = 's' as u8, - Tuple = 't' as u8, + Keyed = 'y' as u8, + Kinded = 'k' as u8, + Bytesprefix = 'b' as u8, + Stringprefix = 's' as u8, + // special + Basic = '1' as u8, + Ignored = '0' as u8, + Advanced = 'a' as u8, } impl Strategy { - // pub const fn dm_kind(repr_kind: Kind) -> Kind { - // match repr_kind { - // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, - // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, - // Kind::Union if S == Self::BytesPrefix as u8 => Kind::Map, - // _ if S == Self::StringPairs as u8 => Kind::String, - // Kind::Union if S == Self::StringPrefix as u8 => Kind::Map, - // _ if S == Self::Tuple as u8 => Kind::List, - // _ => panic!(), - // } - // } + /// + pub const fn is_basic(&self) -> bool { + *self as u8 == Self::Basic as u8 + } - // pub const fn schema_kind() -> Kind { - // match S { - // _ if S == Self::BytesPrefix as u8 => Kind::Union, - // _ if S == Self::ListPairs as u8 => Kind::Struct, - // _ if S == Self::StringJoin as u8 => Kind::Struct, - // _ if S == Self::StringPairs as u8 => Kind::Struct, - // _ if S == Self::StringPrefix as u8 => Kind::Union, - // _ if S == Self::Tuple as u8 => Kind::Struct, - // _ => panic!(), - // } - // } + /// + pub const fn is_ignored(&self) -> bool { + *self as u8 == Self::Ignored as u8 + } - // pub const fn repr_kind() -> Kind { - // match S { - // _ if S == Self::BytesPrefix as u8 => Kind::Bytes, - // _ if S == Self::ListPairs as u8 => Kind::List, - // _ if S == Self::StringJoin as u8 => Kind::String, - // _ if S == Self::StringPairs as u8 => Kind::String, - // _ if S == Self::StringPrefix as u8 => Kind::String, - // _ if S == Self::Tuple as u8 => Kind::List, - // _ => panic!(), - // } - // } + /// + pub const fn is_advanced(&self) -> bool { + *self as u8 == Self::Advanced as u8 + } } /// An iterator over the elements of a list-like type, whether produced from an /// in-memory type or from an underlying [`Representation`]. #[doc(hidden)] -pub trait ListIterator { +pub trait ListIterator { fn size_hint(&self) -> Option; - fn field(&self) -> Field<'_>; + // fn next_ignored(&mut self) -> Result; - fn next_ignored(&mut self) -> Result; + // fn next(&mut self) -> Result, Error> { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // } - fn next(&mut self) -> Result, Error> - where - T: Representation, - { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - } + // fn next_ref(&mut self) -> Result, Error> { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // } - fn next_ref(&mut self) -> Result, Error> - where - T: Representation, - { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - } + // fn next_ref_mut(&mut self) -> Result, Error> { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // } - fn next_ref_mut(&mut self) -> Result, Error> - where - T: Representation, - { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - } + // fn next_seed<'a, const C: u64, Ctx: Context>( + // &mut self, + // seed: SelectorSeed<'a, Ctx, T>, + // ) -> Result + // where + // T: Select; - fn next_seed<'a, const C: u64, Ctx: Context>( + /// Returns `Ok(true)` if element was found and was successfully + /// selected/ignored, and `Ok(false)` if iterator was already empty. + fn next_element_seed<'a, const C: u64, Ctx: Context + 'a, F>( &mut self, - seed: SelectorSeed<'a, Ctx, T>, + seeder: F, ) -> Result where - T: Select; + T: Select, + F: FnOnce(usize) -> Result>, Error>, + { + unimplemented!() + } } /// An iterator over the keys and values of a map-like type, whether produced /// from an in-memory type or from an underlying [`Representation`]. #[doc(hidden)] -pub trait MapIterator { +pub trait MapIterator +where + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, +{ fn size_hint(&self) -> Option; - fn field(&self) -> Field<'_>; - fn next_key( &mut self, expected_field_name: Option<&'static str>, - ) -> Result, Error> - where - K: Representation; + ) -> Result, Error>; fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error>; - fn next_value(&mut self, field: &Field<'_>) -> Result - where - V: Representation, - { + fn next_value(&mut self, field: &Field<'_>) -> Result { Err(Error::Custom(anyhow::Error::msg("unimplemented"))) } fn next_value_seed<'a, const C: u64, Ctx: Context>( &mut self, seed: SelectorSeed<'a, Ctx, V>, - // field: &Field<'_>, ) -> Result<(), Error> where - K: Representation, V: Select; + fn next_entry(&mut self) -> Result, Error> { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + } + + fn next_entry_seed<'a, const C: u64, Ctx: Context + 'a, F>( + &mut self, + seeder: F, + ) -> Result + where + V: Select, + F: FnOnce(&str) -> Result>, Error>, + { + Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + + // let key = if let Some(key) = self.next_key::(None)? { + // key + // } else { + // return Ok(true); + // }; + + // // todo + // let include = filter.map(|pred| pred(&key.to_string())).unwrap_or(true); + // if include { + // self.next_value_seed::(seed)?; + // Ok(false) + // } else { + // // self.next_value_ignored(&field)?; + // Ok(false) + // } + } + + /* // fn next_entry<'a, const C: u64>( // &mut self, // // seed: SelectorSeed<'a, Ctx, V>, @@ -201,6 +217,7 @@ pub trait MapIterator { // self.next_value_seed::(seeder(key)?)?; // Ok(false) // } + */ } // impl<'a, const C: u64, F, Ctx, T, O> RepresentationIterator<'a, C, F, Ctx, T, O> diff --git a/src/representation/strategies/stringjoin.rs b/src/representation/strategies/stringjoin.rs index ea45770..d0838c0 100644 --- a/src/representation/strategies/stringjoin.rs +++ b/src/representation/strategies/stringjoin.rs @@ -1,6 +1,6 @@ use crate::dev::*; -const STRATEGY: Strategy = Strategy::StringJoin; +const STRATEGY: Strategy = Strategy::Stringjoin; /* // Blanket impl for structs. diff --git a/src/representation/strategies/stringpairs.rs b/src/representation/strategies/stringpairs.rs index 3b5081c..0e52801 100644 --- a/src/representation/strategies/stringpairs.rs +++ b/src/representation/strategies/stringpairs.rs @@ -1,7 +1,7 @@ use crate::dev::*; use maybestd::{borrow::Cow, fmt, str::FromStr}; -const STRATEGY: Strategy = Strategy::StringPairs; +const STRATEGY: Strategy = Strategy::Stringpairs; /* // Blanket impl for maps. diff --git a/src/representation/strategies/stringprefix.rs b/src/representation/strategies/stringprefix.rs index 6292631..ebdbb05 100644 --- a/src/representation/strategies/stringprefix.rs +++ b/src/representation/strategies/stringprefix.rs @@ -1,3 +1,3 @@ use crate::dev::*; -const STRATEGY: Strategy = Strategy::StringPrefix; +const STRATEGY: Strategy = Strategy::Stringprefix; diff --git a/src/representation/strategies/tuple.rs b/src/representation/strategies/tuple.rs index 6931ff7..e5eebcb 100644 --- a/src/representation/strategies/tuple.rs +++ b/src/representation/strategies/tuple.rs @@ -1,24 +1,16 @@ use crate::dev::*; use macros::derive_more::From; -use maybestd::{fmt, marker::PhantomData}; +use maybestd::{cell::RefCell, fmt, marker::PhantomData, mem::MaybeUninit}; #[doc(hidden)] #[macro_export] macro_rules! tuple { - ($name:ident $ref_name:ident => $($ty:ident)*) => { + ($name:ident $ref_name:ident $suffix:ident => $($ty:ident)*) => { /// Type that implements selection against tuple-represented structs. #[doc(hidden)] #[derive(Clone, Debug, From)] pub struct $ref_name<'a, T = Any, $($ty = Any,)*>($(pub &'a $ty,)* PhantomData); - impl<'a, T, $($ty,)*> $ref_name<'a, T, $($ty,)*> - where - T: Representation, - $($ty: Representation,)* - { - pub(crate) const LEN: usize = tuple!(@len $($ty)*); - } - impl<'a, T, $($ty,)*> From<&'a ($($ty,)*)> for $ref_name<'a, T, $($ty,)*> { @@ -52,14 +44,6 @@ macro_rules! tuple { #[derive(Clone, Debug, From)] pub struct $name($(pub $ty,)* PhantomData); - impl $name - where - T: Representation, - $($ty: Representation,)* - { - pub(crate) const LEN: usize = tuple!(@len $($ty)*); - } - impl From<($($ty,)*)> for $name { fn from(($($ty,)*): ($($ty,)*)) -> Self { Self($($ty,)* PhantomData) @@ -67,25 +51,15 @@ macro_rules! tuple { } const _: () = { + const LEN: usize = tuple!(@len $($ty)*); tuple!(@tuple $name $ref_name => $($ty)*); }; const _: () = { - tuple!(@struct_tuple $name $ref_name => $($ty)*); - }; - const _: () = { - // tuple!(listpairs! $name $ref_name => $($ty)*); - }; - const _: () = { - // tuple!(stringjoin! $name $ref_name => $($ty)*); - }; - const _: () = { - // tuple!(stringpairs! $name $ref_name => $($ty)*); - }; - const _: () = { - // tuple!(stringprefix! $name $ref_name => $($ty)*); + const LEN: usize = tuple!(@len $($ty)*); + tuple!(@struct_tuple $name $ref_name $suffix => $($ty)*); }; }; - (@repr_ext $name:ident $repr:ident => $($ty:ident)*) => { + (@repr_methods $name:ident $repr:ident => $($ty:ident)*) => { fn has_links(&self) -> bool { // let ($($ty,)*) = self; // false $(| $ty.has_links())* @@ -98,25 +72,23 @@ macro_rules! tuple { // $macro_name!($name $ref_name => $($ty)*); // }; (@tuple $name:ident $ref_name:ident => $($ty:ident)*) => { - const LEN: usize = $crate::tuple!(@len $($ty)*); - impl<$($ty,)*> Representation for ($($ty,)*) where $($ty: Representation,)* { - type DataModelKind = type_kinds::List; - type SchemaKind = type_kinds::Struct; - type ReprKind = type_kinds::List; - const NAME: &'static str = stringify!($name); - const SCHEMA: &'static str = ""; + const SCHEMA: &'static str = concat!( + "type ", stringify!($name), " struct { ", + $(stringify!($ty), stringify!($ty),)* + " } representation tuple" + ); const DATA_MODEL_KIND: Kind = Kind::List; const SCHEMA_KIND: Kind = Kind::Struct; const REPR_KIND: Kind = Kind::List; const REPR_STRATEGY: Strategy = Strategy::Tuple; const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; - $crate::tuple!(@repr_ext $name List => $($ty)*); + $crate::tuple!(@repr_methods $name List => $($ty)*); fn serialize(&self, serializer: Se) -> Result where @@ -149,7 +121,7 @@ macro_rules! tuple { { Ok(( $(seq - .next_element_seed(DeserializeWrapper::::new())? + .next_element_seed(DeserializeRepr::::new())? .ok_or_else(|| Ac::Error::missing_field(""))? ,)* )) @@ -160,18 +132,19 @@ macro_rules! tuple { } } }; - (@struct_tuple $name:ident $ref_name:ident => $($ty:ident)*) => { + // (@alias $name:ident => $($ty:ident)*) => () + (@struct_tuple $name:ident $ref_name:ident $suffix:ident => $($ty:ident)*) => { impl<'a, T, $($ty,)*> Representation for $ref_name<'a, T, $($ty,)*> where T: Representation, $($ty: Representation,)* { - type DataModelKind = type_kinds::Map; - type SchemaKind = type_kinds::Struct; - type ReprKind = type_kinds::List; - const NAME: &'static str = stringify!($name); - const SCHEMA: &'static str = ""; + const SCHEMA: &'static str = concat!( + "type ", stringify!($name), " struct { ", + $(stringify!($ty), stringify!($ty),)* + " } representation tuple" + ); const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Struct; const REPR_KIND: Kind = Kind::List; @@ -179,8 +152,10 @@ macro_rules! tuple { const FIELDS: &'static [&'static str] = T::FIELDS; const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; - $crate::tuple!(@repr_ext $ref_name List => $($ty)*); + $crate::tuple!(@repr_methods $ref_name List => $($ty)*); + #[inline] + #[doc(hidden)] fn serialize(&self, serializer: Se) -> Result where Se: Serializer, @@ -188,9 +163,9 @@ macro_rules! tuple { use ser::SerializeSeq; let Self($($ty,)* _) = self; - let mut seq = serializer.serialize_seq(Some(Self::LEN))?; + let mut seq = serializer.serialize_seq(Some(LEN))?; $( - seq.serialize_element(&SerializeWrapper::<'_, MC, $ty>($ty))?; + seq.serialize_element(&SerializeRepr::<'_, MC, $ty>($ty))?; )* seq.end() } @@ -214,12 +189,12 @@ macro_rules! tuple { T: Representation, $($ty: Representation,)* { - type DataModelKind = type_kinds::Map; - type SchemaKind = type_kinds::Struct; - type ReprKind = type_kinds::List; - const NAME: &'static str = stringify!($name); - const SCHEMA: &'static str = ""; + const SCHEMA: &'static str = concat!( + "type ", stringify!($name), " struct { ", + $(stringify!($ty), stringify!($ty),)* + " } representation tuple" + ); const DATA_MODEL_KIND: Kind = Kind::Map; const SCHEMA_KIND: Kind = Kind::Struct; const REPR_KIND: Kind = Kind::List; @@ -227,15 +202,16 @@ macro_rules! tuple { const FIELDS: &'static [&'static str] = T::FIELDS; const HAS_LINKS: bool = false $(| $ty::HAS_LINKS )*; - $crate::tuple!(@repr_ext $name List => $($ty)*); + $crate::tuple!(@repr_methods $name List => $($ty)*); + #[inline] + #[doc(hidden)] fn serialize(&self, serializer: Se) -> Result where Se: Serializer, { $ref_name::from(self).serialize::(serializer) } - #[inline] #[doc(hidden)] fn deserialize<'de, const MC: u64, De>(deserializer: De) -> Result @@ -247,35 +223,157 @@ macro_rules! tuple { } // // Blanket impls for structs. - // repr_serde! { @visitors for T => $name - // { @dk type_kinds::Map @sk type_kinds::Struct @rk type_kinds::List } - // { T, $($ty)* } - // { T: Default + TryFrom<($($ty,)*)> + 'static, - // >::Error: fmt::Display, - // $($ty: Select + 'static,)*, } @serde { - // } - // }; + $crate::tuple!(@select $name $suffix => $($ty)* { $($ty)* }); + $crate::repr_serde! { @visitors for $name + { T, $($ty,)* } { T: Select + 'static, + $($ty: Select + 'static,)* } @serde { + #[inline] + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "A len {}-tuple struct of type {}", LEN, T::NAME) + } + #[inline] + fn visit_seq(self, seq: Ac) -> Result + where + Ac: SeqAccess<'de>, + { paste::paste! { + // self.into_inner() + // .[]( + mut self, + mut iter: It, + constructor: Cfn, + ) -> Result<(), Error> + where + $($ty: Select + 'static,)* + $(It: MapIterator,)* + Cfn: FnOnce($($ty,)*) -> Result, + { + // select the matched node, and set up the dag + self.handle_node(SelectedNode::Map)?; + // FIXME: should maybe just use an option, since idx might get inited + $(let [] = RefCell::new(MaybeUninit::uninit());)* + // create cleanup cb + let drop_inited = |idx: usize, err: Error| -> Result<(), Error> { + let mut i = 0usize; + $({ if i < idx { + unsafe { + [].borrow_mut().assume_init_drop(); + } + i += 1; + }})* + Err(err) + }; + + // + let mut idx = 0usize; + $( if let Err(err) = <_ as MapIterator>::next_key::(&mut iter, Some(T::FIELDS[idx])) + .and_then(|_: Option| self.handle_field::( + &mut iter, + self.is_dag_select().then_some(Box::new(|child, _| { + [].borrow_mut().write(child); + Ok(()) + })), + )) + { + return drop_inited(idx, err); + } + + idx += 1; + // if idx < LEN { + // iter.into_next() + // } else { + // iter + // } + )* + + // match dag + if self.is_dag_select() { + $(let [] = unsafe { + [].into_inner().assume_init() + };)* + self.handle_dag(constructor($([],)*)?)?; + } + + Ok(()) + } + + pub fn []( + mut self, + mut iter: It, + ) -> Result<(), Error> + where + $($ty: Select + 'static,)* + $(It: MapIterator,)* + { + unimplemented!() + } + }} }; } -tuple!(StructTuple2 StructTupleRef2 => A B); -tuple!(StructTuple3 StructTupleRef3 => A B C); -tuple!(StructTuple4 StructTupleRef4 => A B C D); -tuple!(StructTuple5 StructTupleRef5 => A B C D E); -tuple!(StructTuple6 StructTupleRef6 => A B C D E F); -tuple!(StructTuple7 StructTupleRef7 => A B C D E F G); -tuple!(StructTuple8 StructTupleRef8 => A B C D E F G H); -tuple!(StructTuple9 StructTupleRef9 => A B C D E F G H I); -tuple!(StructTuple10 StructTupleRef10 => A B C D E F G H I J); -tuple!(StructTuple11 StructTupleRef11 => A B C D E F G H I J K); -tuple!(StructTuple12 StructTupleRef12 => A B C D E F G H I J K L); -tuple!(StructTuple13 StructTupleRef13 => A B C D E F G H I J K L M); -tuple!(StructTuple14 StructTupleRef14 => A B C D E F G H I J K L M N); -tuple!(StructTuple15 StructTupleRef15 => A B C D E F G H I J K L M N O); -tuple!(StructTuple16 StructTupleRef16 => A B C D E F G H I J K L M N O P); -tuple!(StructTuple17 StructTupleRef17 => A B C D E F G H I J K L M N O P Q); -tuple!(StructTuple18 StructTupleRef18 => A B C D E F G H I J K L M N O P Q R); -tuple!(StructTuple19 StructTupleRef19 => A B C D E F G H I J K L M N O P Q R S); +struct TupleSerdeIter { + pub index: usize, + inner: Ac, + _t: PhantomData<(T, U)>, +} +impl TupleSerdeIter { + // pub fn into_next(self) -> TupleSerdeIter { + // TupleSerdeIter { + // index: self.index + 1, + // inner: self.inner, + // _t: PhantomData, + // } + // } +} + +tuple!(Tuple2 TupleRef2 _2 => A B); +tuple!(Tuple3 TupleRef3 _3 => A B C); +tuple!(Tuple4 TupleRef4 _4 => A B C D); +tuple!(Tuple5 TupleRef5 _5 => A B C D E); +tuple!(Tuple6 TupleRef6 _6 => A B C D E F); +tuple!(Tuple7 TupleRef7 _7 => A B C D E F G); +tuple!(Tuple8 TupleRef8 _8 => A B C D E F G H); +tuple!(Tuple9 TupleRef9 _9 => A B C D E F G H I); +tuple!(Tuple10 TupleRef10 _10 => A B C D E F G H I J); +tuple!(Tuple11 TupleRef11 _11 => A B C D E F G H I J K); +tuple!(Tuple12 TupleRef12 _12 => A B C D E F G H I J K L); +tuple!(Tuple13 TupleRef13 _13 => A B C D E F G H I J K L M); +tuple!(Tuple14 TupleRef14 _14 => A B C D E F G H I J K L M N); +tuple!(Tuple15 TupleRef15 _15 => A B C D E F G H I J K L M N O); +tuple!(Tuple16 TupleRef16 _16 => A B C D E F G H I J K L M N O P); +tuple!(Tuple17 TupleRef17 _17 => A B C D E F G H I J K L M N O P Q); +tuple!(Tuple18 TupleRef18 _18 => A B C D E F G H I J K L M N O P Q R); +tuple!(Tuple19 TupleRef19 _19 => A B C D E F G H I J K L M N O P Q R S); + +// impl MapIterator for TupleSerdeIter { +// fn size_hint(&self) -> Option { +// Some(MAX) +// } + +// fn field(&self) -> Field<'_> { +// unimplemented!() +// } + +// fn next_ignored(&mut self) -> Result { +// Ok(false) +// } +// } // impl_tuple!(@repr Tuple12 Tuple12RefTuple2Ref => A B C D E F G H I J K L { diff --git a/src/select/context.rs b/src/select/context.rs index a570b33..fe4553e 100644 --- a/src/select/context.rs +++ b/src/select/context.rs @@ -10,25 +10,28 @@ mod ipfs; use crate::dev::*; -use maybestd::io::{empty, Cursor, Empty, Read, Sink, Write}; -use std::collections::HashMap; +use maybestd::{ + collections::HashMap, + io::{empty, Cursor, Empty, Read, Sink, Write}, +}; -trait BlockWriter: Write {} +// trait BlockWriter: Write {} -/// Trait for providing blocks and additional logic required for selection. +/// Trait for providing blocks and additional logic required for selection, +/// patching, etc. pub trait Context: Sized { /// - type Reader: Read; + type Reader: Read; // ? BufRead? /// - type Writer: Write; + type Writer: Write; // ? BufWrite? // type Marker; /// fn block_reader(&mut self, cid: &Cid) -> Result; - /// + /// TODO: fn block_writer(&mut self, cid_to_replace: Option<&Cid>) -> Result { unimplemented!() } @@ -134,7 +137,7 @@ impl MemoryContext { multihash_code: u64, block: Vec, ) -> Result { - let cid = Cid::new(version, multicodec_code, multihash_code, block.as_slice())?; + let cid = Cid::from_reader(version, multicodec_code, multihash_code, block.as_slice())?; self.blocks.insert(cid, block); Ok(cid) } diff --git a/src/select/mod.rs b/src/select/mod.rs index dea4144..edde2a5 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -14,16 +14,17 @@ mod selectors; mod state; pub use context::*; +pub use dag_selection::*; pub use field::*; +pub use node_selection::*; pub use params::*; pub use seed::*; -pub use selection::*; pub use selectors::*; pub use state::*; use crate::dev::*; use macros::derive_more::{Display, From}; -use std::{ +use maybestd::{ cell::RefCell, path::{Path, PathBuf}, str::FromStr, @@ -63,6 +64,10 @@ pub trait Select: Representation { ctx, ); + // TODO: put this block here + // let cid = &seed.state.current_block; + // let block = seed.ctx.block_reader(cid)?; + // cid.multicodec()?.read_with_seed(Self::Walker::from(seed), block) Self::__select(seed) } @@ -86,81 +91,6 @@ pub trait Select: Representation { // Self::Seed::<'a, 'de, C>::from(seed).deserialize(deserializer) } - #[doc(hidden)] - fn __select_seq<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - mut seq: A, // should be ListIterator - ) -> Result, A::Error> - where - A: SeqAccess<'de>, - { - // seq.next_element_seed(CodecSeed::from(seed)) - Err(A::Error::custom("__select_seq not yet implemented")) - // TODO: default impl should use GAT for CodedSeed - // seq.next_element_seed(Self::Seed::<'a, 'de, C>::from(seed)) - } - - #[doc(hidden)] - fn __select_map<'a, 'de, const C: u64, A>( - seed: SelectorSeed<'a, Ctx, Self>, - mut map: A, // should be MapIterator, - is_key: bool, - ) -> Result, A::Error> - where - A: MapAccess<'de>, - { - Err(A::Error::custom("__select_map not yet implemented")) - // TODO: default impl should use GAT for CodedSeed - // let seed = Self::Seed::<'a, 'de, C>::from(seed); - // if is_key { - // map.next_key_seed(seed) - // } else { - // Ok(Some(map.next_value_seed(seed)?)) - // } - } - - // #[doc(hidden)] - // fn __select_list<'a, 'de, const C: u64, I, T>( - // seed: SelectorSeed<'a, Ctx, Self>, - // // mut seq: A, // should be ListIterator - // mut iter: I, - // ) -> Result, Error> - // where - // // A: SeqAccess<'de>, - // I: ListIterator, - // T: Select, - // { - // unimplemented!() - // // seq.next_element_seed(CodecSeed::from(seed)) - // // Err(Error::Custom("unimplemented")) - // // TODO: default impl should use GAT for CodedSeed - // // seq.next_element_seed(Self::Seed::<'a, 'de, C>::from(seed)) - // } - - // #[doc(hidden)] - // fn __select_map<'a, 'de, const C: u64, I, K, V>( - // seed: SelectorSeed<'a, Ctx, Self>, - // // mut map: A, // should be MapIterator, - // // is_key: bool, - // mut iter: I, - // ) -> Result, Error> - // where - // // A: MapAccess<'de>, - // I: MapIterator, - // K: StringRepresentation, - // V: Representation, - // { - // unimplemented!() - // // Err(Error::Custom("unimplemented")) - // // TODO: default impl should use GAT for CodedSeed - // // let seed = Self::Seed::<'a, 'de, C>::from(seed); - // // if is_key { - // // map.next_key_seed(seed) - // // } else { - // // Ok(Some(map.next_value_seed(seed)?)) - // // } - // } - /// Selects against the dag, loading more blocks from `Ctx` if required. /// /// TODO @@ -198,14 +128,14 @@ pub trait Select: Representation { unimplemented!() } - /// Flushes the dag according to the selector, writing blocks to `Ctx` if - /// flushing linked dags. - /// - /// TODO - #[doc(hidden)] - fn flush(&mut self, ctx: &mut Ctx) -> Result<(), Error> { - unimplemented!() - } + // /// Flushes the dag according to the selector, writing blocks to `Ctx` if + // /// flushing linked dags. + // /// + // /// TODO + // #[doc(hidden)] + // fn flush(&mut self, ctx: &mut Ctx) -> Result<(), Error> { + // unimplemented!() + // } // fn patch>(seed: ContextSeed<'_, C, Self, S>) -> Result<(), Error> { // unimplemented!() @@ -401,7 +331,7 @@ mod params { } } -mod selection { +mod node_selection { use super::*; /// @@ -444,6 +374,10 @@ mod selection { } } } +} + +mod dag_selection { + use super::*; /// pub struct DagSelection { @@ -598,7 +532,7 @@ mod selection { /// #[serde(skip)] // TODO #[serde(rename = "string")] - String(IpldString), + String(String), /// #[serde(skip)] // TODO @@ -927,7 +861,7 @@ mod field { #[cfg(test)] mod tests { - use crate::prelude::*; + use crate::*; schema! { #[ipld_attr(internal)] diff --git a/src/select/seed.rs b/src/select/seed.rs index 35d5c40..1b898bf 100644 --- a/src/select/seed.rs +++ b/src/select/seed.rs @@ -1,3 +1,5 @@ +use std::{borrow::Borrow, ops::Deref}; + use crate::dev::{macros::derive_more::From, *}; use maybestd::{fmt, marker::PhantomData, str::FromStr}; @@ -12,6 +14,8 @@ pub enum SelectionMode { /// Selection will invoke the provided callback on all matched [`Node`]s. MatchNode, + Match, + /// Selection will invoke the provided callback on all matched [`Dag`]s. Select, @@ -46,117 +50,22 @@ pub struct SelectorSeed<'a, Ctx, T> { pub type EmptySeed = SelectorSeed<'static, (), T>; -/// A marked [`SelectorSeed`] that's aware of the codec of the block it's -/// currenly selecting against. -#[cfg_attr(not(feature = "dev"), doc(hidden))] -#[derive(Debug)] -pub struct CodecSeed< - const C: u64, - S, - T, - U, - DK = ::DataModelKind, - SK = ::SchemaKind, - RK = ::ReprKind, ->(pub(crate) S, PhantomData<(T, U, DK, SK, RK)>) -where - T: Representation, - DK: TypedKind, - SK: TypedKind, - RK: TypedKind; - -impl CodecSeed { - /// - pub fn from(seed: S) -> Self { - Self(seed, PhantomData) - } - - /// Normalizes the representation kind, if typed. - const fn repr_kind() -> Kind { - if Kind::TypedInt.contains(T::REPR_KIND) { - Int::REPR_KIND - } else if Kind::TypedFloat.contains(T::REPR_KIND) { - Float::REPR_KIND - } else { - T::REPR_KIND - } - } -} - -/// Blanket impl for all `CodecSeed`s that implement `Visitor` for a given `T`. -/// Doing this allows us to more easily "escape" [`serde`]'s traits into our own -/// methods for selection. -impl<'a, 'de, const C: u64, S, T, U, DK, SK, RK> DeserializeSeed<'de> - for CodecSeed -where - Self: Visitor<'de> + LinkVisitor<'de>, - S: SeedType, - T: Representation, - DK: TypedKind, - SK: TypedKind, - RK: TypedKind, -{ - type Value = >::Value; - - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - if T::__IGNORED { - return deserializer.deserialize_ignored_any(self); - } else if T::DATA_MODEL_KIND.is_option() { - return deserializer.deserialize_option(self); - } - - match (T::SCHEMA_KIND, Self::repr_kind()) { - // union (kinded => any, stringprefix => str, bytesprefix => bytes) - // union keyed (ref), envelope (tag + ref), inline (tag + inline) - (Kind::Union, Kind::Map) => deserializer.deserialize_enum(T::NAME, T::FIELDS, self), - - // structs (stringpair, stringjoin => str) - // struct map - (Kind::Struct, Kind::Map) => deserializer.deserialize_struct(T::NAME, T::FIELDS, self), - // struct tuple, listpairs - (Kind::Struct, Kind::List) => { - deserializer.deserialize_tuple_struct(T::NAME, T::FIELDS.len(), self) - } - - // enum (int => int, string => str) - - // basic - (_, Kind::Null) => deserializer.deserialize_unit(self), - (_, Kind::Bool) => deserializer.deserialize_bool(self), - (_, Kind::Int8) => deserializer.deserialize_i8(self), - (_, Kind::Int16) => deserializer.deserialize_i16(self), - (_, Kind::Int32) => deserializer.deserialize_i32(self), - (_, Kind::Int64) => deserializer.deserialize_i64(self), - (_, Kind::Int128) => deserializer.deserialize_i128(self), - (_, Kind::Uint8) => deserializer.deserialize_u8(self), - (_, Kind::Uint16) => deserializer.deserialize_u16(self), - (_, Kind::Uint32) => deserializer.deserialize_u32(self), - (_, Kind::Uint64) => deserializer.deserialize_u64(self), - (_, Kind::Uint128) => deserializer.deserialize_u128(self), - (_, Kind::Float32) => deserializer.deserialize_f32(self), - (_, Kind::Float64) => deserializer.deserialize_f64(self), - (_, Kind::String) => deserializer.deserialize_str(self), - (_, Kind::Bytes) => Multicodec::deserialize_bytes::(deserializer, self), - (_, Kind::List) => deserializer.deserialize_seq(self), - (_, Kind::Map) => deserializer.deserialize_map(self), - (_, Kind::Link) => Multicodec::deserialize_link::(deserializer, self), - // anything else - _ => Multicodec::deserialize_any::(deserializer, self), - } - } -} +// Blanket impl for all `CodecSeed`s that implement `Visitor` for a given `T`. +// Doing this allows us to more easily "escape" [`serde`]'s traits into our own +// methods for selection, requiring only that we implement [`Visitor`] for +// `CodecSeed<..., T>`. +repr_serde!(@def_seed); #[doc(hidden)] pub trait SeedType: Sized { - type Input; + // type Input; type Output; type Wrapped: SeedType; const CAN_SELECT: bool; + fn mode(&self) -> SelectionMode; + fn selector(&self) -> &Selector; + // fn select_node() -> Result<(), Error> { // unimplemented!() // } @@ -169,22 +78,30 @@ pub trait SeedType: Sized { } } impl SeedType for PhantomData { - type Input = (); + // type Input = (); type Output = T; type Wrapped = PhantomData; const CAN_SELECT: bool = false; + + fn mode(&self) -> SelectionMode { + SelectionMode::Match + } + fn selector(&self) -> &Selector { + &DEFAULT_SELECTOR + } } -// impl SeedType for DeserializeWrapper { -// type Input = (); -// type Output = T; -// type Wrapped = DeserializeWrapper; -// const CAN_SELECT: bool = false; -// } -impl<'a, Ctx, T: 'a, U: 'a> SeedType for SelectorSeed<'a, Ctx, T> { - type Input = &'a mut T; +impl<'a, Ctx, T, U> SeedType for SelectorSeed<'a, Ctx, T> { + // type Input = &'a mut T; type Output = (); type Wrapped = SelectorSeed<'a, Ctx, U>; const CAN_SELECT: bool = true; + + fn mode(&self) -> SelectionMode { + self._mode() + } + fn selector(&self) -> &Selector { + self.selector + } } // impl<'de, const C: u64, T> CodecSeed, T> @@ -246,38 +163,25 @@ where } // TODO: be lazier: provide a mode method that lets us skip any dag-deserialization work, while also letting us just call what we want without a lot of branching -impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> -where - Ctx: Context, - T: Representation, -{ - // #[inline] - // pub(crate) fn mode(&self) -> SelectionMode<'_> { - // match (&self.callback, self.selector) { - // (Callback::SelectNode { .. }, Selector::Matcher(m)) => { - // SelectionMode::SelectNode(m.label.as_deref()) - // } - // (Callback::SelectNode { .. }, _) => SelectionMode::SelectNode(None), - // (Callback::SelectDag { .. } | Callback::MatchDag { .. }, _) => SelectionMode::SelectDag, - // // Self::Patch { .. } => SelectionMode::Patch, - // } - // } - +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> { /// #[inline] - pub const fn mode(&self) -> SelectionMode { - match &self.callback { - Callback::SelectNode { .. } if self.selector.is_matcher() => SelectionMode::MatchNode, - Callback::SelectNode { .. } => SelectionMode::CoverNode, - Callback::SelectDag { .. } | Callback::MatchDag { .. } => SelectionMode::Select, - Callback::Patch { .. } => SelectionMode::Patch, + const fn _mode(&self) -> SelectionMode { + match (&self.callback, self.selector.is_matcher()) { + (Callback::SelectNode { .. }, true) => SelectionMode::MatchNode, + (Callback::SelectNode { .. }, _) => SelectionMode::CoverNode, + (Callback::SelectDag { .. }, true) | (Callback::MatchDag { .. }, _) => { + SelectionMode::Match + } + (Callback::SelectDag { .. }, _) => SelectionMode::Select, + (Callback::Patch { .. }, _) => SelectionMode::Patch, } } /// #[inline] - pub const fn is_node_select(&self) -> bool { - match self.mode() { + pub fn is_node_select(&self) -> bool { + match self._mode() { SelectionMode::CoverNode | SelectionMode::MatchNode => true, _ => false, } @@ -285,21 +189,38 @@ where /// #[inline] - pub const fn is_dag_select(&self) -> bool { - match self.mode() { - SelectionMode::Select => true, + pub fn is_dag_select(&self) -> bool { + match self._mode() { + SelectionMode::Select | SelectionMode::Match => true, _ => false, } } /// #[inline] - pub const fn is_patch(&self) -> bool { - match self.mode() { + pub fn is_patch(&self) -> bool { + match self._mode() { SelectionMode::Patch => true, _ => false, } } +} +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> +where + Ctx: Context, + T: Representation, +{ + // #[inline] + // pub(crate) fn mode(&self) -> SelectionMode<'_> { + // match (&self.callback, self.selector) { + // (Callback::SelectNode { .. }, Selector::Matcher(m)) => { + // SelectionMode::SelectNode(m.label.as_deref()) + // } + // (Callback::SelectNode { .. }, _) => SelectionMode::SelectNode(None), + // (Callback::SelectDag { .. } | Callback::MatchDag { .. }, _) => SelectionMode::SelectDag, + // // Self::Patch { .. } => SelectionMode::Patch, + // } + // } /// #[inline] @@ -371,23 +292,17 @@ where T: Representation, { /// - pub fn select_node(&mut self, node: SelectedNode) -> Result<(), Error> { + pub fn handle_node(&mut self, node: SelectedNode) -> Result<(), Error> { if let Some(matcher) = self.selector.as_matcher() { - self.callback.select_node( - self.state.path(), - node, - true, - matcher.label.as_deref(), - self.ctx, - ) - } else { self.callback - .select_node(self.state.path(), node, false, None, self.ctx) + .select_node(self.state.path(), node, matcher.label.as_deref(), self.ctx) + } else { + self.callback.cover_node(self.state.path(), node, self.ctx) } } /// - pub fn select_dag(&mut self, dag: T) -> Result<(), Error> + pub fn handle_dag(&mut self, dag: T) -> Result<(), Error> where T: Representation + 'static, { @@ -396,6 +311,7 @@ where .select_dag((self.state.path(), dag, matcher.label.as_deref()), self.ctx) } + /* /// fn to_field_select_seed<'b, U>( &'b mut self, @@ -419,59 +335,61 @@ where ctx: self.ctx, }) } + */ /// Execute the next [`Selector`] against the next element of the /// [`ListIterator`]. - pub fn select_index<'b, const C: u64, U>( + /// + /// TODO: switch on mode, calling the right iter method + /// + /// T creates seed (+ iter) + /// seed + iter -> select/patch_dm(iter) -> handle_index + /// - if selector for current index exists, descend + /// - else, ignore + pub fn handle_index<'b, const C: u64, U>( &'b mut self, - index: usize, + iter: &mut impl ListIterator, match_cb: Option + 'b>>, // match_cb: Option<&'b mut dyn MatchDagOp>, - iter: &mut impl ListIterator, ) -> Result where U: Select, { - let res = iter.next_seed::({ - let field = index.into(); - self.state.descend::(&field)?; - SelectorSeed { + let was_empty = iter.next_element_seed::(|idx| { + let field = Field::Index(idx); + Ok(Some(SelectorSeed { selector: self.selector.try_next(Some(&field))?, - state: self.state, + state: self.state.descend::(&field)?, callback: self.callback.wrap_match::(match_cb), ctx: self.ctx, - } + })) })?; - self.state.ascend::()?; - - Ok(res) + self.state.ascend::(); + Ok(was_empty) } /// - pub fn select_field<'b, const C: u64, K, V>( + pub fn handle_field<'b, const C: u64, K, V>( &'b mut self, - // key: &K, - match_cb: Option + 'b>>, iter: &mut impl MapIterator, - ) -> Result<(), Error> + match_cb: Option + 'b>>, + ) -> Result where K: StringRepresentation, ::Err: fmt::Display, V: Select, { - iter.next_value_seed::({ - let field = iter.field(); - self.state.descend::(&field)?; - SelectorSeed { + let was_empty = iter.next_entry_seed::(|key| { + let field = Field::Key(key.into()); + Ok(Some(SelectorSeed { selector: self.selector.try_next(Some(&field))?, - state: self.state, + state: self.state.descend::(&field)?, callback: self.callback.wrap_match::(match_cb), ctx: self.ctx, - } + })) })?; - self.state.ascend::()?; - - Ok(()) + self.state.ascend::(); + Ok(was_empty) } } @@ -544,538 +462,325 @@ where #[doc(hidden)] #[macro_export] macro_rules! repr_serde { - // impl Visitor for CodedSeed by REPR_KIND - (@visitor $ty:ident $marker_ty:ty { $($rk:tt)* } - { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ident - // $(< - // // match one or more lifetimes separated by a comma - // $( $ty_generics:ident ),+ - // >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - // #[doc(hidden)] - impl<'_a, 'de, const C: u64, Ctx, $($generics)*> - Visitor<'de> for - CodecSeed, - $ty, $marker_ty, $($rk)*> - where - Ctx: Context, - $ty: Representation + Select, - $($bounds)* - { - type Value = (); - $($visit_fns)* - } - }; - }; - // impl LinkVisitor for CodedSeed by REPR_KIND - (@visitor_ext $ty:ident $marker_ty:ty { $($rk:tt)* } - { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ident - // $(< - // // match one or more lifetimes separated by a comma - // $( $ty_generics:ident ),+ - // >)? - { $($visit_fns:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; + /////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// - // #[doc(hidden)] - impl<'_a, 'de, const C: u64, Ctx, $($generics)*> - LinkVisitor<'de> for - CodecSeed, - $ty, $marker_ty, $($rk)*> - where - Ctx: Context, - $ty: Representation + Select, - $($bounds)* - { - $($visit_fns)* - } - }; + // impls Visitor for $seed, T> + (@visitors for $T:ty { $($visit_fns:tt)* }) => { + repr_serde!(@visitors for $T {} {} @serde { $($visit_fns)* }); }; - - // Select - - // impl Select for T, using the seed's select - (@select - $ty:ty => $marker_ty:ty - { $($generics:tt)* } { $($bounds:tt)* } + (@visitors for $T:ty where + @serde { $($visit_fns:tt)* } + @link { $($visit_link_fns:tt)* } ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - impl Select for $ty - where - Ctx: Context, - $($bounds)* - { - // #[inline] - // fn select( - // params: Params<'_, Ctx, Self>, - // ctx: &mut Ctx, - // ) -> Result<(), Error> { - // SelectorSeed::<'_, Ctx, Self>::select(params, ctx) - // } - - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = CodecSeed::::from(seed); - seed.deserialize(deserializer) - } - - // #[doc(hidden)] - // #[inline] - // fn __select_seq<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // mut seq: A, - // ) -> Result, A::Error> - // where - // A: SeqAccess<'de>, - // { - // let seed = CodecSeed::::from(seed); - // seq.next_element_seed(seed) - // } - // - // #[doc(hidden)] - // #[inline] - // fn __select_map<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // mut map: A, - // is_key: bool, - // ) -> Result, A::Error> - // where - // A: MapAccess<'de>, - // { - // let seed = CodecSeed::::from(seed); - // if is_key { - // map.next_key_seed(seed) - // } else { - // Ok(Some(map.next_value_seed(seed)?)) - // } - // } - } - }; + repr_serde!(@visitors for $T {} {} + @serde { $($visit_fns)* } @link { $($visit_link_fns)* } + ); }; - - /////////////////////////////////////////////////////////////// - (@visitors for $T:ty => $U:ty - { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } - { $($generics:tt)* } { $($bounds:tt)* } + (@visitors for $T:ty { $($generics:tt)* } { $($bounds:tt)* } @serde { $($visit_fns:tt)* } ) => { - repr_serde!(@visitors for $T => $U - { @dk ($($dk)*) @sk ($($sk)*) @rk ($($rk)*) } - { $($generics)* } { $($bounds)* } + repr_serde!(@visitors for $T { $($generics)* } { $($bounds)* } @serde { $($visit_fns)* } @link {} ); }; - (@visitors for $T:ty => $U:ty - { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } - { $($generics:tt)* } { $($bounds:tt)* } + (@visitors for $T:ty { $($generics:tt)* } { $($bounds:tt)* } @serde { $($visit_fns:tt)* } @link { $($visit_link_fns:tt)* } ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; + #[doc(hidden)] + impl<'_a, 'de, const MC: u64, Ctx, $($generics)*> + $crate::dev::Visitor<'de> for + Seed, $T> + where + Ctx: $crate::dev::Context, + $($bounds)* + { + type Value = <$crate::dev::SelectorSeed<'_a, Ctx, $T> as SeedType<$T>>::Output; + $($visit_fns)* + } - #[doc(hidden)] - impl<'_a, 'de, const C: u64, Ctx, $($generics)*> - Visitor<'de> for - CodecSeed, $T, $U, - $($dk)*, $($sk)*, $($rk)* - > - where - Ctx: Context, - $T: Select + Representation< - DataModelKind = $($dk)*, - SchemaKind = $($sk)*, - ReprKind = $($rk)* - >, - $($bounds)* - { - type Value = as SeedType<$T>>::Output; - $($visit_fns)* - } + #[doc(hidden)] + impl<'_a, 'de, const MC: u64, Ctx, $($generics)*> + LinkVisitor<'de, MC> for + Seed, $T> + where + Ctx: $crate::dev::Context, + $($bounds)* + { + $($visit_link_fns)* + } + }; + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // impls Select for T, where $seed: DeserializeSeed + (@select for $T:ty) => { repr_serde!(@select for $T {} {}); }; + (@select for $T:ty { $($generics:tt)* } { $($bounds:tt)* }) => { + impl $crate::dev::Select for $T + where + Ctx: $crate::dev::Context, + $($bounds)* + { #[doc(hidden)] - impl<'_a, 'de, const C: u64, Ctx, $($generics)*> - LinkVisitor<'de> for - CodecSeed, $T, $U, - $($dk)*, $($sk)*, $($rk)* - > + #[inline] + fn __select_de<'a, 'de, const C: u64, D>( + seed: $crate::dev::SelectorSeed<'a, Ctx, Self>, + deserializer: D, + ) -> Result<(), D::Error> where - Ctx: Context, - $T: Select + Representation< - DataModelKind = $($dk)*, - SchemaKind = $($sk)*, - ReprKind = $($rk)* - >, - $($bounds)* + D: $crate::dev::Deserializer<'de>, { - $($visit_link_fns)* + Seed::::from(seed).deserialize(deserializer) } - }; - }; - // (@select_for $T:ty => $U:ty - // ) => { - // repr_serde!( - // @select_for $T => $U - // { @dk (<$T as Representation>::DataModelKind) - // @sk (<$T as Representation>::SchemaKind) - // @rk (<$T as Representation>::ReprKind) } - // ); - // }; - (@select_for $T:ty) => { - repr_serde!(@select_for $T {} {}); - }; - (@select_for $T:ty { $($generics:tt)* } { $($bounds:tt)* }) => { - repr_serde!(@select_for $T => $T { $($generics)* } { $($bounds)* }); + } }; - (@select_for $T:ty => $U:ty { $($generics:tt)* } { $($bounds:tt)* }) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - impl Select for $T - where - Ctx: Context, - $($bounds)* - { - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = CodecSeed::::from(seed); - seed.deserialize(deserializer) - } + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + // defines a new Seed to be used as a DeserializeSeed and Visitor + (@def_seed) => { + use $crate::maybestd::marker::PhantomData as Phantom; + + #[doc(hidden)] + pub(crate) struct Seed(S, Phantom); + #[doc(hidden)] + pub(crate) trait ISeed: AsRef + AsMut + From { + const CAN_SELECT: bool; + type Inner; + fn into_inner(self) -> S; + fn mode(&self) -> SelectionMode; + fn selector(&self) -> &Selector; + } + impl, T> ISeed for Seed { + const CAN_SELECT: bool = S::CAN_SELECT; + type Inner = T; + #[inline(always)] + fn into_inner(self) -> S { + self.0 } - }; - }; - (@select_for $T:ty => $U:ty - { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } - ) => { - repr_serde!(@select_for $T => $U - { @dk ($($dk)*) @sk ($($sk)*) @rk ($($rk)*) } {} {} - ); - }; - (@select_for $T:ty => $U:ty - { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } - { $($generics:tt)* } { $($bounds:tt)* } - ) => { - repr_serde!(@select_for $T => $U { $($generics)* } { - $T: Representation< - DataModelKind = $($dk)*, - SchemaKind = $($sk)*, - ReprKind = $($rk)* - >, - $($bounds)* - }); - }; - (@select_for_newtype $T:ty => $($constructor:tt)* ( $U:ty ) - { @dk ($($dk:tt)*) @sk ($($sk:tt)*) @rk ($($rk:tt)*) } - { $($generics:tt)* } { $($bounds:tt)* } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; - - impl Select for $T - where - Ctx: Context, - $T: Representation< - DataModelKind = $($dk)*, - SchemaKind = $($sk)*, - ReprKind = $($rk)* - >, - $($bounds)* - { - #[doc(hidden)] - #[inline] - fn __select<'a>( - seed: SelectorSeed<'a, Ctx, Self>, - ) -> Result<(), Error> { - let seed = seed.wrap::<$U, _>($constructor); - <$U>::__select(seed) - } + #[inline(always)] + fn selector(&self) -> &Selector { + self.0.selector() } - }; - }; + #[inline(always)] + fn mode(&self) -> SelectionMode { + self.0.mode() + } + } - /* - (@seed_from_params $params:ident $ctx:ident) => {{ - let Params { - cid, - selector, - max_path_depth, - max_link_depth, - callback, - } = $params; - let mut state = State { - max_path_depth, - max_link_depth, - ..Default::default() - }; + impl AsRef for Seed { + #[inline(always)] + fn as_ref(&self) -> &S { + &self.0 + } + } + impl AsMut for Seed { + #[inline(always)] + fn as_mut(&mut self) -> &mut S { + &mut self.0 + } + } + impl From for Seed { + #[inline(always)] + fn from(seed: S) -> Self { + Self(seed, Phantom) + } + } - let root = cid.ok_or_else(|| { - Error::InvalidSelectionParams("selection must start against some cid") - })?; - let block = $ctx.block_reader(&root)?; + impl<'de, const C: u64, S, T: Representation> DeserializeSeed<'de> for Seed + where + Self: LinkVisitor<'de, C>, + S: SeedType, + T: Representation, + { + type Value = >::Value; - let default_selector = Selector::DEFAULT; - SelectorSeed { - selector: &selector.unwrap_or(&default_selector), - state: &mut state, - callback, - ctx: &mut $ctx, + #[inline] + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::deserialize_with_visitor::(deserializer, self) + } } - }}; - */ - - // newtype impls + }; +} - (@select_newtype - { $($generics:tt)* } { $($bounds:tt)* } - $ty:ty { $constructor:expr => $inner_ty:ty } - ) => { - const _: () = { - #[allow(unused_imports)] - use $crate::dev::*; +/// ideas for refactor +/// +/// notes: +/// - serde == ||basic-data-model|| access to ||encoded|| data +/// - ipld data model == +/// - ipld node == ||basic-data-model|| access to ||abstract-data-model|| data +/// +/// ! reqs: +/// 0. select/patch against blocks +/// 1. easy support for selective-deserialization +/// 1b. share selection impl between block (select) and dag (select_in) +/// ==> AstWalk.deserialize(block_de) +/// ==> AstWalk.deserialize(self.into_deserializer()) +/// e.g. tuple struct -> tupledeserializer, so it knows fields +/// => each IntoDeserializer must support T::REPR (for select(_in)) +/// (? DM, SCHEMA?) +/// => [opt] Into(Map/Seq/Enum/Struct)Access for Ref(Mut) +/// 1c. share Visitor logic between decode (Phantom) and select (Seed) +/// - Phantom.deserialize(...) vs AstWalk.deserialize(...) +/// i.e. AstWalk.seed.select(T::from(val)) vs return T::from(val) +/// - each visit fn: +/// - is given a source of value(s) from a REPRESENTATION +/// - MUST decide to: +/// 1. drain source (by SCHEMA) and return T +/// 2. selectively drain source (by SCHEMA) and return None +/// 3. ...? +/// ? ==> SelectorSeed.explore_list(seq) +/// - +/// +/// ! nice to haves: +/// 1. serde-compatible +/// 2. +/// 3. ? (de)serialize as another repr +/// - aka follow another type's (de)serialize instructions +/// ... U::deserialize(t.into_deserializer()) +/// +/// ! dream features: +/// 1. provide hooks forcompat with rkyv / other frameworks +pub trait Walk<'de, 'a: 'de, const MC: u64 = IDENTITY, T = Any> +where + T: Representation + 'de, + Self: Default + + LinkVisitor<'de, MC, Value = AstResult<'de, T>> + + DeserializeSeed<'de, Value = AstResult<'de, T>>, +{ +} - impl Select for $ty - where - Ctx: Context, - $($bounds)* - { - #[doc(hidden)] - #[inline] - fn __select<'a>( - seed: SelectorSeed<'a, Ctx, Self>, - ) -> Result<(), Error> { - let seed = seed.wrap::<$inner_ty, _>($constructor); - <$inner_ty>::__select(seed) - } +impl<'de, 'a: 'de, const MC: u64, T, W> Walk<'de, 'a, MC, T> for W +where + T: Representation + 'de, + W: Default + + LinkVisitor<'de, MC, Value = AstResult<'de, T>> + + DeserializeSeed<'de, Value = AstResult<'de, T>>, +{ +} - // #[doc(hidden)] - // #[inline] - // fn __select_de<'a, 'de, const C: u64, D>( - // seed: SelectorSeed<'a, Ctx, Self>, - // deserializer: D, - // ) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // let seed = seed.wrap::<$inner_ty, _>($constructor); - // <$inner_ty>::__select_de::(seed, deserializer) - // } +// impl<'de, 'a: 'de, const FULL: bool, W, T> DeserializeSeed<'de> for W +// where +// T: Representation, +// W: Walk<'de, 'a, T, FULL>, +// { +// unimplemented!() +// } - // #[doc(hidden)] - // #[inline] - // fn __select_seq<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // seq: A, - // ) -> Result, A::Error> - // where - // A: SeqAccess<'de>, - // { - // let seed = seed.wrap::<$inner_ty, _>($constructor); - // <$inner_ty>::__select_seq::(seed, seq) - // } +/// +pub struct AstWalk<'a, const MC: u64 = IDENTITY, Ctx = (), T = Any>(pub SelectorSeed<'a, Ctx, T>); - // #[doc(hidden)] - // #[inline] - // fn __select_map<'a, 'de, const C: u64, A>( - // seed: SelectorSeed<'a, Ctx, Self>, - // map: A, - // is_key: bool, - // ) -> Result, A::Error> - // where - // A: MapAccess<'de>, - // { - // let seed = seed.wrap::<$inner_ty, _>($constructor); - // <$inner_ty>::__select_map::(seed, map, is_key) - // } - } - }; - }; +/// +#[derive(Debug)] +pub enum AstResult<'a, T> { + /// + Ok, + /// + Value(T), + /// + Ref(&'a T), + /// + RefMut(&'a mut T), +} - /* +impl<'a, T> AstResult<'a, T> { + #[inline(always)] + pub(crate) fn unwrap_val(self) -> T { + match self { + AstResult::Value(val) => val, + _ => unreachable!("AstResult return type should be known"), + } + } +} - // TODO: instead of transmuting cb in DeSeed, transmute it in Select - (@selector_seed_codec_deseed_newtype - { $($generics:tt)* } { $($bounds:tt)* } - // TODO: this should probably by a ty - $ty:ident as $inner_ty:ty - ) => { - $crate::dev::macros::impl_selector_seed_serde! { - @selector_seed_codec_deseed { $($generics)* } { $($bounds)* } $ty - { - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - if _RK { - unimplemented!() - } else { - let inner_seed = macros::impl_selector_seed_serde! { - @selector_seed_wrap - // TODO: probably need to pass a closure - self { $ty => $inner_ty } - }; +impl<'a, const MC: u64, Ctx, T> AstWalk<'a, MC, Ctx, T> +where + T: Representation, +{ + #[inline(always)] + fn into_inner(self) -> SelectorSeed<'a, Ctx, T> { + self.0 + } + #[inline(always)] + fn selector(&self) -> &Selector { + self.0.selector + } + #[inline(always)] + fn mode(&self) -> SelectionMode { + self.0._mode() + } +} - // cfg_if::cfg_if! { - // if #[cfg(feature = "serde-codec")] { - // // (&mut &mut &mut Decoder(deserializer)).deserialize_any(self) - // inner_seed.deserialize((&mut &mut &mut Decoder(deserializer))) - // } else { - // // deserializer.deserialize_any(self) - // inner_seed.deserialize(deserializer) - // } - // } +impl<'a, const MC: u64, Ctx, T> AsRef> for AstWalk<'a, MC, Ctx, T> { + #[inline(always)] + fn as_ref(&self) -> &SelectorSeed<'a, Ctx, T> { + &self.0 + } +} +impl<'a, const MC: u64, Ctx, T> AsMut> for AstWalk<'a, MC, Ctx, T> { + #[inline(always)] + fn as_mut(&mut self) -> &mut SelectorSeed<'a, Ctx, T> { + &mut self.0 + } +} +impl<'a, const MC: u64, Ctx, T> From> for AstWalk<'a, MC, Ctx, T> { + #[inline(always)] + fn from(seed: SelectorSeed<'a, Ctx, T>) -> Self { + Self(seed) + } +} - // inner_seed.deserialize::(deserializer) - inner_seed.deserialize(deserializer) - } - } - }} - }; - // produces an seed for the inner_ty, providing the original cb with ty - // (@selector_seed_wrap $seed:ident { $constructor:expr => $inner_ty:ty }) => {{ - // use $crate::dev::{DagSelection, Callback::*}; +impl<'de, 'a: 'de, const MC: u64, Ctx, T: Representation> DeserializeSeed<'de> + for AstWalk<'a, MC, Ctx, T> +where + Self: LinkVisitor<'de, MC>, + T: Representation, +{ + type Value = >::Value; - // let SelectorSeed { selector, state, callback, ctx } = $seed.0; - // let callback = match callback { - // SelectDag { mut cb } => SelectDag { - // cb: Box::new(move |selection, ctx| { - // let inner_dag = selection.dag.downcast::<$inner_ty>()?; - // let dag = $constructor(inner_dag.into()); - // cb(DagSelection { dag: dag.into(), ..selection }, ctx) - // }), - // }, - // cb => cb.clone(), - // _ => unreachable!(), - // }; - // Self::from(SelectorSeed { selector, state, callback, ctx }) - // }}; + #[inline] + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::deserialize_with_visitor::(deserializer, self) + } +} - // (@empty $seed:ident $constructor:expr => $inner_ty:tt) => { unimplemented!() }; - // TODO: deprecate, since we want SelectorSeed to do all the heavy-lifting - // (@select_newtype - // { $($generics:tt)* } { $($bounds:tt)* } - // $ty:ident as $inner_ty:ident - // ) => { - // /// Delegates directly to the inner type's [`Select`] implmentation, - // /// wrapping the provided callbacks to ensure the expected types are - // /// selected. - // /// - // /// [`Select`]: crate::dev::Select - // impl $crate::dev::Select for $ty - // where - // Ctx: $crate::dev::Context, - // $inner_ty: $crate::dev::Select, - // $($bounds)* - // { - // fn select( - // params: $crate::dev::Params<'_, Ctx, Self>, - // ctx: &mut Ctx, - // ) -> Result<(), $crate::dev::Error> { - // use $crate::dev::Callback::*; +// impl<'de, 'a: 'de, const MC: u64, Ctx, T> DeserializeSeed<'de> for AstWalk<'a, MC, Ctx, T> +// where +// Self: LinkVisitor<'de, MC, Value = AstResult>, +// T: Representation, +// { +// type Value = AstResult; - // let params = $crate::dev::Params::<'_, Ctx, $inner_ty> { - // cid: params.cid, - // selector: params.selector, - // max_path_depth: params.max_path_depth, - // max_link_depth: params.max_link_depth, - // callback: match params.callback { - // SelectNode { cb, only_matched } => SelectNode { cb, only_matched }, - // SelectDag { mut cb } => SelectDag { - // cb: Box::new(move |selection, ctx| { - // let dag = selection.dag.downcast::<$inner_ty>()?; - // let selection = $crate::dev::DagSelection { - // dag: Self(dag).into(), - // ..selection - // }; - // cb(selection, ctx) - // }), - // }, - // _ => unreachable!(), - // }, - // }; +// #[inline] +// fn deserialize(self, deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// T::deserialize_with_visitor::(deserializer, self) +// } +// } - // <$inner_ty>::select(params, ctx) - // } - // } - // }; +// impl<'de, const C: u64, S, T: Representation> DeserializeSeed<'de> for S +// where +// S: Visitor<'de, Value = > + LinkVisitor<'de>, +// T: Representation, +// { +// type Value = >::Value; - // (visit_self - // { $($generics:tt)* } { $($bounds:tt)* } - // $type:ty - // { $($visit_fn:tt)* } - // { $($flush_fn:tt)* } - // ) => { - // impl $crate::dev::Visit for $type - // where - // Ctx: $crate::dev::Context, - // $($bounds)* - // { - // // #[inline] - // // fn r#match( - // // selector: &$crate::dev::Selector, - // // state: $crate::dev::SelectorState, - // // ctx: &mut Ctx - // // ) -> Result, $crate::dev::Error> { - // // let deserializer = ctx.path_decoder(state.path())?; - // // $crate::dev::SelectorSeed::<'_, Ctx, Self, Self>::from(selector, state, ctx) - // // .deserialize(deserializer) - // // .map_err($crate::dev::Error::decoder) - // // } - // - // fn visit( - // &mut self, - // selector: &$crate::dev::Selector, - // state: $crate::dev::SelectorState, - // ctx: &mut Ctx, - // op: F, - // ) -> Result<(), $crate::dev::Error> - // where - // F: Fn(T, &mut Ctx) -> Result, $crate::dev::Error>, - // { - // unimplemented!() - // } - // - // fn flush( - // &mut self, - // selector: &$crate::dev::Selector, - // state: $crate::dev::SelectorState, - // ctx: &mut Ctx, - // ) -> Result<(), $crate::dev::Error> { - // unimplemented!() - // } - // } - // }; - */ -} +// #[inline] +// fn deserialize(self, deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// T::deserialize_with_visitor::(deserializer, self) +// } +// } diff --git a/src/select/selectors.rs b/src/select/selectors.rs index 1189abf..43308e3 100644 --- a/src/select/selectors.rs +++ b/src/select/selectors.rs @@ -1,12 +1,17 @@ use crate::dev::*; use macros::derive_more::{AsMut, AsRef, From, TryInto}; use maybestd::{ + boxed::Box, fmt, ops::{Bound, Range, RangeBounds, RangeFrom, RangeInclusive}, rc::Rc, str::FromStr, }; +/// +#[cfg_attr(feature = "dev", doc(hidden))] +pub static DEFAULT_SELECTOR: Selector = Selector::DEFAULT; + schema! { /// SelectorEnvelope is the recommended top-level value for serialized /// messages that don't have established existing context with marks the @@ -33,29 +38,29 @@ schema! { /// | Matcher "." /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreAll "a" /// | ExploreFields "f" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreIndex "i" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreRange "r" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreRecursive "R" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreUnion "|" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreConditional "&" /// | ExploreRecursiveEdge "@" /// - #[ipld_attr(wrapper = "Rc")] + #[ipld_attr(wrapper = "Box")] | ExploreInterpretAs "~" } representation keyed } @@ -80,7 +85,7 @@ schema! { /// be represented as a set of three nexted ExploreFields selectors, each /// specifying one field. #[ipld_attr(internal)] - #[derive(Clone, Debug, From)] + #[derive(Clone, Debug, Default, From)] pub type ExploreFields struct { // fields {String:Selector} (rename "f>"), } @@ -90,7 +95,7 @@ schema! { /// ExploreIndex traverses a specific index in a list, and applies a next /// selector to the reached node. #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] pub type ExploreIndex struct { index Int (rename "i") next Selector (rename ">") @@ -101,7 +106,7 @@ schema! { /// ExploreRange traverses a list, and for each element in the range /// specified, will apply a next selector to those reached nodes. #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] pub type ExploreRange struct { start Int (rename "^") end Int (rename "$") @@ -151,7 +156,7 @@ schema! { /// be used to let the selector know where to stop recursing preventing from /// having to traverse the full structure. #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] pub type ExploreRecursive struct { /// pub sequence Selector (rename ":>") @@ -176,13 +181,13 @@ schema! { schema! { /// #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] pub type RecursionLimit_None struct {} } schema! { /// #[ipld_attr(internal)] - #[derive(Clone, Debug, From)] + #[derive(Clone, Debug, Default, From)] #[from(forward)] pub type RecursionLimit_Depth int } @@ -198,7 +203,7 @@ schema! { /// ExploreRecursiveEdge is valid. An ExploreRecursiveEdge without an /// enclosing ExploreRecursive is an error. #[ipld_attr(internal)] - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] pub type ExploreRecursiveEdge struct {} } @@ -211,11 +216,11 @@ schema! { /// simultaneously continuing to explore deeper parts of the tree with /// another selector, for example. #[ipld_attr(internal)] - #[derive(Clone, Debug + #[derive(Clone, Debug, Default, // From )] - pub type ExploreUnion null; - // pub type ExploreUnion [Selector]; + pub type ExploreUnion null + // pub type ExploreUnion [Selector] } schema! { @@ -515,6 +520,7 @@ impl Selector { /// Attempts to produce the next selector to apply, given an optional field /// (key or index). /// TODO: matcher is infinite; need to distinguish link boundaries + /// TODO: should return Option<&Selector> pub fn try_next<'a>(&self, field: Option<&Field<'_>>) -> Result<&Selector, Error> { match (self, field) { (Self::Matcher(_), _) => Ok(self), @@ -526,7 +532,7 @@ impl Selector { } (Self::ExploreRange(inner), Some(f)) if f.as_usize() - .filter(|idx| inner.to_range().contains(idx)) + .filter(|idx| inner.contains(&(*idx as Int))) .is_some() => { Ok(&inner.next) @@ -569,7 +575,7 @@ impl Default for Selector { } } -// TODO +// TODO for all impl fmt::Display for Selector { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { Ok(()) @@ -685,6 +691,12 @@ impl ExploreRecursive { pub const CODE: char = 'R'; } +impl Default for RecursionLimit { + fn default() -> Self { + Self::RecursionLimit_None(RecursionLimit_None {}) + } +} + /* ExploreUnion */ impl ExploreUnion { diff --git a/src/select/state.rs b/src/select/state.rs index 03f811e..c10e038 100644 --- a/src/select/state.rs +++ b/src/select/state.rs @@ -114,136 +114,158 @@ pub(crate) use callbacks::*; mod callbacks { use super::*; - /// - pub trait SelectNodeOp: FnMut(NodeSelection, &mut C) -> Result<(), Error> { + pub use match_dag::*; + pub use patch_dag::*; + pub use select_dag::*; + pub use select_node::*; + + mod select_node { + use super::*; + /// - fn clone_box<'a>(&self) -> Box + 'a> - where - Self: 'a; - } + pub trait SelectNodeOp: FnMut(NodeSelection, &mut C) -> Result<(), Error> { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } - impl SelectNodeOp for F - where - F: FnMut(NodeSelection, &mut C) -> Result<(), Error> + Clone, - { - fn clone_box<'a>(&self) -> Box + 'a> + impl SelectNodeOp for F where - Self: 'a, + F: FnMut(NodeSelection, &mut C) -> Result<(), Error> + Clone, { - Box::new(self.clone()) + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } } - } - impl<'a, C> Clone for Box + 'a> - where - C: 'a, - { - fn clone(&self) -> Self { - (**self).clone_box() + impl<'a, C> Clone for Box + 'a> + where + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } } } + mod select_dag { + use super::*; - /// - pub trait SelectDagOp: FnMut(DagSelection, &mut C) -> Result<(), Error> { /// - fn clone_box<'a>(&self) -> Box + 'a> - where - Self: 'a; - } + pub trait SelectDagOp: FnMut(DagSelection, &mut C) -> Result<(), Error> { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } - impl SelectDagOp for F - where - F: FnMut(DagSelection, &mut C) -> Result<(), Error> + Clone, - { - fn clone_box<'a>(&self) -> Box + 'a> + impl SelectDagOp for F where - Self: 'a, + F: FnMut(DagSelection, &mut C) -> Result<(), Error> + Clone, { - Box::new(self.clone()) + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } } - } - impl<'a, C> Clone for Box + 'a> - where - C: 'a, - { - fn clone(&self) -> Self { - (**self).clone_box() + impl<'a, C> Clone for Box + 'a> + where + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } } } + mod match_dag { + use super::*; - /// - pub trait MatchDagOp: FnMut(T, &mut C) -> Result<(), Error> { /// - fn clone_box<'a>(&self) -> Box + 'a> - where - Self: 'a; - } + pub trait MatchDagOp: FnMut(T, &mut C) -> Result<(), Error> { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } - impl MatchDagOp for F - where - F: FnMut(T, &mut C) -> Result<(), Error> + Clone, - { - fn clone_box<'a>(&self) -> Box + 'a> + impl MatchDagOp for F where - Self: 'a, + F: FnMut(T, &mut C) -> Result<(), Error> + Clone, { - Box::new(self.clone()) + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } } - } - impl<'a, T, C> Clone for Box + 'a> - where - T: 'a, - C: 'a, - { - fn clone(&self) -> Self { - (**self).clone_box() + impl<'a, T, C> Clone for Box + 'a> + where + T: 'a, + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } } } + mod patch_dag { + use super::*; - /// - pub trait PatchDagOp: FnMut(&mut T, &mut C) -> Result { /// - fn clone_box<'a>(&self) -> Box + 'a> - where - Self: 'a; - } + pub trait PatchDagOp: FnMut(&mut T, &mut C) -> Result { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } - impl PatchDagOp for F - where - F: FnMut(&mut T, &mut C) -> Result + Clone, - { - fn clone_box<'a>(&self) -> Box + 'a> + impl PatchDagOp for F where - Self: 'a, + F: FnMut(&mut T, &mut C) -> Result + Clone, { - Box::new(self.clone()) + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } } - } - impl<'a, T, C> Clone for Box + 'a> - where - T: 'a, - C: 'a, - { - fn clone(&self) -> Self { - (**self).clone_box() + impl<'a, T, C> Clone for Box + 'a> + where + T: 'a, + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } } } /// + /// TODO: merge this back with state #[doc(hidden)] pub enum Callback<'a, C, T> { SelectNode { + // state cb: Box + 'a>, only_results: bool, }, SelectDag { + // state // TODO: does this need to be cloneable? it is either called on U, or wrapped cb: Box + 'a>, }, MatchDag { + // Option; if None, deserializes up to links cb: Box + 'a>, }, Patch { @@ -451,24 +473,32 @@ mod callbacks { // } */ + pub(crate) fn cover_node( + &mut self, + path: &Path, + selected_node: SelectedNode, + ctx: &mut C, + ) -> Result<(), Error> { + match self { + Self::SelectNode { cb, only_results } if !*only_results => { + cb(NodeSelection::covered(path, selected_node), ctx) + } + _ => Ok(()), + } + } + pub(crate) fn select_node( &mut self, path: &Path, selected_node: SelectedNode, - is_result: bool, label: Option<&str>, ctx: &mut C, ) -> Result<(), Error> { match self { - Self::SelectNode { cb, .. } if is_result => { + Self::SelectNode { cb, .. } => { cb(NodeSelection::result(path, selected_node, label), ctx) } - Self::SelectNode { cb, only_results } if !*only_results => { - cb(NodeSelection::covered(path, selected_node), ctx) - } - Self::SelectNode { .. } => Ok(()), - Self::SelectDag { .. } => Ok(()), - _ => unreachable!(), + _ => Ok(()), } } @@ -612,7 +642,7 @@ impl State { &mut self, // next_selector: Selector, next_path: &Field<'_>, - ) -> Result<(), Error> { + ) -> Result<&mut Self, Error> { if self.path_depth >= self.max_path_depth() { return Err(Error::SelectorDepth( "descending would exceed max path depth", @@ -627,39 +657,23 @@ impl State { } next_path.append_to_path(&mut self.path); - self.path_depth = self - .path_depth - .checked_add(1) - .ok_or_else(|| Error::SelectorDepth("exceeds root path depth", self.path_depth))?; - if T::IS_LINK { - self.link_depth = self - .link_depth - .checked_sub(1) - .ok_or_else(|| Error::SelectorDepth("exceeds root link depth", self.link_depth))?; + self.path_depth += 1; + if T::DATA_MODEL_KIND.is_link() { + self.link_depth += 1; } - Ok(()) + Ok(self) } #[inline] pub(crate) fn ascend( &mut self, // previous_selector: Selector, - ) -> Result<(), Error> { + ) { self.path.pop(); - self.path_depth = self - .path_depth - .checked_sub(1) - .ok_or_else(|| Error::SelectorDepth("exceeds root path depth", self.path_depth))?; - - if T::IS_LINK { - self.link_depth = self - .link_depth - .checked_sub(1) - .ok_or_else(|| Error::SelectorDepth("exceeds root link depth", self.link_depth))?; + self.path_depth -= 1; + if T::DATA_MODEL_KIND.is_link() { + self.link_depth -= 1; } - - // self.selector = previous_selector; - Ok(()) } } From fa10f25e8072480a1244c8f873feb6e5b7a112b5 Mon Sep 17 00:00:00 2001 From: sunny-g Date: Sun, 25 Dec 2022 13:24:28 -0600 Subject: [PATCH 9/9] stash; gonna try impl DeSeed for &mut AstWalk --- macros-internals/src/schema/expand.rs | 74 +- macros-internals/src/schema/mod.rs | 2 +- .../src/schema/union/expand_kinded.rs | 26 +- macros-internals/src/schema2/mod.rs | 76 +- .../src/schema2/representation.rs | 113 ++- macros-internals/src/schema2/select.rs | 60 +- macros/src/lib.rs | 13 +- src/codecs/dag_cbor.rs | 10 +- src/codecs/dag_json.rs | 4 +- src/codecs/mod.rs | 21 + src/compat/core.rs | 210 ++++- src/data_model/any.rs | 25 + src/data_model/link.rs | 25 +- src/data_model/list.rs | 270 ++++--- src/data_model/map.rs | 150 ++-- src/data_model/mod.rs | 52 +- src/data_model/primitive.rs | 235 +++--- src/error.rs | 17 +- src/lib.rs | 3 +- src/multicodec.rs | 6 +- src/representation/mod.rs | 26 +- src/representation/strategies/listpairs.rs | 45 +- src/representation/strategies/mod.rs | 717 ++++++++++++++---- src/representation/strategies/tuple.rs | 45 +- src/select/context.rs | 38 + src/select/mod.rs | 467 ++++++++---- src/select/seed.rs | 695 ++++++++++++----- src/select/selectors.rs | 78 +- src/select/state.rs | 359 ++++++--- tests/codec-fixtures.rs | 14 +- 30 files changed, 2774 insertions(+), 1102 deletions(-) diff --git a/macros-internals/src/schema/expand.rs b/macros-internals/src/schema/expand.rs index 619c6a7..c1b8e2f 100644 --- a/macros-internals/src/schema/expand.rs +++ b/macros-internals/src/schema/expand.rs @@ -138,19 +138,24 @@ pub(crate) trait ExpandBasicRepresentation { } fn impl_select(&self, meta: &SchemaMeta, rest: Option) -> TokenStream { - let methods = rest.unwrap_or(quote::quote! { - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - Seed::::from(seed).deserialize(deserializer) - } - }); + let walker = quote::quote! { + // ::Walker::<'de, MC> + AstWalk::<'__a, MC, Ctx, Self> + }; + // let methods = rest.unwrap_or(quote::quote! { + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const MC: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // #walker::from(seed).deserialize(deserializer)?; + // Ok(()) + // } + // }); let name = &meta.name; // let (impl_gen, ty_gen, where_gen) = match &meta.generics { @@ -163,7 +168,8 @@ pub(crate) trait ExpandBasicRepresentation { where Ctx: Context, { - #methods + type Walker<'__a, const MC: u64> = #walker where Ctx: '__a; + // #methods } } } @@ -315,27 +321,27 @@ macro_rules! derive_newtype { (@select $def:ident, $meta:ident => $inner_ty:ident) => {{ let name = &$meta.name; $def.impl_select($meta, Some(quote::quote! { - #[doc(hidden)] - #[inline] - fn __select<'a>( - seed: SelectorSeed<'a, Ctx, Self>, - ) -> Result<(), Error> { - let seed = seed.wrap::<#$inner_ty, _>(#name); - <#$inner_ty as Select>::__select(seed) - } + // #[doc(hidden)] + // #[inline] + // fn __select<'a>( + // seed: SelectorSeed<'a, Ctx, Self>, + // ) -> Result<(), Error> { + // let seed = seed.wrap::<#$inner_ty, _>(#name); + // <#$inner_ty as Select>::__select(seed) + // } - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - let seed = seed.wrap::<#$inner_ty, _>(#name); - <#$inner_ty as Select>::__select_de::(seed, deserializer) - } + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const MC: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // let seed = seed.wrap::<#$inner_ty, _>(#name); + // <#$inner_ty as Select>::__select_de::(seed, deserializer) + // } })) }}; (@conv @has_constructor $def:ident, $meta:ident) => {{ diff --git a/macros-internals/src/schema/mod.rs b/macros-internals/src/schema/mod.rs index e3ac7d8..4423b90 100644 --- a/macros-internals/src/schema/mod.rs +++ b/macros-internals/src/schema/mod.rs @@ -60,7 +60,7 @@ impl SchemaMeta { #r#extern #[allow(clippy::useless_attribute)] use __ipld::dev::*; - __ipld::repr_serde!(@def_seed); + __ipld::repr_serde!(@def_walk); } } diff --git a/macros-internals/src/schema/union/expand_kinded.rs b/macros-internals/src/schema/union/expand_kinded.rs index fdb0c06..6ff8697 100644 --- a/macros-internals/src/schema/union/expand_kinded.rs +++ b/macros-internals/src/schema/union/expand_kinded.rs @@ -82,18 +82,24 @@ impl ExpandBasicRepresentation for KindedUnionReprDefinition { } } #[inline] - fn deserialize<'de, const MC: u64, De: Deserializer<'de>>(de: De) -> Result { + fn deserialize<'de, const MC: u64, De>(de: De) -> Result + where + De: Deserializer<'de> + { struct V; impl<'de, const MC: u64> Visitor<'de> for V { - type Value = #name; + type Value = AstResult<#name>; + #expecting + #(#non_link_visitors)* } impl<'de, const MC: u64> LinkVisitor<'de, MC> for V { #(#link_visitors)* } - Multicodec::deserialize_any::(de, V::) + let res = Multicodec::deserialize_any::(de, V::)?; + Ok(res.unwrap_val()) } }, ) @@ -132,11 +138,11 @@ impl KindedUnionReprDefinition { } fn expecting(&self, meta: &SchemaMeta) -> TokenStream { - let name = &meta.name; + let name = &meta.name.to_string(); quote! { #[inline] fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { - write!(f, "A `{}`", stringify!(#name)) + write!(f, "A `{}`", #name) } } } @@ -295,6 +301,7 @@ impl UnionKindedField { let seed = self .into_inner() .wrap::<#ty, _>(|dag: #ty| #name::#variant(dag.into())); + <#ty>::__select_de::(seed, #deserializer) } } else { @@ -314,7 +321,8 @@ impl UnionKindedField { where A: serde::de::SeqAccess<'de> { - #visit_impl + // { #visit_impl }?; + Ok(AstResult::Ok) } }, SchemaKind::Map => quote! { @@ -323,7 +331,8 @@ impl UnionKindedField { where A: serde::de::MapAccess<'de> { - #visit_impl + // { #visit_impl }?; + Ok(AstResult::Ok) } }, _ => quote! { @@ -332,7 +341,8 @@ impl UnionKindedField { where E: serde::de::Error { - #visit_impl + // { #visit_impl }?; + Ok(AstResult::Ok) } }, }) diff --git a/macros-internals/src/schema2/mod.rs b/macros-internals/src/schema2/mod.rs index 1d29b96..c12d61e 100644 --- a/macros-internals/src/schema2/mod.rs +++ b/macros-internals/src/schema2/mod.rs @@ -8,8 +8,10 @@ mod representation; mod select; +mod typedefs; pub use representation::{DeriveRepresentation, ReprKind, SchemaKind}; +pub use select::DeriveSelect; use crate::dev::*; use darling::{ @@ -55,11 +57,23 @@ macro_rules! proc_macro_compat { }); } } + + impl $t { + fn body(&self) -> TokenStream { + match self.schema_kind().unwrap() { + SchemaKind::Null => self.expand_null(), + SchemaKind::Struct(ref repr) => self.expand_struct(repr), + SchemaKind::Enum => self.expand_enum(), + SchemaKind::Union(ref repr) => self.expand_union(repr), + SchemaKind::Copy => self.expand_newtype(), + } + } + } }; } proc_macro_compat!(DeriveRepresentation); -// proc_macro_compat!({ 'S' as u64 }); +proc_macro_compat!(DeriveSelect); // #[derive(Clone, Debug, FromDeriveInput)] // #[darling( @@ -78,7 +92,7 @@ proc_macro_compat!(DeriveRepresentation); #[derive(Clone, Debug, FromDeriveInput)] #[darling(attributes(ipld), forward_attrs(cfg, repr), supports(any))] pub struct Ipld { - vis: Visibility, + // vis: Visibility, ident: Ident, // generics: ast::Generics, generics: Generics, @@ -93,9 +107,32 @@ pub struct Ipld { repr_kind: SpannedValue, #[darling(default, rename = "where_ctx")] where_ctx: Option>, - #[darling(default, rename = "merge")] - merge: Option, - // include: Option>, + // #[darling(default, rename = "merge")] + // merge: Option, +} + +// enum +impl Ipld { + fn discriminant(&self) -> Option<&Expr> { + self.data + .as_ref() + .take_enum() + .and_then(|v| v[0].discriminant.as_ref()) + } +} + +// struct +impl Ipld { + fn fields(&self) -> impl Iterator { + self.data.as_ref().take_struct().unwrap().into_iter() + } +} + +// union +impl Ipld { + fn variants(&self) -> impl Iterator { + self.data.as_ref().take_enum().unwrap().into_iter() + } } impl Ipld { @@ -107,17 +144,16 @@ impl Ipld { self.into_token_stream() } - fn discriminant(&self) -> Option<&Expr> { - self.data - .as_ref() - .take_enum() - .and_then(|v| v[0].discriminant.as_ref()) + fn imports(&self) -> TokenStream { + SchemaMeta::imports(self.internal) } - fn fields(&self) -> impl Iterator { - self.data.as_ref().take_struct().unwrap().into_iter() + fn scope(&self) -> Ident { + Ident::new(&format!("_{}_FOR_{}", T, &self.ident), Span::call_site()) } +} +impl Ipld { fn schema_kind(&self) -> Result { use ReprKind::*; use SchemaKind::*; @@ -157,12 +193,14 @@ impl Ipld { } impl Ipld { - fn imports(&self) -> TokenStream { - SchemaMeta::imports(self.internal) - } - - fn scope(&self) -> Ident { - Ident::new(&format!("_{}_FOR_{}", T, &self.ident), Span::call_site()) + pub(crate) fn expecting(&self) -> TokenStream { + let name = &self.ident; + quote! { + #[inline] + fn expecting(&self, f: &mut maybestd::fmt::Formatter<'_>) -> maybestd::fmt::Result { + write!(f, "A `{}`", stringify!(#name)) + } + } } } @@ -203,6 +241,8 @@ pub struct IpldVariant { // attrs #[darling(default)] wrapper: Option, + // #[darling(default)] + rename: Option, } #[derive(Clone, Debug, FromMeta)] diff --git a/macros-internals/src/schema2/representation.rs b/macros-internals/src/schema2/representation.rs index 9552020..79acf96 100644 --- a/macros-internals/src/schema2/representation.rs +++ b/macros-internals/src/schema2/representation.rs @@ -73,16 +73,11 @@ impl DeriveRepresentation { pub(crate) fn derive(&self) -> TokenStream { let name = &self.ident; let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); - let body = match self.schema_kind().unwrap() { - SchemaKind::Null => self.expand_null(), - SchemaKind::Struct(_) => Default::default(), - SchemaKind::Enum => Default::default(), - SchemaKind::Union(_) => Default::default(), - SchemaKind::Copy => self.expand_newtype(), - }; + let body = self.body(); quote! { - impl #impl_generics Representation for #name #ty_generics #where_clause { + impl #impl_generics Representation for #name #ty_generics + #where_clause { #body } } @@ -175,7 +170,7 @@ impl DeriveRepresentation { } } - fn expand_map(&self) -> TokenStream { + pub(crate) fn expand_struct(&self, repr: &ReprKind) -> TokenStream { let name = &self.ident; let inner = &self.fields().next().unwrap().ty; let schema = { @@ -230,17 +225,107 @@ impl DeriveRepresentation { } } } + + pub(crate) fn expand_enum(&self) -> TokenStream { + Default::default() + } + + pub(crate) fn expand_union(&self, repr: &ReprKind) -> TokenStream { + let name = &self.ident; + let schema = self.to_string(); + + let expecting = self.expecting(); + + quote! { + const NAME: &'static str = stringify!(#name); + const SCHEMA: &'static str = #schema; + // todo: + const DATA_MODEL_KIND: Kind = Kind::Null; + const SCHEMA_KIND: Kind = Kind::Union; + const REPR_KIND: Kind = Kind::Any; + const REPR_STRATEGY: Strategy = Strategy::Kinded; + // todo: + const HAS_LINKS: bool = false; + + #[inline] + fn name(&self) -> &'static str { + unimplemented!() + } + #[inline] + fn has_links(&self) -> bool { + unimplemented!() + } + #[inline] + fn as_field(&self) -> Option> { + unimplemented!() + } + #[inline] + fn to_selected_node(&self) -> SelectedNode { + unimplemented!() + } + #[inline] + fn serialize(&self, serializer: __S) -> Result<__S::Ok, __S::Error> + where + __S: Serializer, + { + match self { + _ => unimplemented!(), + } + } + #[inline] + fn deserialize<'de, const __C: u64, __D>(de: __D) -> Result + where + __D: Deserializer<'de>, + { + struct V; + impl<'de, const MC: u64> Visitor<'de> for V { + type Value = #name; + #expecting + // #(#non_link_visitors)* + } + impl<'de, const MC: u64> LinkVisitor<'de, MC> for V { + // #(#link_visitors)* + } + + Multicodec::deserialize_any::<__C, __D, _>(de, V::<__C>) + } + } + } } impl fmt::Display for DeriveRepresentation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.schema_kind().or(Err(fmt::Error))? { SchemaKind::Null => write!(f, "type {} null", &self.ident), - SchemaKind::Struct(repr) => unimplemented!(), - SchemaKind::Enum => unimplemented!(), - SchemaKind::Union(repr) => unimplemented!(), - SchemaKind::Copy => unimplemented!(), - _ => unimplemented!(), + SchemaKind::Copy => write!( + f, + "type {} = {:?}", + &self.ident, + &self.fields().next().unwrap().ty + ), + SchemaKind::Enum => write!(f, "unimplemented"), + SchemaKind::Struct(repr) => match repr { + _ => write!(f, "unimplemented"), + }, + SchemaKind::Union(repr) => match repr { + ReprKind::Kinded => { + write!(f, "type {} union {{\n", &self.ident)?; + for variant in self.variants() { + // todo: add dm kind + write!(f, "| {}", &variant.ident,)?; + } + write!(f, "}}") + } + ReprKind::Keyed => { + write!(f, "type {} union {{\n", &self.ident)?; + for variant in self.variants() { + write!(f, "| {} \"{:?}\"", &variant.ident, &variant.rename)?; + } + write!(f, "}}") + } + _ => write!(f, "unimplemented"), + }, + _ => write!(f, "unimplemented"), } } } diff --git a/macros-internals/src/schema2/select.rs b/macros-internals/src/schema2/select.rs index 5378aee..f06f755 100644 --- a/macros-internals/src/schema2/select.rs +++ b/macros-internals/src/schema2/select.rs @@ -15,20 +15,74 @@ use syn::{ pub const CODE: u64 = 'S' as u64; -impl Ipld { +pub type DeriveSelect = Ipld; + +impl DeriveSelect { fn validate(&self) -> ParseResult<()> { Ok(()) } pub(crate) fn derive(&self) -> TokenStream { - Default::default() + let name = &self.ident; + + let select = { + let body = self.body(); + let (impl_generics, ty_generics, where_clause) = { + let (_, ty_generics, where_clause) = self.generics.split_for_impl(); + let impl_generics = quote! { + <__Ctx: Context> + }; + (impl_generics, ty_generics, where_clause) + }; + quote! { + impl #impl_generics Select<__Ctx> for #name #ty_generics + #where_clause { + type Walker<'__a, const MC: u64> = AstWalk<'__a, MC, __Ctx, Self>; + #body + } + } + }; + + let visitor: TokenStream = { + match self.schema_kind().unwrap() { + // SchemaKind::Null => self.expand_null_visitor(), + // SchemaKind::Struct(ref repr) => unimplemented!(), + // SchemaKind::Enum => self.expand_enum(), + // SchemaKind::Union(ref repr) => self.expand_union(repr), + // SchemaKind::Copy => self.expand_newtype(), + _ => Default::default(), + } + }; + + quote! { + #visitor + #select + } } pub(crate) fn expand_null(&self) -> TokenStream { - Default::default() + quote! {} + } + + pub(crate) fn expand_null_visitor(&self) -> TokenStream { + quote! {} } pub(crate) fn expand_newtype(&self) -> TokenStream { Default::default() } + + pub(crate) fn expand_struct(&self, repr: &ReprKind) -> TokenStream { + Default::default() + } + + pub(crate) fn expand_enum(&self) -> TokenStream { + Default::default() + } + + pub(crate) fn expand_union(&self, repr: &ReprKind) -> TokenStream { + let name = &self.ident; + + quote! {} + } } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 26627a3..7544444 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -7,7 +7,8 @@ extern crate proc_macro; use ipld_macros_internals::{ - schema2::DeriveRepresentation, RootSelectorDefinition, SchemaDefinition, + schema2::{DeriveRepresentation, DeriveSelect}, + RootSelectorDefinition, SchemaDefinition, }; use proc_macro::TokenStream; use syn::parse_macro_input; @@ -47,11 +48,11 @@ pub fn derive_representation(input: TokenStream) -> TokenStream { .into() } -// #[proc_macro_derive(Select, attributes(ipld))] -// pub fn derive_select(input: TokenStream) -> TokenStream { -// parse_macro_input!(input as DeriveSelect).expand().into() -// } -// +#[proc_macro_derive(Select, attributes(ipld))] +pub fn derive_select(input: TokenStream) -> TokenStream { + parse_macro_input!(input as DeriveSelect).expand().into() +} + // #[proc_macro_derive(Patch, attributes(ipld))] // pub fn derive_patch(input: TokenStream) -> TokenStream { // parse_macro_input!(input as DerivePatch).expand().into() diff --git a/src/codecs/dag_cbor.rs b/src/codecs/dag_cbor.rs index 21ae62d..ed5323d 100644 --- a/src/codecs/dag_cbor.rs +++ b/src/codecs/dag_cbor.rs @@ -85,6 +85,7 @@ impl DagCbor { // deserializer.deserialize_bytes(DagCborVisitor::<'l', _>(visitor)) } + /// todo: refactor to (DeSeed and reader) => seed.deserialize(from(reader)) #[doc(hidden)] #[inline] pub fn read_with_seed(seed: SelectorSeed<'_, Ctx, T>, reader: R) -> Result<(), Error> @@ -94,7 +95,14 @@ impl DagCbor { R: Read, { let mut de = CborDeserializer::from_reader(reader); - T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) + // T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) + + // todo: requires T::Walk + // T::deserialize_with_visitor::<'_, ::CODE, _, _>(&mut de, seed) + // .map(AstResult::unwrap_val) + // .map_err(Error::decoder) + + unimplemented!() } // pub(crate) fn deserializer_from_reader( diff --git a/src/codecs/dag_json.rs b/src/codecs/dag_json.rs index fbc4583..e8af577 100644 --- a/src/codecs/dag_json.rs +++ b/src/codecs/dag_json.rs @@ -111,7 +111,9 @@ impl DagJson { R: Read, { let mut de = JsonDeserializer::from_reader(reader); - T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) + // T::__select_de::<{ ::CODE }, _>(seed, &mut de).map_err(Error::decoder) + + unimplemented!() } } diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index 696db8f..f7fb4ca 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -179,6 +179,27 @@ pub trait LinkVisitor<'de, const MC: u64 = IDENTITY>: Visitor<'de> { Err(E::invalid_type(de::Unexpected::Other("Cid"), &self)) } + // fn visit_dag(self, _: T) -> Result + // where + // E: serde::de::Error, + // { + // unimplemented!() + // } + + // fn visit_ref(self, _: &T) -> Result + // where + // E: serde::de::Error, + // { + // unimplemented!() + // } + + // fn visit_ref_mut(self, _: &T) -> Result + // where + // E: serde::de::Error, + // { + // unimplemented!() + // } + //////////////////////////////////////////////////////////////////////// // Visitor API from serde //////////////////////////////////////////////////////////////////////// diff --git a/src/compat/core.rs b/src/compat/core.rs index bb2b8b8..ff8c318 100644 --- a/src/compat/core.rs +++ b/src/compat/core.rs @@ -53,7 +53,7 @@ mod ignored { where E: de::Error, { - Ok(()) + Ok(AstResult::Ok) } }} @@ -88,7 +88,7 @@ mod ignored { } repr_serde! { @select for PhantomData { T } { T: Representation }} - repr_serde! { @visitors for PhantomData { T } { T: Representation + '_a } @serde { + repr_serde! { @visitors for PhantomData { T } { T: Representation + '__a } @serde { #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", T::NAME) @@ -311,23 +311,209 @@ macro_rules! derive { } } - impl Select for $wrapper + impl<'a: 'de, 'de, const MC: u64, Ctx, T> Visitor<'de> for AstWalk<'a, MC, Ctx, $wrapper> where Ctx: Context, - T: Select + 'static, + T: Select, { - #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> + type Value = AstResult<$wrapper>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + unimplemented!() + } + + fn visit_bool(self, v: bool) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_i8(self, v: i8) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_i16(self, v: i16) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_i32(self, v: i32) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_i64(self, v: i64) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_i128(self, v: i128) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_u8(self, v: u8) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_u16(self, v: u16) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_u32(self, v: u32) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_u64(self, v: u64) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_u128(self, v: u128) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_f32(self, v: f32) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_f64(self, v: f64) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_char(self, v: char) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_borrowed_str(self, v: &'de str) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_string(self, v: String) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_byte_buf(self, v: Vec) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_none(self) -> Result + where + E: de::Error, + { + unimplemented!() + } + fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { - let seed = seed.wrap::($constructor); - T::__select_de::(seed, deserializer) + unimplemented!() + } + fn visit_unit(self) -> Result + where + E: de::Error, + { + unimplemented!() } + fn visit_newtype_struct( + self, + deserializer: D + ) -> Result + where + D: Deserializer<'de>, + { + unimplemented!() + } + fn visit_seq(self, seq: A) -> Result + where + A: SeqAccess<'de>, + { + unimplemented!() + } + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'de>, + { + unimplemented!() + } + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, + { + unimplemented!() + } + } + impl<'a: 'de, 'de, const MC: u64, Ctx, T> LinkVisitor<'de, MC> for AstWalk<'a, MC, Ctx, $wrapper> + where + Ctx: Context, + T: Select, + { + } + + impl Select for $wrapper + where + Ctx: Context, + T: Select + 'static, + { + type Walker<'a, const MC: u64> = AstWalk<'a, MC, Ctx, Self> where Ctx: 'a; + + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const C: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // let seed = seed.wrap::($constructor); + // T::__select_de::(seed, deserializer) + // } } }; /* diff --git a/src/data_model/any.rs b/src/data_model/any.rs index b2537cb..c989c86 100644 --- a/src/data_model/any.rs +++ b/src/data_model/any.rs @@ -46,6 +46,31 @@ schema! { } representation kinded; } +// #[derive( +// Clone, +// Debug, +// // From, +// PartialEq, +// // TryInto, +// // IsVariant, Unwrap +// Representation, +// Select, +// )] +// #[ipld(internal)] +// // #[from(forward)] +// // #[try_into(owned, ref, ref_mut)] +// pub enum Any { +// Null(Null), +// Bool(Bool), +// Int(Int), +// Float(Float), +// String(String), +// Bytes(Bytes), +// List(List), +// Map(Map), +// Link(Link>), +// } + // impl FromIterator for Any, (T: StringRepresentation, Any) #[cfg(feature = "dep:rkyv")] diff --git a/src/data_model/link.rs b/src/data_model/link.rs index bffda0f..2278e3b 100644 --- a/src/data_model/link.rs +++ b/src/data_model/link.rs @@ -168,18 +168,19 @@ where Ctx: Context, T: Select + 'static, { - fn select_link<'de, const C: u64>(mut self, cid: Cid) -> Result<(), Error> { - // TODO: handle "blocks encoded with rawa codec are valid Bytes kinds" - - if self.selector.is_matcher() { - if self.is_dag_select() { - self.handle_dag(Link::Id(cid))?; - } else { - self.handle_node(cid.into())?; - } - - return Ok(()); - } + fn select_link<'de, const C: u64>(mut self, link: Link) -> Result, Error> { + // TODO: handle "blocks encoded with raw codec are valid Bytes kinds" + + // if self.selector.is_matcher() { + // if self.is_select_dag() { + // self.handle_dag(Link::Id(cid))?; + // } else { + // self.handle_node(cid.into())?; + // } + + // return Ok(()); + // } + // self.match_dag(link) /// TODO: continue selection if the current selector is not a matcher unimplemented!() diff --git a/src/data_model/list.rs b/src/data_model/list.rs index 0137ab2..f603939 100644 --- a/src/data_model/list.rs +++ b/src/data_model/list.rs @@ -48,12 +48,12 @@ impl Representation for List { #[inline] #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - struct ListVisitor(PhantomData); - impl<'de, const C: u64, T> Visitor<'de> for ListVisitor + struct ListVisitor(PhantomData); + impl<'de, const MC: u64, T> Visitor<'de> for ListVisitor where T: Representation, { @@ -69,18 +69,18 @@ impl Representation for List { { let mut list = List::with_capacity(seq.size_hint().unwrap_or(8)); // let mut iter = SerdeListIterator::<'de, A>::from(seq); - // while let Some(dag) = iter.next::().map_err(A::Error::custom)? { + // while let Some(dag) = iter.next::().map_err(A::Error::custom)? { // list.push(dag); // } - while let Some(dag) = seq.next_element_seed(DeserializeRepr::::new())? { + while let Some(dag) = seq.next_element_seed(DeserializeRepr::::new())? { list.push(dag); } Ok(list) } } - deserializer.deserialize_seq(ListVisitor::(PhantomData)) + deserializer.deserialize_seq(ListVisitor::(PhantomData)) } } @@ -98,19 +98,26 @@ repr_serde! { @visitors for List { T } { T: Select + 'static } @serde { use de::value::SeqAccessDeserializer as De; match (self.mode(), self.selector()) { - (SelectionMode::Match, _) => { + (SelectionMode::Decode, _) => { let list = >::deserialize::(De::new(seq))?; - // todo: - self.into_inner().handle_dag(list).map_err(A::Error::custom) + Ok(AstResult::Value(list)) + // self.into_inner() + // .match_list::(SerdeListIterator::from(seq)) + // .map_err(A::Error::custom) + } + // (SelectionMode::Patch, _) => {} (_, Selector::ExploreUnion(s)) if s.matches_first() => { let list = >::deserialize::(De::new(seq))?; - // todo: for each selector, __select_in - list.__select_in(self.into_inner()).map_err(A::Error::custom) + // todo: for each selector, List::select + // list.__select_in(self.into_inner()).map_err(A::Error::custom)?; + Ok(AstResult::Ok) + } + _ => { + self.into_inner() + .select_list::(SeqAccessIterator::from(seq)) + .map_err(A::Error::custom) } - _ => self.into_inner() - .select_list::(SerdeListIterator::from(seq)) - .map_err(A::Error::custom) } } }} @@ -122,58 +129,49 @@ where T: Select + 'static, { /// - pub fn select_list( + pub fn select_list<'de, const MC: u64, const IN: bool, U, I>( mut self, mut iter: I, // dag: Either<&T2, I>, - ) -> Result<(), Error> + ) -> Result, Error> where - U: Select, - I: ListIterator, + 'a: 'de, + Ctx: 'de, + U: Select + 'a, + I: ListIterator<'de, U>, { - // match self.selector { - // Selector::Matcher(_) => self.match_list::(iter), - // Selector::ExploreIndex(s) => self.explore_list_range::(iter, s.to_range()), - // Selector::ExploreRange(s) => self.explore_list_range::(iter, s.to_range()), - // Selector::ExploreAll(s) => self.explore_list_range::(iter, s.to_range()), - // s => Err(Error::unsupported_selector::>(s)), - // } - - self.handle_node(SelectedNode::List)?; - loop { - if self.handle_index::(&mut iter, None)? { - break; - } + match self.selector { + Selector::Matcher(_) => self.match_list::(iter), + Selector::ExploreIndex(s) => self.explore_list_range::(iter, s.to_range()), + Selector::ExploreRange(s) => self.explore_list_range::(iter, s.to_range()), + Selector::ExploreAll(s) => self.explore_list_range::(iter, s.to_range()), + s => Err(Error::unsupported_selector::(s)), } - Ok(()) - } - /// - pub fn patch_list( - mut self, - mut iter: I, - // dag: Either<&T2, I>, - ) -> Result<(), Error> - where - U: Select, - I: ListIterator, - { - unimplemented!() + // self.cover_node(SelectedNode::List)?; + // loop { + // if self.handle_index::(&mut iter, None)? { + // break; + // } + // } + + // Ok(AstResult::Ok) } - /* /// Executes a [`Matcher`] selector against a list (data model) type. /// todo could probably use a collection trait instead of multiple Fns - pub fn match_list( + pub fn match_list<'de, const MC: u64, U, I>( mut self, mut iter: I, // init_new_dag: F1, // mut match_cb: F2, // into_dag: F3, - ) -> Result<(), Error> + ) -> Result, Error> where - U: Select, - I: ListIterator, + 'a: 'de, + Ctx: 'de, + U: Select + 'a, + I: ListIterator<'de, U>, // T2: Default, // F1: FnOnce(&I) -> T2, // for<'b> F2: FnMut(&'b T2) -> Box + 'b>, @@ -184,17 +182,34 @@ where // } // select the matched list node, or setup the list - self.handle_node(SelectedNode::List)?; + // self.handle_node(SelectedNode::List)?; // let new_dag = self // .is_dag_select() // .then(|| init_new_dag(&iter)) // .unwrap_or_default(); // select against each child - loop { - if self.handle_index::(&mut iter, None)? { - break; - } + // while let Some(_) = self.handle_index::(&mut iter)? { + // break; + // } + let (selector, mut state, cb, mut ctx) = self.into_parts(); + for index in 0usize.. { + let field = Field::Index(index); + let seed = + Self::to_field_select_seed::(&selector, &mut state, cb.clone(), ctx, &field)?; + let res = match seed { + None => (&mut iter).next_ignored::()?, + Some(seed) => (&mut iter).next_element_seed::(seed)?, + }; + + match res { + None => break, + Some(AstResult::Value(v)) => {} + _ => {} + // Some(AstResult::Continue) => Ok(Some(AstResult::Continue)), + // Some(AstResult::Break) => Ok(Some(AstResult::Break)), + _ => unimplemented!(), + }; } // finally, select the dag itself (if applicable) @@ -202,18 +217,21 @@ where // self.handle_dag(into_dag(new_dag))?; // } - Ok(()) + Ok(AstResult::Ok) } /// explore index, range, or all - pub fn explore_list_range( + fn explore_list_range<'de, const MC: u64, U, I, R>( mut self, mut iter: I, range: R, - ) -> Result<(), Error> + ) -> Result, Error> where + 'a: 'de, + // 'b: 'c, + Ctx: 'de, U: Select, - I: ListIterator, + I: ListIterator<'de, U>, R: RangeBounds + Iterator, { let range_copy = (range.start_bound().cloned(), range.end_bound().cloned()); @@ -226,47 +244,60 @@ where }; let is_unbounded = ignore_end_idx.is_none(); - // select the list node - self.handle_node(SelectedNode::List)?; + // // select the list node + // self.handle_node(SelectedNode::List)?; // ignore everything before the start (unless 0) // if empty, return an err if start_idx > 0 { for index in 0usize..start_idx { - if iter.next_ignored()? { + if iter.next_ignored::()?.is_none() { return Err(Error::explore_list_failure::(self.selector, index)); } } } // explore any/all indices in the range + let (selector, mut state, cb, mut ctx) = self.into_parts(); for index in range { - // TODO: should be iter.next_element_seed(self.to_field_select_seed()) - let is_empty = self.handle_index::(&mut iter, None)?; + let field = Field::Index(index); + let res = if selector.next(Some(&field)).is_none() { + (&mut iter).next_ignored::()? + } else { + let iter = &mut iter; + let res = iter.next_element_seed::(SelectorSeed::from_parts( + &selector, + state.descend::(&field)?, + cb.clone(), + ctx, + ))?; + state.ascend::(); + res + }; // if unbounded and empty, then we're done exploring // if bounded and empty, then we failed to explore everything - if is_unbounded && is_empty { - return Ok(()); - } else if is_empty && range_copy.contains(&index) { - return Err(Error::explore_list_failure::(&self.selector, index)); + if is_unbounded && res.is_none() { + return Ok(AstResult::Ok); + } else if res.is_none() && range_copy.contains(&index) { + return Err(Error::explore_list_failure::(&selector, index)); } } // finish ignoring the remainder of the list if !is_unbounded { for _ in ignore_end_idx.unwrap().. { - if iter.next_ignored()? { + if iter.next_ignored::()?.is_none() { break; } } } - Ok(()) + Ok(AstResult::Ok) } - */ } +// #[cfg(feature = "skipped")] mod iterators { use super::*; use serde::de::IntoDeserializer; @@ -282,7 +313,7 @@ mod iterators { // } // impl<'de, const C: u64, A> SerdeListIterator2<'de, C, A> { - // pub const fn ignored(seq: A) -> Self { + // pub const fn ignored( A) -> Self { // SerdeListIterator2 { // seq, // seed: DeserializeWrapper::::new(), @@ -328,43 +359,57 @@ mod iterators { /// A [`Select`]able list iterator over a serde sequence representation. #[doc(hidden)] #[derive(Debug)] - pub struct SerdeListIterator<'de, A> { - inner: A, + pub struct SeqAccessIterator<'de, A> { + seq: A, index: usize, _t: PhantomData<&'de ()>, } - impl<'de, A> From for SerdeListIterator<'de, A> { - fn from(inner: A) -> Self { + impl<'de, A> From for SeqAccessIterator<'de, A> { + fn from(seq: A) -> Self { Self { - inner, + seq, index: 0, _t: PhantomData, } } } - impl<'de, T, A> ListIterator for SerdeListIterator<'de, A> + impl<'de: 'a, 'a, T, A> ListIterator<'a, T> for SeqAccessIterator<'de, A> where T: Representation, A: SeqAccess<'de>, { fn size_hint(&self) -> Option { - self.inner.size_hint() + self.seq.size_hint() } - /* - fn next_ignored(&mut self) -> Result { - let is_empty = self - .inner + + fn index(&self) -> usize { + self.index + } + + fn next_ignored(&mut self) -> Result>, Error> +where + // 'a: 'b, + // 'b: 'de, + // Ctx: Context, + // T: Select, + { + let res = self + .seq .next_element::() - .map_err(|_| Error::explore_index_failure::(self.index))? - .is_none(); - if !is_empty { - self.index += 1; + .map_err(|_| Error::explore_index_failure::(self.index))?; + match res { + None => Ok(None), + Some(_) => { + self.index += 1; + Ok(Some(AstResult::Ok)) + } } - Ok(is_empty) } + + /* fn next(&mut self) -> Result, Error> { let dag = self - .inner + .seq .next_element_seed(DeserializeRepr::::new()) .map_err(|_| Error::explore_index_failure::(self.index))?; @@ -375,15 +420,15 @@ mod iterators { Ok(dag) } } - fn next_seed<'a, const C: u64, Ctx: Context>( + fn next_seed<'de, const C: u64, Ctx: Context>( &mut self, - seed: SelectorSeed<'a, Ctx, T>, + seed: SelectorSeed<'de, Ctx, T>, ) -> Result where T: Select, { let is_empty = self - .inner + .seq .next_element_seed(DeserializeSelect::::from(seed)) .map_err(|_| Error::explore_index_failure::(self.index))? .is_none(); @@ -394,43 +439,28 @@ mod iterators { } */ - fn next_element_seed<'a, const C: u64, Ctx: Context + 'a, F>( + fn next_element_seed<'b, const MC: u64, Ctx>( &mut self, - seeder: F, - ) -> Result + seed: SelectorSeed<'b, Ctx, T>, + ) -> Result>, Error> where - T: Select, - F: FnOnce(usize) -> Result>, Error>, + // 'a: 'b, + // 'b: 'de, + 'de: 'b, + Ctx: Context + 'de, + T: Select + 'de, { - let was_empty = match seeder(self.index)? { - None => self - .inner - .next_element::() - .map(|opt| opt.map(|_| ())), - Some(seed) => self - .inner - .next_element_seed(DeserializeSelect::::from(seed)), - } - .map_err(|_| Error::explore_index_failure::(self.index))? - .is_none(); - - if !was_empty { + let res = self + .seq + .next_element_seed(>::Walker::<'b, MC>::from(seed)) + .map_err(|_| Error::explore_index_failure::(self.index))?; + if res.is_some() { self.index += 1; } - Ok(was_empty) + Ok(res) } } - // impl<'de, A> IntoDeserializer<'de, A::Error> for SerdeListIterator<'de, A> - // where - // A: SeqAccess<'de>, - // { - // type Deserializer = SeqAccessDeserializer; - // fn into_deserializer(self) -> Self::Deserializer { - // SeqAccessDeserializer::new(self.inner) - // } - // } - /* /// A [`Select`]able list iterator over an underlying iterator. pub struct MemoryListIterator<'a, T, I> { diff --git a/src/data_model/map.rs b/src/data_model/map.rs index 848a7a5..e33cf93 100644 --- a/src/data_model/map.rs +++ b/src/data_model/map.rs @@ -80,19 +80,19 @@ where // new_map.insert(key, iter.next_value::()?) // } - let mut iter = SerdeMapIterator::<'de, A>::from(map); - while let Some(key) = <_ as MapIterator>::next_key::(&mut iter, None) - .map_err(A::Error::custom)? - { - let val = key - .as_field() - .ok_or_else(|| Error::explore_key_failure::(None)) - .and_then(|field| { - <_ as MapIterator>::next_value::(&mut iter, &field) - }) - .map_err(A::Error::custom)?; - new_map.insert(key, val); - } + // let mut iter = SerdeMapIterator::<'de, A>::from(map); + // while let Some(key) = <_ as MapIterator>::next_key::(&mut iter, None) + // .map_err(A::Error::custom)? + // { + // let val = key + // .as_field() + // .ok_or_else(|| Error::explore_key_failure::(None)) + // .and_then(|field| { + // <_ as MapIterator>::next_value::(&mut iter, &field) + // }) + // .map_err(A::Error::custom)?; + // new_map.insert(key, val); + // } Ok(new_map) } @@ -123,14 +123,17 @@ repr_serde! { @visitors for Map if let Some(s) = self.as_ref().selector.as_explore_union() { if s.matches_first() { // TODO: transform the seed to a phantom seed, then recurse - let map = >::deserialize::(MapAccessDeserializer::new(map))?; - return map.__select_in(self.into_inner()).map_err(A::Error::custom); + let map: Map = Representation::deserialize::(MapAccessDeserializer::new(map))?; + // map.__select_in(self.into_inner()).map_err(A::Error::custom)?; + return Ok(AstResult::Ok); } } self.into_inner() .select_map::(SerdeMapIterator::from(map)) - .map_err(A::Error::custom) + .map_err(A::Error::custom)?; + Ok(AstResult::Ok) + /* match self.as_ref().selector { Selector::Matcher(_) => { @@ -164,13 +167,19 @@ mod iterators { /// #[doc(hidden)] #[derive(Debug)] - pub struct SerdeMapIterator<'de, A>(A, PhantomData<&'de ()>); + pub struct SerdeMapIterator<'de, A> { + map: A, + _t: PhantomData<&'de ()>, + } impl<'de, A> From for SerdeMapIterator<'de, A> { - fn from(inner: A) -> Self { - Self(inner, PhantomData) + fn from(map: A) -> Self { + Self { + map, + _t: PhantomData, + } } } - impl<'de, K, V, A> MapIterator for SerdeMapIterator<'de, A> + impl<'de, K, V, A> MapIterator<'de, K, V> for SerdeMapIterator<'de, A> where K: StringRepresentation, ::Err: fmt::Display, @@ -178,41 +187,41 @@ mod iterators { A: MapAccess<'de>, { fn size_hint(&self) -> Option { - self.0.size_hint() + self.map.size_hint() } - fn next_key( + fn next_key( &mut self, - expected_field_name: Option<&'static str>, - ) -> Result, Error> { + expected: Option<&Field<'static>>, + ) -> Result>, Error> { let key = self - .0 - .next_key_seed(DeserializeRepr::::new()) - .or_else(|_| Err(Error::explore_key_failure::(expected_field_name)))?; - - // TODO: assert that key == expected_field_name - Ok(key) - } - - fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { - self.0 - .next_value::() - .or_else(|_| Err(Error::explore_value_failure::(field)))?; - Ok(()) + .map + .next_key_seed(DeserializeRepr::::new()) + .map_err(|_| Error::explore_key_failure::(expected))?; + + match (key, expected) { + (None, None) => Ok(None), + (Some(k), Some(e)) if k.as_field().as_ref() == Some(e) => { + Ok(Some(AstResult::Value(k))) + } + (_, _) => Err(Error::explore_key_failure::(expected)), + } } - fn next_value(&mut self, field: &Field<'_>) -> Result { - self.0 - .next_value_seed(DeserializeRepr::::new()) - .or_else(|_| Err(Error::explore_value_failure::(field))) + fn next_value_ignored(&mut self) -> Result, Error> + where + Ctx: Context + 'de, + V: Select, + { + unimplemented!() } - fn next_value_seed<'a, const C: u64, Ctx: Context>( + fn next_value_seed( &mut self, - seed: SelectorSeed<'a, Ctx, V>, - // field: &Field<'_>, - ) -> Result<(), Error> + seed: SelectorSeed<'de, Ctx, V>, + ) -> Result, Error> where + Ctx: Context + 'de, V: Select, { // let key = >::key(self); @@ -329,7 +338,7 @@ where K: Select + StringRepresentation, ::Err: fmt::Display, V: Select, - I: MapIterator, + I: for<'b> MapIterator<'b, K, V>, { unimplemented!() } @@ -344,42 +353,43 @@ where K: Select + StringRepresentation, ::Err: fmt::Display, V: Select, - I: MapIterator, + I: for<'b> MapIterator<'b, K, V>, { unimplemented!() } /// - pub fn match_map( + pub fn match_map( mut self, mut iter: I, - init_new_dag: F1, - mut match_cb: F2, - into_dag: F3, + // init_new_dag: F1, + // mut match_cb: F2, + // into_dag: F3, ) -> Result<(), Error> where K: Select + StringRepresentation, ::Err: fmt::Display, V: Select, - I: MapIterator, - T2: Default + 'static, - F1: FnOnce(&I) -> T2, - for<'b> F2: FnMut(&'b K, &'b T2) -> Box + 'b>, - F3: FnOnce(T2) -> T, + I: for<'b> MapIterator<'b, K, V>, + // T2: Default + 'static, + // F1: FnOnce(&I) -> T2, + // for<'b> F2: FnMut(&'b K, &'b T2) -> Box + 'b>, + // F3: FnOnce(T2) -> T, { // select the matched node, or set up the dag - self.handle_node(SelectedNode::Map)?; - let new_dag = self - .is_dag_select() - .then(|| init_new_dag(&iter)) - .unwrap_or_default(); + // self.select_node(SelectedNode::Map)?; + // let new_dag = self + // .is_select_dag() + // .then(|| init_new_dag(&iter)) + // .unwrap_or_default(); + // self.select_ref(&new_dag)?; // select against each child - while let Some(key) = iter.next_key::(None)? { - self.handle_field::( - &mut iter, - self.is_dag_select().then(|| match_cb(&key, &new_dag)), - )?; + while let Some(key) = iter.next_key::(None)? { + // self.select_field::( + // &mut iter, + // // self.is_select_dag().then(|| match_cb(&key, &new_dag)), + // )?; } // // let mut seed = self; @@ -403,9 +413,9 @@ where // while !iter.next_entry_seed::(&mut self)? {} // finally, select the matched dag - if self.is_dag_select() { - self.handle_dag(into_dag(new_dag))?; - } + // if self.is_select_dag() { + // self.select_dag(into_dag(new_dag))?; + // } Ok(()) } @@ -416,7 +426,7 @@ where K: Select + StringRepresentation + 'static, ::Err: fmt::Display, V: Select + 'static, - I: MapIterator, + I: for<'b> MapIterator<'b, K, V>, { unimplemented!() } diff --git a/src/data_model/mod.rs b/src/data_model/mod.rs index e6388c9..e78566b 100644 --- a/src/data_model/mod.rs +++ b/src/data_model/mod.rs @@ -76,29 +76,29 @@ where } } -/// Wrapper type to connect [`serde::DeserializeSeed`]s to the underlying type's -/// [`Select::__select_de`] codec-specific implementation. -#[doc(hidden)] -#[derive(Debug)] -pub struct DeserializeSelect(S, PhantomData<(Ctx, T)>); -impl DeserializeSelect { - pub const fn from(seed: S) -> Self { - Self(seed, PhantomData) - } -} -impl<'a, 'de, const C: u64, Ctx, T> DeserializeSeed<'de> - for DeserializeSelect, T> -where - Ctx: Context, - // S: SeedType, TODO: - T: Select, -{ - type Value = (); - #[inline(always)] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - T::__select_de::(self.0, deserializer) - } -} +// /// Wrapper type to connect [`serde::DeserializeSeed`]s to the underlying type's +// /// [`Select::__select_de`] codec-specific implementation. +// #[doc(hidden)] +// #[derive(Debug)] +// pub struct DeserializeSelect(S, PhantomData<(Ctx, T)>); +// impl DeserializeSelect { +// pub const fn from(seed: S) -> Self { +// Self(seed, PhantomData) +// } +// } +// impl<'a, 'de, const C: u64, Ctx, T> DeserializeSeed<'de> +// for DeserializeSelect, T> +// where +// Ctx: Context, +// // S: SeedType, TODO: +// T: Select, +// { +// type Value = (); +// #[inline(always)] +// fn deserialize(self, deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// T::__select_de::(self.0, deserializer) +// } +// } diff --git a/src/data_model/primitive.rs b/src/data_model/primitive.rs index 06061e3..d7b25fd 100644 --- a/src/data_model/primitive.rs +++ b/src/data_model/primitive.rs @@ -25,8 +25,13 @@ mod null { #[ipld(internal)] pub struct Null; - repr_serde! { @select for Null } - repr_serde! { @visitors for Null { + impl<'a, 'de, const MC: u64, Ctx> Visitor<'de> for AstWalk<'a, MC, Ctx, Null> + where + 'a: 'de, + Ctx: Context, + { + type Value = AstResult; + #[inline] fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "A nothing type `{}`", ::NAME) @@ -47,21 +52,16 @@ mod null { { self.visit_none() } - }} - - // impl Select for Null { - // #[doc(hidden)] - // #[inline] - // fn __select_de<'a, 'de, const C: u64, D>( - // seed: SelectorSeed<'a, Ctx, Self>, - // deserializer: D, - // ) -> Result<(), D::Error> - // where - // D: Deserializer<'de>, - // { - // AstWalk::<'a, C, _, Self>(seed).deserialize(deserializer) - // } - // } + } + impl<'a, 'de, const MC: u64, Ctx> LinkVisitor<'de, MC> for AstWalk<'a, MC, Ctx, Null> + where + 'a: 'de, + Ctx: Context, + { + } + impl Select for Null { + type Walker<'a, const MC: u64> = AstWalk<'a, MC, Ctx, Self> where Ctx: 'a; + } impl From<()> for Null { #[inline] @@ -99,11 +99,12 @@ mod bool { #[doc(hidden)] #[inline] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - Deserialize::deserialize(deserializer) + let res = AstWalk::<'de, MC, (), Self>::default().deserialize(deserializer)?; + Ok(res.unwrap_val()) } } @@ -165,11 +166,13 @@ mod num { #[doc(hidden)] #[inline] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - Deserialize::deserialize(deserializer) + // Deserialize::deserialize(deserializer) + let res = AstWalk::<'de, MC, (), Self>::default().deserialize(deserializer)?; + Ok(res.unwrap_val()) } } @@ -187,8 +190,13 @@ mod num { where Er: de::Error, { + // if self.mode() == SelectionMode::Decode { + // return Ok(AstResult::Value(v)); + // } + self.into_inner().select_scalar::(v).map_err(Er::custom) } + $( #[inline] fn $other_visit_fn(self, v: $other_ty) -> Result where @@ -323,12 +331,14 @@ mod string { #[doc(hidden)] #[inline] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - let s = >::deserialize(deserializer)?; - Ok(s.nfc().collect()) + // let s = >::deserialize(deserializer)?; + // Ok(s.nfc().collect()) + let res = AstWalk::<'de, MC, (), Self>::default().deserialize(deserializer)?; + Ok(res.unwrap_val()) } } @@ -344,6 +354,11 @@ mod string { where Er: de::Error, { + + // if self.mode() == SelectionMode::Decode { + // return Ok(AstResult::Value(s.nfc().collect())); + // } + self.into_inner() .select_scalar::(s.nfc().collect()) .map_err(Er::custom) @@ -354,6 +369,10 @@ mod string { where Er: de::Error, { + if self.mode() == SelectionMode::Decode { + return Ok(AstResult::Value(s)); + } + self.visit_str(s.as_ref()) } }} @@ -488,43 +507,49 @@ mod bytes { } #[doc(hidden)] - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, serializer: S) -> Result where S: Serializer, { - Multicodec::serialize_bytes::(self.as_ref(), serializer) + Multicodec::serialize_bytes::(self.as_ref(), serializer) } #[doc(hidden)] - fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result + fn deserialize<'de, const MC: u64, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - struct BytesVisitor; - impl<'de> Visitor<'de> for BytesVisitor { - type Value = Bytes; - #[inline] - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "A slice of bytes of type {}", Self::Value::NAME) - } - #[inline] - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: de::Error, - { - Ok(Self::Value::copy_from_slice(bytes)) - } - #[inline] - fn visit_byte_buf(self, bytes: Vec) -> Result - where - E: de::Error, - { - Ok(Self::Value::from(bytes)) - } - } - impl<'de, const MC: u64> LinkVisitor<'de, MC> for BytesVisitor {} + // struct BytesVisitor; + // impl<'de> Visitor<'de> for BytesVisitor { + // type Value = Bytes; + // #[inline] + // fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // write!(f, "A slice of bytes of type {}", Self::Value::NAME) + // } + // #[inline] + // fn visit_bytes(self, bytes: &[u8]) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::copy_from_slice(bytes)) + // } + // #[inline] + // fn visit_byte_buf(self, bytes: Vec) -> Result + // where + // E: de::Error, + // { + // Ok(Self::Value::from(bytes)) + // } + // } + // impl<'de, const MC: u64> LinkVisitor<'de, MC> for BytesVisitor {} - Multicodec::deserialize_bytes::(deserializer, BytesVisitor) + // Multicodec::deserialize_bytes::(deserializer, BytesVisitor) + + let res = Multicodec::deserialize_bytes( + deserializer, + AstWalk::<'de, MC, (), Self>::default(), + )?; + Ok(res.unwrap_val()) } } @@ -539,6 +564,10 @@ mod bytes { where E: de::Error, { + if self.mode() == SelectionMode::Decode { + return Ok(AstResult::Value(Bytes::copy_from_slice(bytes))); + } + // let bytes = T::try_from(bytes).map_err(E::custom)?; // self.0.select_bytes::(bytes).map_err(E::custom) unimplemented!() @@ -558,11 +587,11 @@ mod bytes { // const NAME: &'static str = "Bytes"; // const SCHEMA: &'static str = "type Bytes bytes"; // const DATA_MODEL_KIND: Kind = Kind::Bytes; - + // // fn to_selected_node(&self) -> SelectedNode { // SelectedNode::Bytes(self.clone()) // } - + // // #[doc(hidden)] // fn serialize(&self, serializer: S) -> Result // where @@ -570,7 +599,7 @@ mod bytes { // { // Multicodec::serialize_bytes::(self.as_ref(), serializer) // } - + // // #[doc(hidden)] // fn deserialize<'de, const C: u64, D>(deserializer: D) -> Result // where @@ -599,11 +628,11 @@ mod bytes { // } // } // impl<'de> LinkVisitor<'de> for BytesVisitor {} - + // // Multicodec::deserialize_bytes::(deserializer, BytesVisitor) // } // } - + // // repr_serde! { @select for Bytes } // repr_serde! { @visitors for Bytes { // #[inline] @@ -635,35 +664,56 @@ mod bytes { // where // Ctx: Context, // T: Select, - impl<'a, Ctx> SelectorSeed<'a, Ctx, Bytes> + impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, + T: Representation, { /// #[inline] // TODO: should accept a slice of bytes, then do conversion - pub fn select_bytes(mut self, bytes: Bytes) -> Result<(), Error> { + pub fn select_bytes<'de, const MC: u64>( + mut self, + bytes: &[u8], + ) -> Result, Error> + where + T: TryFrom<&'de [u8]>, + { + unimplemented!() + } + + /// + #[inline] + // TODO: should accept a slice of bytes, then do conversion + pub fn select_byte_buf<'de, const MC: u64>( + mut self, + bytes: Vec, + ) -> Result, Error> + where + T: TryFrom>, + { // if let Some(s) = self.selector.as_explore_union() { // s.assert_matches_first::()?; // bytes.__select_in(self) // } else { - // self.match_scalar::(raw) + // self.match_scalar::(raw) // } if let Some(matcher) = self.selector.as_matcher() { - let bytes = matcher - .subset - .as_ref() - .map(|slice| bytes.slice(slice.to_range())) - .unwrap_or(bytes); - - if self.is_node_select() { - self.handle_node(bytes.into())?; - } else if self.is_dag_select() { - self.handle_dag(bytes)?; - }; - - return Ok(()); + // let bytes = matcher + // .subset + // .as_ref() + // .map(|slice| bytes.slice(slice.to_range())) + // .unwrap_or(bytes); + + // if self.is_select_node() { + // self.handle_node(bytes.into())?; + // } else if self.is_select_dag() { + // self.handle_dag(bytes)?; + // }; + // return Ok(()); + + // return self.cover_dag(bytes); } match self.selector { @@ -683,27 +733,42 @@ where // TODO And: TypedScalar { /// - pub fn select_scalar(self, raw: T) -> Result<(), Error> { - if let Some(s) = self.selector.as_explore_union() { - s.assert_matches_first::()?; - raw.__select_in(self) - } else { - self.match_scalar::(raw) + #[inline] + pub fn select_scalar(mut self, raw: T) -> Result, Error> { + match self.selector { + Selector::Matcher(_) => self.select_dag(raw), + Selector::ExploreUnion(s) => { + // todo: split into params + ctx, T::select for each + // raw.__select(self) + + Ok(AstResult::Ok) + } + s => Err(Error::unsupported_selector::(s)), } } #[inline] - fn match_scalar<'de, const C: u64>(mut self, dag: T) -> Result<(), Error> { + pub fn patch_scalar(mut self, raw: &mut T) -> Result, Error> { self.selector.try_as_matcher()?; - if self.is_node_select() { - self.handle_node(dag.to_selected_node())?; - } else if self.is_dag_select() { - self.handle_dag(dag)?; - }; + // todo + // self. - Ok(()) + Ok(AstResult::Ok) } + + // #[inline] + // pub fn match_scalar<'de, const MC: u64>(mut self, dag: T) -> Result<(), Error> { + // self.selector.try_as_matcher()?; + + // if self.is_node_select() { + // self.handle_node(dag.to_selected_node())?; + // } else if self.is_dag_select() { + // self.handle_dag(dag)?; + // }; + + // Ok(()) + // } } #[cfg(test)] diff --git a/src/error.rs b/src/error.rs index e7701e9..c265451 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,8 @@ use crate::dev::*; use cid::Error as CidError; use maybestd::{ - error::Error as StdError, fmt::Display, num::TryFromIntError, string::FromUtf8Error, + borrow::Cow, error::Error as StdError, fmt::Display, num::TryFromIntError, + string::FromUtf8Error, }; #[cfg(feature = "multiaddr")] use multiaddr::Error as MultiaddrError; @@ -60,6 +61,9 @@ pub enum Error { ////////////////////////////////////////////////////////////////////// // selector ////////////////////////////////////////////////////////////////////// + #[error("General selection failure: {0}")] + SelectionFailure(String), + #[error("Selector Context error: {0}")] Context(#[from] anyhow::Error), @@ -102,7 +106,7 @@ pub enum Error { #[error("Failed to explore field key `{field_name}` of type `{key_type_name}`")] ExploreFieldKeyFailure { key_type_name: &'static str, - field_name: &'static str, + field_name: String, }, #[error("Failed to explore field value of type `{value_type_name}` for key `{key}`")] @@ -197,10 +201,15 @@ impl Error { } #[doc(hidden)] - pub fn explore_key_failure(field_name: Option<&'static str>) -> Self { + pub fn explore_key_failure(field_name: Option<&Field<'static>>) -> Self { + const ANONYMOUS: Field<'static> = Field::Key(Cow::Borrowed("anonymous key")); Self::ExploreFieldKeyFailure { key_type_name: K::NAME, - field_name: field_name.unwrap_or("anonymous key"), + field_name: field_name + .or(Some(&ANONYMOUS)) + .and_then(|f| f.as_key()) + .unwrap() + .into(), } } diff --git a/src/lib.rs b/src/lib.rs index f89925b..51e5e28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,8 @@ pub use { schema, // selector Representation, - // Select, Patch + Select, + // Patch }, // multiformats diff --git a/src/multicodec.rs b/src/multicodec.rs index f4e7b13..44c93f3 100644 --- a/src/multicodec.rs +++ b/src/multicodec.rs @@ -167,7 +167,11 @@ mod multicodec { match self { $( #[cfg(feature = $feature)] - Self::$variant(_) => <$path>::read_with_seed(seed, reader), + Self::$variant(_) => { + <$path>::read_with_seed(seed, reader) + + // let mut de = <$path>::from_reader() + }, )* } } diff --git a/src/representation/mod.rs b/src/representation/mod.rs index a5f00a5..b8f7d5f 100644 --- a/src/representation/mod.rs +++ b/src/representation/mod.rs @@ -131,6 +131,12 @@ pub trait Representation: Sized { // #[doc(hidden)] // type ReprKind: TypedKind; + // /// + // #[doc(hidden)] + // type Walker<'de, const MC: u64>: Walk<'de, MC, Self> + // where + // Self: 'de; + /// The type's `Select`able static field names and their IPLD Schema kinds. #[doc(hidden)] const FIELDS: &'static [&'static str] = &[]; @@ -205,18 +211,18 @@ pub trait Representation: Sized { // >::deserialize(deserializer) // ::__select_de::(EmptySeed, deserializer) - // deserialize_with_visitor::( + // let res = deserialize_with_visitor::( // deserializer, // Self::Walker::<'de, '_, MC>::default(), - // ) + // )?; + // Ok(res.unwrap_val()) unimplemented!() } - // AstWalk<'a, Ctx, Self> - // /// - // #[doc(hidden)] - // type Walker<'de, 'a: 'de, const MC: u64>: Walk<'de, 'a, MC, Self>; + // type Walker<'de, const MC: u64>: Walk<'de, MC, Self> + // where + // Self: 'de; #[inline] #[doc(hidden)] @@ -325,7 +331,7 @@ pub trait Representation: Sized { #[inline] #[doc(hidden)] -fn deserialize_with_visitor<'de, const MC: u64, D, V, T>( +pub fn deserialize_with_visitor<'de, const MC: u64, D, V, T>( deserializer: D, visitor: V, ) -> Result @@ -409,7 +415,7 @@ pub trait AdvancedRepresentation: Representation + Select {} /// /// TODO: possibly look at erased-serde to complete this "hack" -pub(crate) trait ErasedRepresentation: Downcast { +pub trait ErasedRepresentation: Downcast { // /// The underlying [`Representation`] type this type will downcast to. // type Representation: Representation = Self; @@ -418,6 +424,10 @@ pub(crate) trait ErasedRepresentation: Downcast { /// fn has_links(&self) -> bool; + + // fn is(&self) -> bool { + // self.as_any().is::() + // } } // impl_downcast!(sync ErasedRepresentation assoc Representation diff --git a/src/representation/strategies/listpairs.rs b/src/representation/strategies/listpairs.rs index ba4fccc..f6566fe 100644 --- a/src/representation/strategies/listpairs.rs +++ b/src/representation/strategies/listpairs.rs @@ -281,48 +281,27 @@ mod iterators { /// /// if name is provided - fn next_key( - &mut self, - expected_field_name: Option<&'static str>, - ) -> Result, Error> { + fn next_key<'a, const MC: u64>( + &'a mut self, + expected: Option<&Field<'static>>, + ) -> Result>, Error> { unimplemented!() } - fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { - unimplemented!() - } - - fn next_value_seed<'a, const C: u64, Ctx: Context>( - &mut self, - seed: SelectorSeed<'a, Ctx, V>, - // field: &Field<'_>, - ) -> Result<(), Error> - where - V: Select, - { - unimplemented!() - } + // fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error> { + // unimplemented!() + // } - fn next_entry_seed<'a, const C: u64, Ctx: Context + 'a, F>( - &mut self, + fn next_value_seed<'a: 'b, 'b, const MC: u64, Ctx, F>( + &'a mut self, seeder: F, - ) -> Result + ) -> Result, Error> where + Ctx: Context + 'b, V: Select, - F: FnOnce(&str) -> Result>, Error>, + F: FnOnce(&Field<'_>) -> Result>, Error>, { - // - unimplemented!() - // let key = >::key(self); - // let field = Representation::as_field(key); - // let field = self.field(); - // let err = || Error::explore_value_failure::(field); - - // V::__select_map::(seed, &mut self.inner, false) - // .ok() - // .flatten() - // .ok_or_else(|| Error::explore_value_failure::(field)) } } diff --git a/src/representation/strategies/mod.rs b/src/representation/strategies/mod.rs index c2ebce0..fda870f 100644 --- a/src/representation/strategies/mod.rs +++ b/src/representation/strategies/mod.rs @@ -1,17 +1,19 @@ mod bytesprefix; -#[macro_use] -mod listpairs; +// #[macro_use] +// mod listpairs; mod stringjoin; mod stringpairs; mod stringprefix; -#[macro_use] -mod tuple; +// #[macro_use] +// mod tuple; -#[doc(hidden)] -pub use tuple::*; +pub use list::ListIterator; +pub use map::MapIterator; +// #[doc(hidden)] +// pub use tuple::*; use crate::dev::*; -use maybestd::{fmt, str::FromStr}; +use maybestd::{fmt, iter::Peekable, marker::PhantomData, str::FromStr}; /// #[derive(Copy, Clone, Debug)] @@ -52,185 +54,572 @@ impl Strategy { } } -/// An iterator over the elements of a list-like type, whether produced from an -/// in-memory type or from an underlying [`Representation`]. -#[doc(hidden)] -pub trait ListIterator { - fn size_hint(&self) -> Option; - - // fn next_ignored(&mut self) -> Result; - - // fn next(&mut self) -> Result, Error> { - // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - // } - - // fn next_ref(&mut self) -> Result, Error> { - // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - // } - - // fn next_ref_mut(&mut self) -> Result, Error> { - // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - // } - - // fn next_seed<'a, const C: u64, Ctx: Context>( - // &mut self, - // seed: SelectorSeed<'a, Ctx, T>, - // ) -> Result - // where - // T: Select; - - /// Returns `Ok(true)` if element was found and was successfully - /// selected/ignored, and `Ok(false)` if iterator was already empty. - fn next_element_seed<'a, const C: u64, Ctx: Context + 'a, F>( - &mut self, - seeder: F, - ) -> Result +/// A wrapper around an [`Iterator`] of immutable references to a list dag's +/// elements. +#[derive(Debug)] +pub struct ListIter<'a, I> { + iter: I, + index: usize, + _t: PhantomData<&'a ()>, +} + +impl<'a, I> ListIter<'a, I> { + pub fn new(iter: I) -> Self where - T: Select, - F: FnOnce(usize) -> Result>, Error>, + I: Iterator, + T: Representation + 'a, { - unimplemented!() + Self { + iter, + index: 0, + _t: PhantomData, + } } } -/// An iterator over the keys and values of a map-like type, whether produced -/// from an in-memory type or from an underlying [`Representation`]. -#[doc(hidden)] -pub trait MapIterator +/// A wrapper around an [`Iterator`] of mutable references to a list dag's +/// elements. +#[derive(Debug)] +pub struct ListIterMut<'de, I> { + iter: I, + index: usize, + _t: PhantomData<&'de ()>, +} + +impl<'de, I> ListIterMut<'de, I> { + pub fn new(iter: I) -> Self + where + I: Iterator, + T: Representation + 'de, + { + Self { + iter, + index: 0, + _t: PhantomData, + } + } +} + +/// A wrapper around an [`Iterator`] of a map dag's key-value pairs. +// #[derive(Debug)] +pub struct MapIter<'de, I: Iterator> { + iter: Peekable, + _t: PhantomData<&'de ()>, +} + +impl<'de, I: Iterator> MapIter<'de, I> { + pub fn new(iter: I) -> Self + where + I: Iterator, + K: Representation + 'de, + V: Representation + 'de, + { + Self { + iter: iter.peekable(), + _t: PhantomData, + } + } +} + +/// A wrapper around an [`Iterator`] of a map dag's key-value pairs. +// #[derive(Debug)] +pub struct MapIterMut<'de, I: Iterator> { + iter: Peekable, + _t: PhantomData<&'de ()>, +} + +impl<'de, I: Iterator> MapIterMut<'de, I> { + pub fn new(iter: I) -> Self + where + I: Iterator, + K: Representation + 'de, + V: Representation + 'de, + { + Self { + iter: iter.peekable(), + _t: PhantomData, + } + } +} + +mod list { + use super::*; + + /// An iterator over the elements of a list-like type, whether produced from + /// an in-memory type or from an underlying [`Representation`]. + #[doc(hidden)] + pub trait ListIterator<'de, T: Representation> { + // type Item<'a>; + + /// + fn size_hint(&self) -> Option; + + /// + fn index(&self) -> usize; + + /// + fn next_ignored(&mut self) -> Result>, Error>; + // where + // 'a: 'b, + // 'b: 'de, + // Ctx: Context, + // T: Select + + /// Returns `Ok(true)` if element was found and was successfully + /// selected/ignored, and `Ok(false)` if iterator was already empty. + fn next_element_seed<'b, const MC: u64, Ctx>( + &mut self, + seed: SelectorSeed<'b, Ctx, T>, + ) -> Result>, Error> + where + // 'a: 'b, + // 'b: 'de, + 'de: 'b, + Ctx: Context + 'de, + T: Select; + } + + impl<'de, T: Representation, I: ListIterator<'de, T>> ListIterator<'de, T> for &mut I { + fn size_hint(&self) -> Option { + (**self).size_hint() + } + + fn index(&self) -> usize { + (**self).index() + } + + fn next_ignored(&mut self) -> Result>, Error> where - K: StringRepresentation, - ::Err: fmt::Display, - V: Representation, -{ - fn size_hint(&self) -> Option; + // 'a: 'b, + // 'b: 'de, + // Ctx: Context, + // T: Select, + { + (**self).next_ignored::() + } + + fn next_element_seed<'b, const MC: u64, Ctx>( + &mut self, + seed: SelectorSeed<'b, Ctx, T>, + ) -> Result>, Error> + where + // 'a: 'b, + // 'b: 'de, + 'de: 'b, + Ctx: Context + 'de, + T: Select + 'de, + { + (**self).next_element_seed::(seed) + } + } + + impl<'de, T, I> ListIterator<'de, T> for ListIter<'de, I> + where + T: Representation + 'de, + I: Iterator, + { + // type Item<'a> = &'a T; + + fn size_hint(&self) -> Option { + self.iter.size_hint().1 + } - fn next_key( - &mut self, - expected_field_name: Option<&'static str>, - ) -> Result, Error>; + fn index(&self) -> usize { + self.index + } - fn next_value_ignored(&mut self, field: &Field<'_>) -> Result<(), Error>; + fn next_ignored(&mut self) -> Result>, Error> +where + // 'a: 'b, + // 'b: 'de, + // Ctx: Context, + // T: Select, + { + if self.iter.next().is_some() { + self.index += 1; + Ok(Some(AstResult::Ok)) + } else { + Ok(None) + } + } - fn next_value(&mut self, field: &Field<'_>) -> Result { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + fn next_element_seed<'b, const MC: u64, Ctx>( + &mut self, + seed: SelectorSeed<'b, Ctx, T>, + ) -> Result>, Error> + where + // 'a: 'b, + // 'b: 'de, + 'de: 'b, + Ctx: Context + 'de, + T: Select + 'de, + { + let found = match self.iter.next() { + None => false, + Some(dag) => { + dag.__select(seed)?; + true + } + }; + + if found { + self.index += 1; + Ok(Some(AstResult::Ok)) + } else { + Ok(None) + } + } } - fn next_value_seed<'a, const C: u64, Ctx: Context>( - &mut self, - seed: SelectorSeed<'a, Ctx, V>, - ) -> Result<(), Error> + impl<'de, T, I> ListIterator<'de, T> for ListIterMut<'de, I> where - V: Select; + T: Representation + 'de, + I: Iterator, + { + fn size_hint(&self) -> Option { + self.iter.size_hint().1 + } - fn next_entry(&mut self) -> Result, Error> { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + fn index(&self) -> usize { + self.index + } + + fn next_ignored(&mut self) -> Result>, Error> +where + // 'a: 'b, + // 'b: 'de, + // Ctx: Context, + // T: Select, + { + if self.iter.next().is_some() { + self.index += 1; + Ok(Some(AstResult::Ok)) + } else { + Ok(None) + } + } + + fn next_element_seed<'b, const MC: u64, Ctx>( + &mut self, + seed: SelectorSeed<'b, Ctx, T>, + ) -> Result>, Error> + where + // 'a: 'b, + // 'b: 'de, + 'de: 'b, + Ctx: Context + 'de, + T: Select + 'de, + { + let found = match self.iter.next() { + None => false, + Some(dag) => { + dag.__patch(seed)?; + true + } + }; + + if found { + self.index += 1; + Ok(Some(AstResult::Ok)) + } else { + Ok(None) + } + } } +} - fn next_entry_seed<'a, const C: u64, Ctx: Context + 'a, F>( - &mut self, - seeder: F, - ) -> Result +mod map { + use super::*; + + /// An iterator over the keys and values of a map-like type, whether produced + /// from an in-memory type or from an underlying [`Representation`]. + #[doc(hidden)] + pub trait MapIterator<'a, K, V> where - V: Select, - F: FnOnce(&str) -> Result>, Error>, + K: StringRepresentation, + ::Err: fmt::Display, + V: Representation, { - Err(Error::Custom(anyhow::Error::msg("unimplemented"))) - - // let key = if let Some(key) = self.next_key::(None)? { - // key - // } else { - // return Ok(true); - // }; - - // // todo - // let include = filter.map(|pred| pred(&key.to_string())).unwrap_or(true); - // if include { - // self.next_value_seed::(seed)?; + /// + fn size_hint(&self) -> Option; + + /// + fn next_key( + &mut self, + expected: Option<&Field<'static>>, + ) -> Result>, Error>; + + /// + fn next_value_ignored(&mut self) -> Result, Error> + where + Ctx: Context + 'a, + V: Select; + + /// + fn next_value_seed( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + ) -> Result, Error> + where + Ctx: Context + 'a, + V: Select; + + /// + fn next_entry_seed( + &mut self, + seed: SelectorSeed<'a, Ctx, V>, + ) -> Result>, Error> + where + Ctx: Context + 'a, + V: Select, + { + match self.next_key::(None)? { + None => Ok(None), + Some(_) => self.next_value_seed::(seed).map(Some), + } + } + + /* + // fn next_value_ignored<'a, const C: u64, Ctx: Context, V>(&mut self) -> Result>, Error> + // where V: Select {} + + // fn next_value(&mut self, field: &Field<'_>) -> Result { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // } + + // fn next_value_seed<'a, const C: u64, Ctx: Context>( + // &mut self, + // seed: SelectorSeed<'a, Ctx, V>, + // ) -> Result, Error> + // where + // V: Select; + + // fn next_entry(&mut self) -> Result, Error> { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // } + + // fn next_entry_seed<'a, const C: u64, Ctx: Context + 'a, F>( + // &mut self, + // seeder: F, + // ) -> Result>, Error> + // where + // V: Select, + // F: FnOnce(&str) -> Result>, Error>, + // { + // Err(Error::Custom(anyhow::Error::msg("unimplemented"))) + // + // // let key = if let Some(key) = self.next_key::(None)? { + // // key + // // } else { + // // return Ok(true); + // // }; + // + // // // todo + // // let include = filter.map(|pred| pred(&key.to_string())).unwrap_or(true); + // // if include { + // // self.next_value_seed::(seed)?; + // // Ok(false) + // // } else { + // // // self.next_value_ignored(&field)?; + // // Ok(false) + // // } + // } + */ + + /* + // fn next_entry<'a, const C: u64>( + // &mut self, + // // seed: SelectorSeed<'a, Ctx, V>, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result, Error> + // where + // K: Representation, + // { + // unimplemented!() + // } + + // fn next_entry_seed<'a, const C: u64, T, Ctx: Context>( + // &mut self, + // root_seed: &mut SelectorSeed<'a, Ctx, T>, + // // seeder: F, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result + // where + // T: Representation, + // K: Representation, + // V: Select, + // // F: FnOnce(K) -> Result>, Error>, + // { + // let key = if let Some(key) = self.next_key::(None)? { + // key + // } else { + // return Ok(true); + // }; + + // root_seed.select_field::(root_seed.) + // Ok(false) - // } else { - // // self.next_value_ignored(&field)?; + // } + + // /// + // /// impl DeSeed and Visitor::visit_seq for some type + // /// if key matches, create field select seed and call V::__select_map + // /// else, ignore value + // /// return is_empty + // fn next_entry_seed<'a, const C: u64, Ctx: Context, F>( + // &mut self, + // // seed: SelectorSeed<'a, Ctx, V>, + // seeder: F, + // // expected_field_name: Option bool> + // // field: &Field<'_>, + // ) -> Result + // where + // Ctx: 'a, + // K: Representation, + // V: Select, + // F: FnOnce(K) -> Result, Error>, + // { + // let key = if let Some(key) = self.next_key::(None)? { + // key + // } else { + // return Ok(true); + // }; + + // self.next_value_seed::(seeder(key)?)?; // Ok(false) // } + */ } - /* - // fn next_entry<'a, const C: u64>( - // &mut self, - // // seed: SelectorSeed<'a, Ctx, V>, - // // expected_field_name: Option bool> - // // field: &Field<'_>, - // ) -> Result, Error> - // where - // K: Representation, - // { - // unimplemented!() - // } - - // fn next_entry_seed<'a, const C: u64, T, Ctx: Context>( - // &mut self, - // root_seed: &mut SelectorSeed<'a, Ctx, T>, - // // seeder: F, - // // expected_field_name: Option bool> - // // field: &Field<'_>, - // ) -> Result - // where - // T: Representation, - // K: Representation, - // V: Select, - // // F: FnOnce(K) -> Result>, Error>, - // { - // let key = if let Some(key) = self.next_key::(None)? { - // key - // } else { - // return Ok(true); - // }; - - // root_seed.select_field::(root_seed.) - - // Ok(false) - // } - - // /// - // /// impl DeSeed and Visitor::visit_seq for some type - // /// if key matches, create field select seed and call V::__select_map - // /// else, ignore value - // /// return is_empty - // fn next_entry_seed<'a, const C: u64, Ctx: Context, F>( - // &'a mut self, - // // seed: SelectorSeed<'a, Ctx, V>, - // seeder: F, - // // expected_field_name: Option bool> - // // field: &Field<'_>, - // ) -> Result - // where - // Ctx: 'a, - // K: Representation, - // V: Select, - // F: FnOnce(K) -> Result, Error>, - // { - // let key = if let Some(key) = self.next_key::(None)? { - // key - // } else { - // return Ok(true); - // }; - - // self.next_value_seed::(seeder(key)?)?; - // Ok(false) - // } - */ -} + impl<'de, K, V, I> MapIterator<'de, K, V> for MapIter<'de, I> + where + K: StringRepresentation + 'de, + ::Err: fmt::Display, + V: Representation + 'de, + I: Iterator, + { + fn size_hint(&self) -> Option { + self.iter.size_hint().1 + } + + fn next_key( + &mut self, + expected: Option<&Field<'static>>, + ) -> Result>, Error> { + match self.iter.peek() { + None => Ok(None), + // todo: assert match expected + Some((k, _)) => { + // self.field.replace( + // k.as_field() + // .ok_or(Error::explore_key_failure::(expected))?, + // ); + Ok(Some(AstResult::Ok)) + } + } + } -// impl<'a, const C: u64, F, Ctx, T, O> RepresentationIterator<'a, C, F, Ctx, T, O> -// where -// F: FnMut(SelectorSeed<'a, Ctx, T>) -> Result, -// Ctx: Context, -// T: Select, -// { -// // fn next(&mut self, seed: SelectorSeed<'a, Ctx, T>) -> Result<(), Error> { + fn next_value_ignored(&mut self) -> Result, Error> + where + Ctx: Context + 'de, + V: Select, + { + // let field = self + // .field + // .take() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // self.iter + // .next() + // .ok_or_else(|| Error::explore_value_failure::(&field)); + Ok(AstResult::Ok) + } -// // } + fn next_value_seed( + &mut self, + seed: SelectorSeed<'de, Ctx, V>, + ) -> Result, Error> + where + Ctx: Context + 'de, + V: Select, + { + // let field = self + // .field + // .take() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // let (_, dag) = self + // .iter + // .next() + // .ok_or_else(|| Error::explore_value_failure::(&field))?; -// fn next_with_seed(&mut self, seed: SelectorSeed<'a, Ctx, T>) -> Result { -// (self.func)(seed) -// } -// } + // dag.__select(seed)?; + Ok(AstResult::Ok) + } + } + + impl<'de, K, V, I> MapIterator<'de, K, V> for MapIterMut<'de, I> + where + K: StringRepresentation + 'de, + ::Err: fmt::Display, + V: Representation + 'de, + I: Iterator, + { + fn size_hint(&self) -> Option { + self.iter.size_hint().1 + } + + fn next_key( + &mut self, + expected: Option<&Field<'static>>, + ) -> Result>, Error> { + match self.iter.peek() { + None => Ok(None), + // todo: assert match expected + Some((k, _)) => { + // self.field.replace( + // k.as_field() + // .ok_or(Error::explore_key_failure::(expected))?, + // ); + Ok(Some(AstResult::Ok)) + } + } + } + + fn next_value_ignored(&mut self) -> Result, Error> + where + Ctx: Context + 'de, + V: Select, + { + // let field = self + // .field + // .take() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // self.iter + // .next() + // .ok_or_else(|| Error::explore_value_failure::(&field)); + Ok(AstResult::Ok) + } + + fn next_value_seed( + &mut self, + seed: SelectorSeed<'de, Ctx, V>, + ) -> Result, Error> + where + Ctx: Context + 'de, + V: Select, + { + // let field = self + // .field + // .take() + // .ok_or_else(|| Error::explore_key_failure::(None))?; + // let (k, dag) = self + // .iter + // .next() + // .ok_or_else(|| Error::explore_value_failure::())?; + + // dag.__patch(seed)?; + Ok(AstResult::Ok) + } + } +} diff --git a/src/representation/strategies/tuple.rs b/src/representation/strategies/tuple.rs index e5eebcb..cee01ef 100644 --- a/src/representation/strategies/tuple.rs +++ b/src/representation/strategies/tuple.rs @@ -265,7 +265,7 @@ macro_rules! tuple { Cfn: FnOnce($($ty,)*) -> Result, { // select the matched node, and set up the dag - self.handle_node(SelectedNode::Map)?; + // self.handle_node(SelectedNode::Map)?; // FIXME: should maybe just use an option, since idx might get inited $(let [] = RefCell::new(MaybeUninit::uninit());)* // create cleanup cb @@ -282,32 +282,33 @@ macro_rules! tuple { // let mut idx = 0usize; - $( if let Err(err) = <_ as MapIterator>::next_key::(&mut iter, Some(T::FIELDS[idx])) - .and_then(|_: Option| self.handle_field::( - &mut iter, - self.is_dag_select().then_some(Box::new(|child, _| { - [].borrow_mut().write(child); - Ok(()) - })), - )) - { - return drop_inited(idx, err); - } - - idx += 1; - // if idx < LEN { - // iter.into_next() - // } else { - // iter - // } - )* + // $( if let Err(err) = + // <_ as MapIterator>::next_key::(&mut iter, Some(T::FIELDS[idx])) + // .and_then(|_: Option<&String>| self.select_field::( + // &mut iter, + // // self.is_dag_select().then_some(Box::new(|child, _| { + // // [].borrow_mut().write(child); + // // Ok(()) + // // })), + // )) + // { + // return drop_inited(idx, err); + // } + + // idx += 1; + // // if idx < LEN { + // // iter.into_next() + // // } else { + // // iter + // // } + // )* // match dag - if self.is_dag_select() { + if self.is_select_dag() { $(let [] = unsafe { [].into_inner().assume_init() };)* - self.handle_dag(constructor($([],)*)?)?; + self.select_dag(constructor($([],)*)?)?; } Ok(()) diff --git a/src/select/context.rs b/src/select/context.rs index fe4553e..2079bd2 100644 --- a/src/select/context.rs +++ b/src/select/context.rs @@ -13,6 +13,7 @@ use crate::dev::*; use maybestd::{ collections::HashMap, io::{empty, Cursor, Empty, Read, Sink, Write}, + task, }; // trait BlockWriter: Write {} @@ -121,6 +122,43 @@ impl Context for () { } } +#[cfg(feature = "sync")] +mod sync { + /// ! only 1 place where blocking hurts: `Context::block_reader/writer()` + /// ! in Select/Patch API + /// ! in Link::deserialize + /// if called within async fn, + /// - ctx.block_reader/writer() cannot use `block_on` + /// - ctx.block_reader/writer() cannot return SyncIoBridge + /// ? + /// + /// + /// struct SelectFuture(recv, params, Ctx); + /// + /// impl Future for SelectFuture { + /// type Output = Result; + /// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + /// + /// } + ///} + /// + use super::*; + + pub struct AsyncContext<'a, C> { + inner: C, + waker: &'a task::Waker, + } + + impl<'a, C: Context> Context for AsyncContext<'a, C> { + type Reader = C::Reader; + type Writer = C::Writer; + + fn block_reader(&mut self, cid: &Cid) -> Result { + self.inner.block_reader(cid) + } + } +} + /// #[derive(Clone, Debug, Default)] pub struct MemoryContext { diff --git a/src/select/mod.rs b/src/select/mod.rs index edde2a5..d87c1b1 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -26,20 +26,23 @@ use crate::dev::*; use macros::derive_more::{Display, From}; use maybestd::{ cell::RefCell, + future::{self, IntoFuture}, path::{Path, PathBuf}, str::FromStr, + task::Poll, vec::IntoIter, }; /// /// TODO: + 'static? -/// - Selectable? -pub trait Select: Representation { - // /// - // #[doc(hidden)] - // type Seed<'a, 'de, const C: u64>: From> + DeserializeSeed<'de> = CodedSelectorSeed<'a, C, false, Ctx, Self>; +pub trait Select: Representation + 'static { + /// + #[doc(hidden)] + type Walker<'a, const MC: u64>: Walk<'a, MC, Self> + From> + where + Ctx: 'a; - /// Produces a stream of [`Selection`]s of some type `T`. + /// ... /// /// Under the hood, this serves as the entrypoint for deserialization of a /// block via a typed `ContextSeed`: a type that implements @@ -49,99 +52,175 @@ pub trait Select: Representation { /// /// /// TODO: update this interface, since SelectorSeed is doing the work and it should be refactored a bit (borrow state, ) - fn select(params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { + /// + /// todo: 1. build seed, fetch deserializer => seed.deserialize(de) + /// todo: 2. should maybe accept a deserializer + params + ctx + fn select_in<'a, P>(params: P, ctx: Ctx) -> Result<(), Error> + where + P: Into>, + Self: 'a, + { let Params { selector, mut state, callback, - } = params; - - let default_selector = Selector::DEFAULT; - let seed = SelectorSeed::from_parts( - &selector.unwrap_or(&default_selector), - &mut state, - callback, - ctx, - ); + } = params.into(); + let seed = SelectorSeed::from_parts(&selector, &mut state, callback, ctx); + + // todo: + // if matcher, Repr::deserialize and call callback (match_val) + // if explore_union, read block for each (? in parallel?) + // if explore_interpret_as, ... + // if let Some(matcher) = seed.selector.as_matcher() { + // // params.callback(self.as_ref()) + // return Ok(()); + // } - // TODO: put this block here - // let cid = &seed.state.current_block; - // let block = seed.ctx.block_reader(cid)?; - // cid.multicodec()?.read_with_seed(Self::Walker::from(seed), block) - Self::__select(seed) + Self::__select_in(seed) } #[doc(hidden)] - fn __select<'a>(seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { - let cid = &seed.state.current_block; - let block = seed.ctx.block_reader(cid)?; - cid.multicodec()?.read_with_seed(seed, block) + // fn __select<'a, W: Into>>(walker: W) -> Result<(), Error> { + fn __select_in<'a>(mut seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { + match seed.selector { + // if exploreunion, call select on each (? in parallel?) + Selector::ExploreUnion(_) => todo!(), + _ => { + let cid = &seed.state.current_block; + let block = seed.ctx.block_reader(cid)?; + cid.multicodec()?.read_with_seed(seed, block) + } + } } - #[doc(hidden)] - fn __select_de<'a, 'de, const C: u64, D>( - seed: SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - Err(D::Error::custom("__select_de not yet implemented")) - // TODO: default impl should use GAT for CodedSeed - // Self::Seed::<'a, 'de, C>::from(seed).deserialize(deserializer) - } + // #[doc(hidden)] + // fn __select_de<'a, 'de, const MC: u64, D>( + // seed: SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: Deserializer<'de>, + // { + // Err(D::Error::custom("__select_de not yet implemented")) + // // TODO: default impl should use GAT for CodedSeed + // // Self::Seed::<'a, 'de, C>::from(seed).deserialize(deserializer) + // } /// Selects against the dag, loading more blocks from `Ctx` if required. /// - /// TODO + /// todo: 1. build seed, + /// if match, call selectdagrefop on ref (match_ref) + /// otherwise, create XAccessDeserializer => seed.visit_XX(accessor) + /// * select_in and select share same code path b/c ... callbacks on refs have indeterminate lifetimes? #[doc(hidden)] - fn select_in(&self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result<(), Error> { + fn select<'a, P>(&'a self, params: P, ctx: Ctx) -> Result<(), Error> + where + P: Into>, + { let Params { selector, mut state, callback, - } = params; + } = params.into(); + let seed = SelectorSeed::from_parts(&selector, &mut state, callback, ctx); - let default_selector = Selector::DEFAULT; - let seed = SelectorSeed::from_parts( - &selector.unwrap_or(&default_selector), - &mut state, - callback, - ctx, - ); - - self.__select_in(seed) + self.__select(seed) } #[doc(hidden)] - fn __select_in<'a>(&self, seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { - unimplemented!() + fn __select<'a>(&'a self, mut seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { + match seed.selector { + // if matcher, call selectdagop on self + Selector::Matcher(_) => { + seed.select_ref(self)?; + return Ok(()); + } + // if exploreunion, call select on each (? in parallel?) + Selector::ExploreUnion(_) => todo!(), + _ => unreachable!(), + } + + // let mut de = self.[into_access().]into_deserializer(); + // Self::Walk::<'a, IDENTITY>::from(seed).deserialize(&mut de) } /// Patches the dag according to the selector, loading more blocks from /// `Ctx` if required. Returns `true` if any patch operation was executed /// and subsequently mutated a part of the dag. /// + /// todo: 1. build seed, + /// if match, call patchdagop on ref_mut (match_ref_mut) + /// if exploreunion, patch one at a time + /// otherwise, create self+seed [+ iterator] => seed.patch_list/map(..) + #[doc(hidden)] + fn patch<'a, P>(&'a mut self, params: P, ctx: Ctx) -> Result<(), Error> + where + P: Into>, + { + let Params { + selector, + mut state, + callback, + } = params.into(); + let seed = SelectorSeed::<'_, Ctx, Self>::from_parts(&selector, &mut state, callback, ctx); + + self.__patch(seed) + } + + #[doc(hidden)] + fn __patch<'a>(&'a mut self, mut seed: SelectorSeed<'a, Ctx, Self>) -> Result<(), Error> { + // if matcher, call selectdagop on self + // if exploreunion, call select on each (? in parallel?) + match seed.selector { + Selector::Matcher(_) => { + seed.patch_dag(self)?; + return Ok(()); + } + Selector::ExploreUnion(_) => todo!(), + _ => self.__patch(seed), + } + } + + /// Flushes the dag according to the selector, writing blocks to `Ctx` if + /// flushing linked dags. + /// /// TODO #[doc(hidden)] - fn patch(&mut self, params: Params<'_, Ctx, Self>, ctx: &mut Ctx) -> Result { + fn flush(&mut self, params: Params<'_, Ctx>, ctx: &mut Ctx) -> Result<(), Error> { unimplemented!() } - // /// Flushes the dag according to the selector, writing blocks to `Ctx` if - // /// flushing linked dags. - // /// - // /// TODO - // #[doc(hidden)] - // fn flush(&mut self, ctx: &mut Ctx) -> Result<(), Error> { - // unimplemented!() - // } - // fn patch>(seed: ContextSeed<'_, C, Self, S>) -> Result<(), Error> { // unimplemented!() // } } +fn select_async( + params: Params<'_, Ctx>, + ctx: &mut Ctx, +) -> impl IntoFuture> +where + Ctx: Context, + T: Select, +{ + enum SM { + Waiting, + Selecting, + Done, + } + // let first = future::poll_fn(|cx| + // 1. poll block_reader; SM::Waiting -> SM::Selecting + // Poll::Pending); + + // let next = future::poll_fn(|cx| + // 2. begin selection + // - every subsequent block_reader call + // Poll::Pending); + // 3. await ... ? + + future::pending() +} + // impl Select for T // where // C: Context, @@ -193,21 +272,21 @@ mod params { /// #[derive(Debug)] - pub struct Params<'a, C, T = Any> + pub struct Params<'a, Ctx> where - C: Context, - T: Representation, + Ctx: Context, + // T: Representation, { - pub(crate) selector: Option<&'a Selector>, + pub(crate) selector: &'a Selector, pub(crate) state: State, // pub(crate) max_path_depth: Option, // pub(crate) max_link_depth: Option, - pub(crate) callback: Callback<'a, C, T>, + pub(crate) callback: Option>, } - // impl<'a, C, T> Default for Params<'a, C, T> + // impl<'a, Ctx, T> Default for Params<'a, Ctx, T> // where - // C: Context, + // Ctx: Context, // T: Representation, // { // fn default() -> Self { @@ -216,24 +295,21 @@ mod params { // state: Default::default(), // // max_path_depth: None, // // max_link_depth: None, - // callback: Default::default(), + // callback: None, // } // } // } - impl<'a, C, T> Params<'a, C, T> + impl<'a, Ctx> Params<'a, Ctx> where - C: Context, - T: Representation, + Ctx: Context, + // T: Representation, { /// - pub fn new_select(cid: Cid) -> Self { + pub fn new(selector: &'a Selector) -> Self { Self { - selector: None, - state: State { - current_block: cid, - ..Default::default() - }, + selector, + state: Default::default(), callback: Default::default(), } } @@ -244,11 +320,11 @@ mod params { // self // } - /// - pub fn with_selector(mut self, selector: &'a Selector) -> Self { - self.selector.replace(selector); - self - } + // /// + // pub fn with_selector(mut self, selector: &'a Selector) -> Self { + // self.selector.replace(selector); + // self + // } /// pub fn with_max_path_depth(mut self, max_path_depth: usize) -> Self { @@ -262,49 +338,53 @@ mod params { self } - /// - pub fn into_node_iter( - self, - only_results: bool, - ctx: &mut C, - ) -> Result, Error> - where - T: Select, - { - let vec = RefCell::new(Vec::new()); - let params = Params { - callback: Callback::SelectNode { - only_results, - cb: Box::new(|node, _| { - vec.borrow_mut().push(node); - Ok(()) - }), - }, - ..self - }; - - T::select(params, ctx)?; - Ok(vec.into_inner().into_iter()) - } + // /// + // pub fn into_node_iter( + // self, + // only_results: bool, + // ctx: &mut Ctx, + // ) -> Result, Error> + // where + // T: Select, + // { + // let vec = RefCell::new(Vec::new()); + // let params = Params { + // callback: Some(Callback::SelectNode { + // only_matched: only_results, + // cb: Box::new(|node, _| { + // vec.borrow_mut().push(node); + // Ok(()) + // }), + // }), + // ..self + // }; + + // T::select_in(params, ctx)?; + // Ok(vec.into_inner().into_iter()) + // } /// /// TODO: make this more like an actual iterator, that can pause across links - pub fn into_dag_iter(self, ctx: &mut C) -> Result, Error> + pub fn select_in(self, cid: Cid, ctx: Ctx) -> Result, Error> where - T: Select, + T: Select, { let vec = RefCell::new(Vec::new()); let params = Params { - callback: Callback::SelectDag { + state: State { + current_block: cid, + ..self.state + }, + callback: Some(Callback::SelectDag { cb: Box::new(|node, _| { vec.borrow_mut().push(node); Ok(()) }), - }, + }), ..self }; - T::select(params, ctx)?; + T::select_in(params, ctx)?; Ok(vec.into_inner().into_iter()) } @@ -380,24 +460,88 @@ mod dag_selection { use super::*; /// - pub struct DagSelection { - pub path: PathBuf, - pub dag: AnyRepresentation, - pub label: Option, + pub struct DagRefSelection<'a> { + pub path: &'a Path, + pub dag: &'a dyn ErasedRepresentation, + pub label: Option<&'a str>, } - impl From<(P, T, Option<&str>)> for DagSelection - where - P: Into, - T: Representation + 'static, - { - fn from((path, dag, label): (P, T, Option<&str>)) -> Self { + impl<'a> DagRefSelection<'a> { + /// + pub fn new(path: &'a Path, dag: &'a T, label: Option<&'a str>) -> Self + where + T: Representation + 'static, + { + Self { + path, + dag: dag, + label, + } + } + + /// + #[inline] + pub fn is(&self) -> bool + where + T: Representation + 'static, + { + (*self.dag).as_any().is::() + } + + /// + #[inline] + pub fn downcast_ref(&self) -> Option<&T> + where + T: Representation + 'static, + { + (*self.dag).as_any().downcast_ref() + } + } + + /// + pub struct DagRefMutSelection<'a> { + pub path: &'a Path, + pub dag: &'a mut dyn ErasedRepresentation, + pub label: Option<&'a str>, + } + + impl<'a> DagRefMutSelection<'a> { + /// + pub fn new(path: &'a Path, dag: &'a mut T, label: Option<&'a str>) -> Self + where + T: Representation + 'static, + { Self { - path: path.into(), - dag: dag.into(), - label: label.map(|s| s.to_string()), + path, + dag: dag, + label, } } + + /// + #[inline] + pub fn is(&self) -> bool + where + T: Representation + 'static, + { + (*self.dag).as_any().is::() + } + + /// + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> + where + T: Representation + 'static, + { + (*self.dag).as_any_mut().downcast_mut() + } + } + + /// + pub struct DagSelection { + pub path: PathBuf, + pub dag: Box, + pub label: Option, } impl DagSelection { @@ -408,10 +552,49 @@ mod dag_selection { { Self { path: path.to_owned(), - dag: dag.into(), + dag: Box::new(dag), label: label.map(str::to_string), } } + + /// + #[inline] + pub fn is(&self) -> bool + where + T: Representation + 'static, + { + (*self.dag).as_any().is::() + } + + /// + #[inline] + pub fn downcast_ref(&self) -> Option<&T> + where + T: Representation + 'static, + { + (*self.dag).as_any().downcast_ref() + } + + /// + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> + where + T: Representation + 'static, + { + (*self.dag).as_any_mut().downcast_mut() + } + + /// + #[inline] + pub fn downcast(self) -> Result + where + T: Representation + 'static, + { + self.dag + .downcast() + .map(|dag| *dag) + .map_err(|_| Error::downcast_failure::("incorrect type")) + } } // pub trait IntoDagIterator: Iterator + Sized { @@ -470,88 +653,115 @@ mod dag_selection { // } /// - #[derive(Clone, Debug, From, Deserialize, Serialize)] + #[derive( + Clone, + Debug, + From, + Deserialize, + Serialize, + // Representation + )] // #[from(forward)] + // #[ipld(internal)] pub enum SelectedNode { /// #[serde(rename = "null")] + // #[ipld(rename = "null")] Null, /// #[serde(rename = "bool")] + // #[ipld(rename = "bool")] Bool(bool), /// #[serde(rename = "int8")] + // #[ipld(rename = "int8")] Int8(i8), /// #[serde(rename = "int16")] + // #[ipld(rename = "int16")] Int16(i16), /// #[serde(rename = "int32")] + // #[ipld(rename = "int32")] Int32(i32), /// #[serde(rename = "int64")] + // #[ipld(rename = "int64")] Int64(i64), /// #[serde(rename = "int")] + // #[ipld(rename = "int")] Int128(i128), /// #[serde(rename = "uint8")] + // #[ipld(rename = "uint8")] Uint8(u8), /// #[serde(rename = "uint16")] + // #[ipld(rename = "uint16")] Uint16(u16), /// #[serde(rename = "uint32")] + // #[ipld(rename = "uint32")] Uint32(u32), /// #[serde(rename = "uint64")] + // #[ipld(rename = "uint64")] Uint64(u64), /// #[serde(rename = "uint128")] + // #[ipld(rename = "uint128")] Uint128(u128), /// #[serde(rename = "float32")] + // #[ipld(rename = "float32")] Float32(f32), /// #[serde(rename = "float64")] + // #[ipld(rename = "float64")] Float64(f64), /// #[serde(skip)] // TODO #[serde(rename = "string")] + // #[ipld(rename = "string")] String(String), /// #[serde(skip)] // TODO #[serde(rename = "bytes")] + // #[ipld(rename = "bytes")] Bytes(Bytes), /// #[serde(rename = "list")] + // #[ipld(rename = "list")] #[from(ignore)] List, /// #[serde(rename = "map")] + // #[ipld(rename = "map")] #[from(ignore)] Map, /// #[serde(skip)] // TODO #[serde(rename = "link")] + // #[ipld(rename = "link")] Link(Cid), } @@ -653,7 +863,7 @@ mod field { /// Wrapper type for types that can be used as dag keys or indices. #[doc(hidden)] - #[derive(Clone, Debug, Display, From)] + #[derive(Clone, Debug, Display, From, Hash, Eq, PartialEq, PartialOrd, Ord)] // #[from(forward)] pub enum Field<'a> { Key(Cow<'a, str>), @@ -663,6 +873,7 @@ mod field { impl<'a> Field<'a> { pub fn append_to_path(&self, path: &mut PathBuf) { + // todo: escaping to prevent hijacking root? match self { Self::Key(s) => path.push(s.as_ref()), // Self::CidKey(c) => path.push(c.to_string()), diff --git a/src/select/seed.rs b/src/select/seed.rs index 1b898bf..98e294b 100644 --- a/src/select/seed.rs +++ b/src/select/seed.rs @@ -1,24 +1,28 @@ use std::{borrow::Borrow, ops::Deref}; use crate::dev::{macros::derive_more::From, *}; -use maybestd::{fmt, marker::PhantomData, str::FromStr}; +use maybestd::{cell::Cell, fmt, marker::PhantomData, mem, str::FromStr}; /// The selection mode of the selector, which determines what gets visited, /// matched, sent and returned. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[doc(hidden)] pub enum SelectionMode { + /// ... + Decode, + /// Selection will invoke the provided callback on all traversed [`Node`]s. CoverNode, /// Selection will invoke the provided callback on all matched [`Node`]s. MatchNode, - Match, - /// Selection will invoke the provided callback on all matched [`Dag`]s. Select, + /// + SelectRef, + /// Selection will invoke the provided callback on all matched [`Dag`]s, /// optionally mutating the dag updates matching dags with the output of a callback. /// Optionally flushes changes after each callback. @@ -41,21 +45,27 @@ pub enum SelectionMode { /// e.g. /// ? - ergo, for ADLs: /// ? - map the input selector to another tailored for the underlying types -pub struct SelectorSeed<'a, Ctx, T> { +pub struct SelectorSeed<'a, Ctx, T> +where + T: Representation, +{ pub(crate) selector: &'a Selector, pub(crate) state: &'a mut State, - pub(crate) callback: Callback<'a, Ctx, T>, - pub(crate) ctx: &'a mut Ctx, + pub(crate) callback: Option>, + pub(crate) ctx: Ctx, + _t: PhantomData, } -pub type EmptySeed = SelectorSeed<'static, (), T>; +/// +pub type EmptySeed = SelectorSeed<'static, Ctx, T>; // Blanket impl for all `CodecSeed`s that implement `Visitor` for a given `T`. // Doing this allows us to more easily "escape" [`serde`]'s traits into our own // methods for selection, requiring only that we implement [`Visitor`] for // `CodecSeed<..., T>`. -repr_serde!(@def_seed); +repr_serde!(@def_walk); +/* #[doc(hidden)] pub trait SeedType: Sized { // type Input; @@ -103,6 +113,7 @@ impl<'a, Ctx, T, U> SeedType for SelectorSeed<'a, Ctx, T> { self.selector } } + */ // impl<'de, const C: u64, T> CodecSeed, T> // // where @@ -151,7 +162,7 @@ impl<'a, Ctx, T, U> SeedType for SelectorSeed<'a, Ctx, T> { impl<'a, Ctx, T> fmt::Debug for SelectorSeed<'a, Ctx, T> where Ctx: Context, - T: fmt::Debug + Representation, + T: Representation, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SelectorSeed") @@ -163,24 +174,44 @@ where } // TODO: be lazier: provide a mode method that lets us skip any dag-deserialization work, while also letting us just call what we want without a lot of branching -impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> { +impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> +where + T: Representation, +{ /// #[inline] - const fn _mode(&self) -> SelectionMode { + pub const fn _mode(&self) -> SelectionMode { match (&self.callback, self.selector.is_matcher()) { - (Callback::SelectNode { .. }, true) => SelectionMode::MatchNode, - (Callback::SelectNode { .. }, _) => SelectionMode::CoverNode, - (Callback::SelectDag { .. }, true) | (Callback::MatchDag { .. }, _) => { - SelectionMode::Match - } - (Callback::SelectDag { .. }, _) => SelectionMode::Select, - (Callback::Patch { .. }, _) => SelectionMode::Patch, + (None, _) => SelectionMode::Decode, + (Some(Callback::SelectNode { .. }), true) => SelectionMode::MatchNode, + (Some(Callback::SelectNode { .. }), _) => SelectionMode::CoverNode, + // (Callback::SelectDag { .. }, true) | (Callback::MatchDag { .. }, _) => { + // SelectionMode::Match + // } + (Some(Callback::SelectDag { .. }), _) => SelectionMode::Select, + (Some(Callback::SelectRef { .. }), _) => SelectionMode::SelectRef, + (Some(Callback::Patch { .. }), _) => SelectionMode::Patch, + } + } + + /// + #[inline] + pub const fn _selector(&self) -> &Selector { + &self.selector + } + + /// + #[inline] + pub const fn is_decode(&self) -> bool { + match self._mode() { + SelectionMode::Decode => true, + _ => false, } } /// #[inline] - pub fn is_node_select(&self) -> bool { + pub const fn is_select_node(&self) -> bool { match self._mode() { SelectionMode::CoverNode | SelectionMode::MatchNode => true, _ => false, @@ -189,22 +220,42 @@ impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> { /// #[inline] - pub fn is_dag_select(&self) -> bool { + pub const fn is_select_dag(&self) -> bool { match self._mode() { - SelectionMode::Select | SelectionMode::Match => true, + SelectionMode::Select | SelectionMode::Decode => true, _ => false, } } /// #[inline] - pub fn is_patch(&self) -> bool { + pub const fn is_select_ref(&self) -> bool { + match self._mode() { + SelectionMode::SelectRef => true, + _ => false, + } + } + + /// + #[inline] + pub const fn is_patch(&self) -> bool { match self._mode() { SelectionMode::Patch => true, _ => false, } } } + +// impl<'a, Ctx, T> Drop for SelectorSeed<'a, Ctx, T> +// where +// T: Representation, +// { +// fn drop(&mut self) { +// self.state.ascend::(); +// mem::drop(self.callback.take()); +// } +// } + impl<'a, Ctx, T> SelectorSeed<'a, Ctx, T> where Ctx: Context, @@ -224,43 +275,53 @@ where /// #[inline] - pub(crate) fn from_parts( + pub fn from_parts( selector: &'a Selector, state: &'a mut State, - callback: Callback<'a, Ctx, T>, - ctx: &'a mut Ctx, + callback: Option>, + ctx: Ctx, ) -> Self { Self { selector, state, callback, ctx, + _t: PhantomData, } } /// - pub fn wrap(self, conv: F) -> SelectorSeed<'a, Ctx, U> - where - Ctx: 'a, - T: 'static, - U: Representation + 'static, - // T: From + 'static, - F: Fn(U) -> T + Clone + 'a, - { - let Self { - selector, - state, - callback, - ctx, - } = self; - SelectorSeed { - selector, - state, - callback: callback.wrap::(conv), - ctx, - } + #[inline] + #[doc(hidden)] + pub(crate) fn into_parts( + self, + ) -> (&'a Selector, &'a mut State, Option>, Ctx) { + (self.selector, self.state, self.callback, self.ctx) } + // /// + // pub fn wrap(self, conv: F) -> SelectorSeed<'a, Ctx, U> + // where + // Ctx: 'a, + // T: 'static, + // U: Representation + 'static, + // // T: From + 'static, + // F: Fn(U) -> T + Clone + 'a, + // { + // let Self { + // selector, + // state, + // callback, + // ctx, + // } = self; + // SelectorSeed { + // selector, + // state, + // callback: callback.map(|c| c.wrap::(conv)), + // ctx, + // } + // } + // /// // fn wrap_advanced(self, conv: F) -> SelectorSeed<'a, Ctx, U> // where @@ -292,51 +353,145 @@ where T: Representation, { /// - pub fn handle_node(&mut self, node: SelectedNode) -> Result<(), Error> { - if let Some(matcher) = self.selector.as_matcher() { - self.callback - .select_node(self.state.path(), node, matcher.label.as_deref(), self.ctx) - } else { - self.callback.cover_node(self.state.path(), node, self.ctx) + pub fn select_node(&mut self, node: SelectedNode) -> Result, Error> { + let path = self.state.path(); + match (self._mode(), &mut self.callback, self.selector.as_matcher()) { + (SelectionMode::MatchNode, Some(cb), Some(m)) => { + cb.match_node(path, node, m.label.as_deref(), &mut self.ctx)?; + Ok(AstResult::Ok) + } + (SelectionMode::CoverNode, Some(cb), _) => { + cb.cover_node(path, node, &mut self.ctx)?; + Ok(AstResult::Ok) + } + _ => unreachable!(), + } + } + + /// + pub fn select_dag(&mut self, dag: T) -> Result, Error> + where + T: 'static, + { + let path = self.state.path(); + match (self._mode(), &mut self.callback, self.selector.as_matcher()) { + (SelectionMode::Decode, _, _) => Ok(AstResult::Value(dag)), + (SelectionMode::Select, Some(cb), Some(m)) => { + cb.match_dag(path, dag, m.label.as_deref(), &mut self.ctx)?; + Ok(AstResult::Ok) + } + _ => self.select_ref(&dag), } } /// - pub fn handle_dag(&mut self, dag: T) -> Result<(), Error> + pub fn select_ref(&mut self, dag: &T) -> Result, Error> where - T: Representation + 'static, + T: 'static, { - let matcher = self.selector.try_as_matcher()?; - self.callback - .select_dag((self.state.path(), dag, matcher.label.as_deref()), self.ctx) + let path = self.state.path(); + match (self._mode(), &mut self.callback, self.selector.as_matcher()) { + (SelectionMode::SelectRef, Some(cb), Some(m)) => { + cb.match_ref(path, dag, m.label.as_deref(), &mut self.ctx)?; + Ok(AstResult::Ok) + } + (SelectionMode::MatchNode | SelectionMode::CoverNode, _, _) => { + self.select_node(dag.to_selected_node()) + } + _ => unreachable!(), + } } - /* /// - fn to_field_select_seed<'b, U>( - &'b mut self, + pub fn patch_dag(&mut self, dag: &mut T) -> Result, Error> + where + T: 'static, + { + let path = self.state.path(); + match (self._mode(), &mut self.callback, self.selector.as_matcher()) { + (SelectionMode::Patch, Some(cb), Some(m)) => { + cb.patch_dag(path, dag, m.label.as_deref(), &mut self.ctx)?; + Ok(AstResult::Ok) + } + _ => unreachable!(), + } + } + + // pub(crate) fn select_index_dag<'b, U>( + // &mut self, + // field: &Field<'_>, + // ) -> Result>, Error> + // where + // 'a: 'b, + // U: Representation, + // { + // match self.selector.next(Some(field)) { + // None => Ok(None), + // Some(s) => Ok(Some(SelectorSeed::from_parts( + // s, + // self.state.descend::(&field)?, + // self.callback.clone(), + // self.ctx, + // ))), + // } + // } + + // pub(crate) fn select_index_ref(&mut self, ) + + // pub(crate) fn patch_index_dag(&mut self, ) + + // pub fn cover_node(&mut self, node: SelectedNode) -> Result, Error> {} + + // /// + // pub fn handle_node(&mut self, node: SelectedNode) -> Result<(), Error> { + // if let Some(matcher) = self.selector.as_matcher() { + // self.callback + // .select_node(self.state.path(), node, matcher.label.as_deref(), self.ctx) + // } else { + // self.callback.cover_node(self.state.path(), node, self.ctx) + // } + // } + + // /// + // pub fn handle_dag(&mut self, dag: T) -> Result<(), Error> + // where + // T: Representation + 'static, + // { + // let matcher = self.selector.try_as_matcher()?; + // self.callback + // .select_dag((self.state.path(), dag, matcher.label.as_deref()), self.ctx) + // } + + /// + #[inline] + pub fn to_field_select_seed<'b, U>( + selector: &'b Selector, + state: &'b mut State, + callback: Option>, + ctx: Ctx, field: &Field<'b>, - match_cb: Option + 'b>>, + // match_cb: Option + 'b>>, // match_cb: Option<&'b mut dyn MatchDagOp>, // match_cb: Option - ) -> Result, Error> + ) -> Result>, Error> where - // 'a: 'b, - // Ctx: 'a, + 'a: 'b, + Ctx: 'b, U: Representation, // F: FnOnce(U, Ctx) -> Result<(), Error>, { - let selector = self.selector.try_next(Some(field))?; - self.state.descend::(&field)?; - Ok(SelectorSeed { - selector, - state: self.state, - callback: self.callback.wrap_match::(match_cb), - ctx: self.ctx, - }) + match selector.next(Some(field)) { + None => Ok(None), + Some(s) => Ok(Some(SelectorSeed::from_parts( + s, + state.descend::(&field)?, + callback.clone(), + ctx, + ))), + } } - */ + /* /// Execute the next [`Selector`] against the next element of the /// [`ListIterator`]. /// @@ -346,51 +501,84 @@ where /// seed + iter -> select/patch_dm(iter) -> handle_index /// - if selector for current index exists, descend /// - else, ignore - pub fn handle_index<'b, const C: u64, U>( - &'b mut self, - iter: &mut impl ListIterator, - match_cb: Option + 'b>>, + pub fn handle_index<'b, const MC: u64, U>( + &'a mut self, + iter: &'b mut impl ListIterator<'b, U>, + // new_cb: Either<(), (&mut U, Box>)> + // match_cb: Option + 'b>>, // match_cb: Option<&'b mut dyn MatchDagOp>, - ) -> Result + ) -> Result>, Error> where + 'a: 'b, U: Select, { - let was_empty = iter.next_element_seed::(|idx| { + // match self._mode() { + // SelectionMode::Decode => { + + // }, + // SelectionMode::CoverNode => unimplemented!(), + // SelectionMode::MatchNode => unimplemented!(), + // SelectionMode::Select => unimplemented!(), + // SelectionMode::SelectRef => unimplemented!(), + // SelectionMode::Patch => unimplemented!(), + // } + + let res = iter.next_element_seed::(|idx| { let field = Field::Index(idx); - Ok(Some(SelectorSeed { - selector: self.selector.try_next(Some(&field))?, - state: self.state.descend::(&field)?, - callback: self.callback.wrap_match::(match_cb), - ctx: self.ctx, - })) + match self.selector.next(Some(&field)) { + None => Ok(None), + Some(selector) => Ok(Some(SelectorSeed { + selector, + state: self.state.descend::(&field)?, + callback: self.callback.clone(), + ctx: self.ctx, + _t: PhantomData, + })), + } })?; - self.state.ascend::(); - Ok(was_empty) + match res { + Some(AstResult::Ok) => Ok(Some(AstResult::Ok)), + Some(AstResult::Value(v)) => Ok(Some(AstResult::Value(v))), + // Some(AstResult::Continue) => Ok(Some(AstResult::Continue)), + // Some(AstResult::Break) => Ok(Some(AstResult::Break)), + // Some(Err(e)) => Err(e), + _ => unimplemented!(), + } } /// - pub fn handle_field<'b, const C: u64, K, V>( + pub fn handle_field<'b, const MC: u64, K, V>( &'b mut self, iter: &mut impl MapIterator, - match_cb: Option + 'b>>, - ) -> Result + // match_cb: Option + 'b>>, + ) -> Result>, Error> where + // 'a: 'b, K: StringRepresentation, ::Err: fmt::Display, V: Select, { - let was_empty = iter.next_entry_seed::(|key| { - let field = Field::Key(key.into()); - Ok(Some(SelectorSeed { - selector: self.selector.try_next(Some(&field))?, - state: self.state.descend::(&field)?, - callback: self.callback.wrap_match::(match_cb), - ctx: self.ctx, - })) - })?; - self.state.ascend::(); - Ok(was_empty) + let res = + iter.next_entry_seed::(|field| match self.selector.next(Some(&field)) { + None => Ok(None), + Some(selector) => Ok(Some(SelectorSeed { + selector, + state: self.state.descend::(&field)?, + callback: self.callback.clone(), + ctx: self.ctx, + _t: PhantomData, + })), + })?; + match res { + Some(AstResult::Ok) => Ok(Some(AstResult::Ok)), + Some(AstResult::Value(v)) => Ok(Some(AstResult::Value(v))), + // Some(AstResult::Continue) => Ok(Some(AstResult::Continue)), + // Some(AstResult::Break) => Ok(Some(AstResult::Break)), + // Some(Err(e)) => Err(e), + _ => unimplemented!(), + } } + */ } // patch methods @@ -489,23 +677,28 @@ macro_rules! repr_serde { @link { $($visit_link_fns:tt)* } ) => { #[doc(hidden)] - impl<'_a, 'de, const MC: u64, Ctx, $($generics)*> + impl<'__a: 'de, 'de, const MC: u64, Ctx, $($generics)*> $crate::dev::Visitor<'de> for - Seed, $T> + // Seed, $T> + AstWalk<'__a, MC, Ctx, $T> where Ctx: $crate::dev::Context, + // $T: '__a, $($bounds)* { - type Value = <$crate::dev::SelectorSeed<'_a, Ctx, $T> as SeedType<$T>>::Output; + // type Value = <$crate::dev::SelectorSeed<'__a, Ctx, $T> as SeedType<$T>>::Output; + type Value = AstResult<$T>; $($visit_fns)* } #[doc(hidden)] - impl<'_a, 'de, const MC: u64, Ctx, $($generics)*> + impl<'__a: 'de, 'de, const MC: u64, Ctx, $($generics)*> LinkVisitor<'de, MC> for - Seed, $T> + // Seed, $T> + AstWalk<'__a, MC, Ctx, $T> where Ctx: $crate::dev::Context, + // $T: '__a, $($bounds)* { $($visit_link_fns)* @@ -520,20 +713,26 @@ macro_rules! repr_serde { (@select for $T:ty { $($generics:tt)* } { $($bounds:tt)* }) => { impl $crate::dev::Select for $T where + $T: 'static, Ctx: $crate::dev::Context, $($bounds)* { #[doc(hidden)] - #[inline] - fn __select_de<'a, 'de, const C: u64, D>( - seed: $crate::dev::SelectorSeed<'a, Ctx, Self>, - deserializer: D, - ) -> Result<(), D::Error> - where - D: $crate::dev::Deserializer<'de>, - { - Seed::::from(seed).deserialize(deserializer) - } + type Walker<'__a, const MC: u64> = AstWalk<'__a, MC, Ctx, Self> where Ctx: '__a; + + // #[doc(hidden)] + // #[inline] + // fn __select_de<'a, 'de, const MC: u64, D>( + // seed: $crate::dev::SelectorSeed<'a, Ctx, Self>, + // deserializer: D, + // ) -> Result<(), D::Error> + // where + // D: $crate::dev::Deserializer<'de>, + // { + // // Seed::::from(seed).deserialize(deserializer) + // AstWalk::<'a, MC, Ctx, $T>::from(seed).deserialize(deserializer)?; + // Ok(()) + // } } }; @@ -606,6 +805,158 @@ macro_rules! repr_serde { T::deserialize_with_visitor::(deserializer, self) } } + + $crate::repr_serde!(@def_walk); + }; + (@def_walk) => { + /// A visitor that walks the AST + // #[derive(Debug)] + #[doc(hidden)] + pub struct AstWalk<'a, const MC: u64 = IDENTITY, Ctx = (), T = Any> + where + Ctx: Context + 'a, + T: Representation, + { + inner: Option>, + } + + impl<'a, const MC: u64, Ctx, T> AstWalk<'a, MC, Ctx, T> + where + Ctx: Context + 'a, + T: Representation, + { + #[inline(always)] + pub fn into_inner(self) -> SelectorSeed<'a, Ctx, T> { + self.inner.unwrap() + } + #[inline(always)] + pub fn selector(&self) -> &Selector { + self.inner.as_ref().unwrap()._selector() + } + #[inline(always)] + pub fn mode(&self) -> SelectionMode { + self.inner.as_ref().map(|s| s._mode()).unwrap_or(SelectionMode::Decode) + } + #[inline(always)] + pub fn from_parts( + selector: &'a Selector, + state: &'a mut State, + callback: Option>, + ctx: Ctx, + ) -> Self { + let inner = Some(SelectorSeed::from_parts( + selector, + state, + callback, + ctx, + )); + Self { inner } + } + // pub fn decode<'de, __D>(deserializer: __D) -> Result + // where + // __D: Deserializer<'a>, + // Self: LinkVisitor<'de, MC, Value = AstResult>, + // T: 'de, + // { + // let res = DeserializeSeed::deserialize(AstWalk::<'de, MC, (), T>::default(), deserializer)?; + // Ok(res.unwrap_val()) + // } + // + // #[inline] + // pub(crate) fn select_in<'de, D>( + // self, + // deserializer: D, + // ) -> Result<(), Error> + // where + // 'a: 'de, + // Self: LinkVisitor<'de, MC>, + // D: Deserializer<'de>, + // { + // deserialize_with_visitor::<'de, MC, D, Self, T>(deserializer, self) + // .map_err(|_| Error::SelectionFailure(T::NAME.into()))?; + // Ok(()) + // } + // + // #[inline] + // pub(crate) fn select<'de>( + // self, + // dag: &'de T, + // ) -> Result<(), Error> + // where + // 'a: 'de, + // { + // Ok(()) + // } + // + // #[inline] + // pub(crate) fn patch<'de>( + // self, + // dag: &'de mut T, + // ) -> Result<(), Error> + // where + // 'a: 'de, + // { + // Ok(()) + // } + } + + impl<'a, const MC: u64, Ctx, T> AsRef> for AstWalk<'a, MC, Ctx, T> + where + Ctx: Context + 'a, + T: Representation, + { + #[inline(always)] + fn as_ref(&self) -> &SelectorSeed<'a, Ctx, T> { + self.inner.as_ref().unwrap() + } + } + impl<'a, const MC: u64, Ctx, T> AsMut> for AstWalk<'a, MC, Ctx, T> + where + Ctx: Context + 'a, + T: Representation, + { + #[inline(always)] + fn as_mut(&mut self) -> &mut SelectorSeed<'a, Ctx, T> { + self.inner.as_mut().unwrap() + } + } + impl<'a, const MC: u64, Ctx, T> Default for AstWalk<'a, MC, Ctx, T> + where + Ctx: Context + 'a, + T: Representation, + { + fn default() -> Self { + Self { inner: None } + } + } + impl<'a, const MC: u64, Ctx, T> From> for AstWalk<'a, MC, Ctx, T> + where + Ctx: Context + 'a, + T: Representation, + { + #[inline(always)] + fn from(inner: SelectorSeed<'a, Ctx, T>) -> Self { + Self { inner: Some(inner) } + } + } + + #[doc(hidden)] + impl<'a: 'de, 'de, const MC: u64, Ctx, T> DeserializeSeed<'de> for AstWalk<'a, MC, Ctx, T> + where + Self: LinkVisitor<'de, MC, Value = AstResult>, + Ctx: Context + 'a, + T: Representation + 'de, + { + type Value = >::Value; + + #[inline] + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + T::deserialize_with_visitor::(deserializer, self) + } + } }; } @@ -647,21 +998,20 @@ macro_rules! repr_serde { /// /// ! dream features: /// 1. provide hooks forcompat with rkyv / other frameworks -pub trait Walk<'de, 'a: 'de, const MC: u64 = IDENTITY, T = Any> +pub trait Walk<'de, const MC: u64 = IDENTITY, T = Any> where - T: Representation + 'de, + // T: Representation + 'de, Self: Default - + LinkVisitor<'de, MC, Value = AstResult<'de, T>> - + DeserializeSeed<'de, Value = AstResult<'de, T>>, + // + LinkVisitor<'de, MC, Value = AstResult> + + DeserializeSeed<'de, Value = AstResult>, { } -impl<'de, 'a: 'de, const MC: u64, T, W> Walk<'de, 'a, MC, T> for W -where - T: Representation + 'de, +impl<'de, const MC: u64, T, W> Walk<'de, MC, T> for W where + // T: Representation + 'de, W: Default - + LinkVisitor<'de, MC, Value = AstResult<'de, T>> - + DeserializeSeed<'de, Value = AstResult<'de, T>>, + // + LinkVisitor<'de, MC, Value = AstResult> + + DeserializeSeed<'de, Value = AstResult> { } @@ -673,23 +1023,36 @@ where // unimplemented!() // } -/// -pub struct AstWalk<'a, const MC: u64 = IDENTITY, Ctx = (), T = Any>(pub SelectorSeed<'a, Ctx, T>); +// /// +// #[derive(Debug, Default)] +// pub struct AstWalk<'a, const MC: u64 = IDENTITY, Ctx = (), T = Any> +// where +// Ctx: Context, +// T: Representation, +// { +// inner: Option>, +// // continuation: +// } /// #[derive(Debug)] -pub enum AstResult<'a, T> { +pub enum AstResult { /// Ok, /// Value(T), /// - Ref(&'a T), - /// - RefMut(&'a mut T), + Continue(Selector, State), + // /// + // Ref(&'a T), + // /// + // RefMut(&'a mut T), + // Continue( + // (&Selector, State) // SelectorSeed<'a, Ctx, T> + // ), } -impl<'a, T> AstResult<'a, T> { +impl AstResult { #[inline(always)] pub(crate) fn unwrap_val(self) -> T { match self { @@ -699,59 +1062,29 @@ impl<'a, T> AstResult<'a, T> { } } -impl<'a, const MC: u64, Ctx, T> AstWalk<'a, MC, Ctx, T> -where - T: Representation, -{ - #[inline(always)] - fn into_inner(self) -> SelectorSeed<'a, Ctx, T> { - self.0 - } - #[inline(always)] - fn selector(&self) -> &Selector { - self.0.selector - } - #[inline(always)] - fn mode(&self) -> SelectionMode { - self.0._mode() - } -} +// impl<'a, T> Try for AstResult<'a, T> { +// type Ok = T; +// type Error = Error; -impl<'a, const MC: u64, Ctx, T> AsRef> for AstWalk<'a, MC, Ctx, T> { - #[inline(always)] - fn as_ref(&self) -> &SelectorSeed<'a, Ctx, T> { - &self.0 - } -} -impl<'a, const MC: u64, Ctx, T> AsMut> for AstWalk<'a, MC, Ctx, T> { - #[inline(always)] - fn as_mut(&mut self) -> &mut SelectorSeed<'a, Ctx, T> { - &mut self.0 - } -} -impl<'a, const MC: u64, Ctx, T> From> for AstWalk<'a, MC, Ctx, T> { - #[inline(always)] - fn from(seed: SelectorSeed<'a, Ctx, T>) -> Self { - Self(seed) - } -} +// #[inline(always)] +// fn into_result(self) -> Result { +// match self { +// AstResult::Ok => Ok(()), +// AstResult::Value(val) => Ok(val), +// _ => unreachable!("AstResult return type should be known"), +// } +// } -impl<'de, 'a: 'de, const MC: u64, Ctx, T: Representation> DeserializeSeed<'de> - for AstWalk<'a, MC, Ctx, T> -where - Self: LinkVisitor<'de, MC>, - T: Representation, -{ - type Value = >::Value; +// #[inline(always)] +// fn from_error(_: Self::Error) -> Self { +// unreachable!("AstResult return type should be known") +// } - #[inline] - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - T::deserialize_with_visitor::(deserializer, self) - } -} +// #[inline(always)] +// fn from_ok(val: Self::Ok) -> Self { +// AstResult::Value(val) +// } +// } // impl<'de, 'a: 'de, const MC: u64, Ctx, T> DeserializeSeed<'de> for AstWalk<'a, MC, Ctx, T> // where diff --git a/src/select/selectors.rs b/src/select/selectors.rs index 43308e3..3ed1608 100644 --- a/src/select/selectors.rs +++ b/src/select/selectors.rs @@ -160,37 +160,37 @@ schema! { pub type ExploreRecursive struct { /// pub sequence Selector (rename ":>") - /// - pub limit RecursionLimit (rename "l") + // /// + // pub limit RecursionLimit (rename "l") /// if a node matches, we won't match it nor explore it's children pub stopAt optional Condition (rename "!") } } -schema! { - /// - #[ipld_attr(internal)] - #[derive(Clone, Debug, From)] - pub type RecursionLimit union { - /// - | RecursionLimit_None "none" - /// - | RecursionLimit_Depth "depth" - } representation keyed -} -schema! { - /// - #[ipld_attr(internal)] - #[derive(Clone, Debug, Default)] - pub type RecursionLimit_None struct {} -} -schema! { - /// - #[ipld_attr(internal)] - #[derive(Clone, Debug, Default, From)] - #[from(forward)] - pub type RecursionLimit_Depth int -} +// schema! { +// /// +// #[ipld_attr(internal)] +// #[derive(Clone, Debug, From)] +// pub type RecursionLimit union { +// /// +// | RecursionLimit_None "none" +// /// +// | RecursionLimit_Depth "depth" +// } representation keyed +// } +// schema! { +// /// +// #[ipld_attr(internal)] +// #[derive(Clone, Debug, Default)] +// pub type RecursionLimit_None struct {} +// } +// schema! { +// /// +// #[ipld_attr(internal)] +// #[derive(Clone, Debug, Default, From)] +// #[from(forward)] +// pub type RecursionLimit_Depth int +// } schema! { /// ExploreRecursiveEdge is a special sentinel value which is used to mark @@ -521,27 +521,27 @@ impl Selector { /// (key or index). /// TODO: matcher is infinite; need to distinguish link boundaries /// TODO: should return Option<&Selector> - pub fn try_next<'a>(&self, field: Option<&Field<'_>>) -> Result<&Selector, Error> { + pub fn next<'a>(&self, field: Option<&Field<'_>>) -> Option<&Selector> { match (self, field) { - (Self::Matcher(_), _) => Ok(self), - (Self::ExploreAll(inner), _) => Ok(&inner.next), + (Self::Matcher(_), _) => Some(self), + (Self::ExploreAll(inner), _) => Some(&inner.next), // TODO assert that provided field/index matches what the selector defines, otherwise return None (Self::ExploreFields { .. }, Some(f)) => todo!(), (Self::ExploreIndex(inner), Some(f)) if f.is_idx(inner.index as usize) => { - Ok(&inner.next) + Some(&inner.next) } (Self::ExploreRange(inner), Some(f)) if f.as_usize() .filter(|idx| inner.contains(&(*idx as Int))) .is_some() => { - Ok(&inner.next) + Some(&inner.next) } - (Self::ExploreRecursive(inner), _) => Ok(&inner.sequence), + (Self::ExploreRecursive(inner), _) => Some(&inner.sequence), (Self::ExploreRecursiveEdge(_), _) => todo!(), (Self::ExploreUnion { .. }, _) => todo!(), - (Self::ExploreInterpretAs(inner), _) => Ok(&inner.next), - _ => Err(Error::missing_next_selector(&self)), + (Self::ExploreInterpretAs(inner), _) => Some(&inner.next), + _ => None, } } @@ -691,11 +691,11 @@ impl ExploreRecursive { pub const CODE: char = 'R'; } -impl Default for RecursionLimit { - fn default() -> Self { - Self::RecursionLimit_None(RecursionLimit_None {}) - } -} +// impl Default for RecursionLimit { +// fn default() -> Self { +// Self::RecursionLimit_None(RecursionLimit_None {}) +// } +// } /* ExploreUnion */ diff --git a/src/select/state.rs b/src/select/state.rs index c10e038..1e2b867 100644 --- a/src/select/state.rs +++ b/src/select/state.rs @@ -97,7 +97,7 @@ use maybestd::{ // _t: PhantomData<(T, U)>, // } // -// pub struct PatchParams<'a, C, T, U = T> { +// pub struct PatchParams<'a, C, U = T> { // /// current dag we're selecting against // /// if none, then load and store while patching // current: &'a mut T, @@ -108,15 +108,16 @@ use maybestd::{ // } // // impl Params for SelectParams {} -// impl<'a, C, T, U> Params for PatchParams<'a, C, T, U> {} +// impl<'a, C, U> Params for PatchParams<'a, C, U> {} -pub(crate) use callbacks::*; +pub use callbacks::*; mod callbacks { use super::*; - pub use match_dag::*; + // pub use match_dag::*; pub use patch_dag::*; pub use select_dag::*; + pub use select_dag_ref::*; pub use select_node::*; mod select_node { @@ -183,6 +184,41 @@ mod callbacks { } } } + mod select_dag_ref { + use super::*; + + /// + pub trait SelectDagRefOp: + FnMut(DagRefSelection<'_>, &mut C) -> Result<(), Error> + { + /// + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a; + } + + impl SelectDagRefOp for F + where + F: FnMut(DagRefSelection<'_>, &mut C) -> Result<(), Error> + Clone, + { + fn clone_box<'a>(&self) -> Box + 'a> + where + Self: 'a, + { + Box::new(self.clone()) + } + } + + impl<'a, C> Clone for Box + 'a> + where + C: 'a, + { + fn clone(&self) -> Self { + (**self).clone_box() + } + } + } + #[cfg(feature = "skipped")] mod match_dag { use super::*; @@ -220,18 +256,20 @@ mod callbacks { use super::*; /// - pub trait PatchDagOp: FnMut(&mut T, &mut C) -> Result { + pub trait PatchDagOp: + FnMut(DagRefMutSelection<'_>, &mut C) -> Result + { /// - fn clone_box<'a>(&self) -> Box + 'a> + fn clone_box<'a>(&self) -> Box + 'a> where Self: 'a; } - impl PatchDagOp for F + impl PatchDagOp for F where - F: FnMut(&mut T, &mut C) -> Result + Clone, + F: FnMut(DagRefMutSelection<'_>, &mut C) -> Result + Clone, { - fn clone_box<'a>(&self) -> Box + 'a> + fn clone_box<'a>(&self) -> Box + 'a> where Self: 'a, { @@ -239,9 +277,8 @@ mod callbacks { } } - impl<'a, T, C> Clone for Box + 'a> + impl<'a, C> Clone for Box + 'a> where - T: 'a, C: 'a, { fn clone(&self) -> Self { @@ -253,52 +290,64 @@ mod callbacks { /// /// TODO: merge this back with state #[doc(hidden)] - pub enum Callback<'a, C, T> { + pub enum Callback<'a, C> { + /// Selects nodes covered/visited by the selection. SelectNode { // state + only_matched: bool, cb: Box + 'a>, - only_results: bool, }, + /// Selects (dyn) dags matched by the selection. SelectDag { + // /// + // current: &'a T, // state // TODO: does this need to be cloneable? it is either called on U, or wrapped cb: Box + 'a>, }, - MatchDag { - // Option; if None, deserializes up to links - cb: Box + 'a>, + // /// Select (exact) dags + // MatchDag { + // // Option; if None, deserializes up to links + // cb: Box + 'a>, + // }, + SelectRef { + // current: &'a T, + cb: Box + 'a>, }, Patch { /// current dag we're selecting against /// if none, then load and store while patching - // current: &'a mut T, + // current: &'a mut T, // flush: bool, - // op to perform on matching dags, allowing update-inplace - cb: Box + 'a>, + /// op to perform on matching dags, allowing update-inplace + cb: Box + 'a>, // op: PatchFn, }, } - impl<'a, C, T> fmt::Debug for Callback<'a, C, T> + impl<'a, C> fmt::Debug for Callback<'a, C> where C: Context, - T: Representation, + // T: Representation, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::SelectNode { only_results, .. } => f + Self::SelectNode { + only_matched: only_results, + .. + } => f .debug_struct("SelectionParams::SelectNode") - .field("source", &T::NAME) - .field("only_results", only_results) + // .field("source", &T::NAME) + .field("only_matched", only_results) .finish(), Self::SelectDag { .. } => f .debug_struct("SelectionParams::SelectDag") - .field("source", &T::NAME) - .finish(), - Self::MatchDag { .. } => f - .debug_struct("SelectionParams::MatchDag") - .field("source", &T::NAME) + // .field("source", &T::NAME) .finish(), + // Self::MatchDag { .. } => f + // .debug_struct("SelectionParams::MatchDag") + // .field("source", &T::NAME) + // .finish(), _ => unimplemented!(), // Self::Patch { current, flush, .. } => f // .debug_struct("SelectionParams::Patch") @@ -309,45 +358,45 @@ mod callbacks { } } - impl<'a, C, T> Clone for Callback<'a, C, T> + impl<'a, C> Clone for Callback<'a, C> where C: Context + 'a, - T: Representation + 'a, + // T: Representation + 'a, { fn clone(&self) -> Self { match self { - Self::SelectNode { cb, only_results } => Self::SelectNode { + Self::SelectNode { + only_matched: only_results, + cb, + } => Self::SelectNode { + only_matched: *only_results, cb: cb.clone(), - only_results: *only_results, }, Self::SelectDag { cb } => Self::SelectDag { cb: cb.clone() }, - Self::MatchDag { cb } => Self::MatchDag { cb: cb.clone() }, - _ => unimplemented!(), + Self::SelectRef { cb } => Self::SelectRef { cb: cb.clone() }, + Self::Patch { cb } => Self::Patch { cb: cb.clone() }, } } } - impl<'a, C, T> Default for Callback<'a, C, T> - where - C: Context, - T: Representation, - { - /// Defaults to a no-op function for selecting nodes. - fn default() -> Self { - Self::SelectNode { - cb: Box::new(|_, _| Ok(())), - only_results: true, - } - } - } + // impl<'a, C> Default for Callback<'a, C> + // where + // C: Context, + // // T: Representation, + // { + // /// Defaults to a no-op function for selecting nodes. + // fn default() -> Self { + // Self::new_select_node::(|_, _| Ok(())) + // } + // } - // impl<'a, C, T, Cb> Into> for Cb + // impl<'a, C, Cb> Into> for Cb // where // C: Context, // T: Representation, // Cb: SelectNodeOp + 'a, // { - // fn into(self) -> SelectionCallback<'a, C, T> { + // fn into(self) -> SelectionCallback<'a, C> { // Self::SelectNode { // cb: Box::new(self), // only_results: false, @@ -355,61 +404,125 @@ mod callbacks { // } // } - impl<'a, C, T> Callback<'a, C, T> + impl<'a, C> Callback<'a, C> where C: Context, - T: Representation, + // T: Representation, { - // Return a callback that will be called on `U`, providing the original - // callback with `T`. - pub(crate) fn wrap(self, conv: F) -> Callback<'a, C, U> + pub(crate) fn new_select_node(func: F) -> Self where - C: 'a, - U: Representation + 'static, - T: 'static, - // T: From + 'static, - F: Fn(U) -> T + Clone + 'a, + F: SelectNodeOp + 'a, { - match self { - Self::SelectNode { cb, only_results } => Callback::SelectNode { cb, only_results }, - Self::SelectDag { mut cb } => { - let cb = Box::new(move |selection: DagSelection, ctx: &mut C| { - let inner_dag = selection.dag.downcast::()?; - let dag = conv(inner_dag).into(); - cb(DagSelection { dag, ..selection }, ctx) - }); - Callback::SelectDag { cb } - } - Self::MatchDag { mut cb } => { - let cb = Box::new(move |dag: U, ctx: &mut C| cb(conv(dag), ctx)); - Callback::MatchDag { cb } - } - _ => unimplemented!(), + Self::SelectNode { + cb: Box::new(func), + only_matched: M, } } - // TODO: implement a clone method, delegate to that in some branches - pub(crate) fn wrap_match<'b, U>( - &'b mut self, - match_cb: Option + 'b>>, - ) -> Callback<'b, C, U> + pub(crate) fn new_select(func: F) -> Self where - 'a: 'b, + F: SelectDagOp + 'a, { - match (match_cb, self) { - // matching the field - (Some(match_cb), _) => Callback::MatchDag { cb: match_cb }, - // - (None, Callback::SelectNode { cb, only_results }) => Callback::SelectNode { - cb: cb.clone(), - only_results: *only_results, - }, - // - (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, - _ => unreachable!(), + Self::SelectDag { cb: Box::new(func) } + } + + pub(crate) fn new_select_ref(func: F) -> Self + where + F: SelectDagRefOp + 'a, + { + Self::SelectRef { + // current, + cb: Box::new(func), } } + pub(crate) fn new_patch(func: F) -> Self + where + F: PatchDagOp + 'a, + { + Self::Patch { + // current, + cb: Box::new(func), + } + } + } + + impl<'a, C> Callback<'a, C> + where + C: Context, + // T: Representation, + { + // /// Return a callback that will be called on `U` returning `T` to be + // /// provided to the original callback. + // pub(crate) fn wrap(self, conv: F) -> Callback<'a, C, U> + // where + // C: 'a, + // U: Representation + 'static, + // T: 'static, + // // T: From + 'static, + // F: Fn(U) -> T + Clone + 'a, + // { + // match self { + // Self::SelectNode { + // only_matched: only_results, + // cb, + // } => Callback::SelectNode { + // only_matched: only_results, + // cb, + // }, + // Self::SelectDag { mut cb } => { + // let cb = Box::new(move |selection: DagSelection, ctx: &mut C| { + // let inner_dag = selection.dag.downcast::()?; + // let dag = conv(inner_dag).into(); + // cb(DagSelection { dag, ..selection }, ctx) + // }); + // Callback::SelectDag { cb } + // } + // // todo? + // // Self::SelectRef { mut cb } => { + // // let cb = Box::new(move |selection: DagSelection, ctx: &mut C| { + // // let inner_dag = selection.dag.downcast::()?; + // // let dag = conv(inner_dag).into(); + // // cb(DagSelection { dag, ..selection }, ctx) + // // }); + // // Callback::SelectDag { cb } + // // } + // // Self::MatchDag { mut cb } => { + // // let cb = Box::new(move |dag: U, ctx: &mut C| cb(conv(dag), ctx)); + // // Callback::MatchDag { cb } + // // } + // _ => unimplemented!(), + // } + // } + + // // TODO: implement a clone method, delegate to that in some branches + // pub(crate) fn transmute_select<'b, U>( + // &'b mut self, + // match_cb: Option + 'b>>, + // ) -> Callback<'b, C, U> + // where + // 'a: 'b, + // { + // match (match_cb, self) { + // // matching the field + // // (Some(match_cb), _) => Callback::MatchDag { cb: match_cb }, + // // + // ( + // None, + // Callback::SelectNode { + // only_matched: only_results, + // cb, + // }, + // ) => Callback::SelectNode { + // only_matched: *only_results, + // cb: cb.clone(), + // }, + // // + // (None, Callback::SelectDag { cb }) => Callback::SelectDag { cb: cb.clone() }, + // _ => unreachable!(), + // } + // } + /* // #[inline] // pub(crate) fn select_node(&self, node: SelectedNode) -> Result<(), Error> { @@ -473,6 +586,18 @@ mod callbacks { // } */ + // pub fn as_mut(&mut self) -> Callback<'_, &mut C> { + // match self { + // Self::SelectNode { only_matched, cb } => Callback::SelectNode { + // only_matched: *only_matched, + // cb: cb.clone(), + // }, + // Self::SelectDag { cb } => Callback::SelectDag { cb: cb.clone() }, + // Self::SelectRef { cb } => Callback::SelectRef { cb: cb.clone() }, + // Self::Patch { cb } => Callback::Patch { cb: cb.clone() }, + // } + // } + pub(crate) fn cover_node( &mut self, path: &Path, @@ -480,14 +605,14 @@ mod callbacks { ctx: &mut C, ) -> Result<(), Error> { match self { - Self::SelectNode { cb, only_results } if !*only_results => { + Self::SelectNode { only_matched, cb } if !*only_matched => { cb(NodeSelection::covered(path, selected_node), ctx) } _ => Ok(()), } } - pub(crate) fn select_node( + pub(crate) fn match_node( &mut self, path: &Path, selected_node: SelectedNode, @@ -502,14 +627,42 @@ mod callbacks { } } - pub(crate) fn select_dag(&mut self, dag: D, ctx: &mut C) -> Result<(), Error> - where - D: Into, - { + pub(crate) fn match_dag( + &mut self, + path: &Path, + dag: T, + label: Option<&str>, + ctx: &mut C, + ) -> Result<(), Error> { + match self { + Self::SelectDag { cb } => cb(DagSelection::new(path, dag, label), ctx), + _ => Ok(()), + } + } + + pub(crate) fn match_ref( + &mut self, + path: &Path, + dag: &T, + label: Option<&str>, + ctx: &mut C, + ) -> Result<(), Error> { + match self { + Self::SelectRef { cb } => cb(DagRefSelection { path, dag, label }, ctx), + _ => Ok(()), + } + } + + pub(crate) fn patch_dag( + &mut self, + path: &Path, + dag: &mut T, + label: Option<&str>, + ctx: &mut C, + ) -> Result { match self { - Self::SelectDag { cb } => cb(dag.into(), ctx), - Self::SelectNode { .. } => Ok(()), - _ => unreachable!(), + Self::Patch { cb } => cb(DagRefMutSelection { path, dag, label }, ctx), + _ => Ok(false), } } @@ -584,7 +737,7 @@ where /// #[derive(AsRef, AsMut, Clone, Debug, Default)] #[doc(hidden)] -pub(crate) struct State { +pub struct State { // selector: Selector, // mode: SelectionMode, pub(crate) current_block: Cid, @@ -597,7 +750,7 @@ pub(crate) struct State { pub(crate) max_path_depth: Option, pub(crate) max_link_depth: Option, // sender: Option, - // params: SelectionParams<'a, C, T, U>, + // params: SelectionParams<'a, C, U>, } // impl<'a> SelectorState<'a> { diff --git a/tests/codec-fixtures.rs b/tests/codec-fixtures.rs index d699147..6213d0e 100644 --- a/tests/codec-fixtures.rs +++ b/tests/codec-fixtures.rs @@ -1,5 +1,5 @@ use ipld::dev::MemoryContext; -use ipld::prelude::*; +use ipld::*; use std::{ env, fs::{self, DirEntry}, @@ -217,7 +217,7 @@ impl Fixture { /// Sets up a `MemoryContext` to provide the fixture's block. fn setup_ctx(&self) -> MemoryContext { const DEFAULT_CID_VERSION: Version = Version::V1; - const DEFAULT_MH: u64 = Multihash::SHA2_256; + const DEFAULT_MH: u64 = Multihasher::SHA2_256; let mut ctx = MemoryContext::default(); let cid = ctx @@ -241,7 +241,7 @@ impl Fixture { FixtureType::Int => self.run_for::(), // FixtureType::Float => self.run_for::(), // floats arent round-tripping with dag-cbor correctly... // FixtureType::Bytes => self.run_for::(), // none of the fixtures match the multibase... - FixtureType::String => self.run_for::(), + FixtureType::String => self.run_for::(), // FixtureType::Array => self.run_for::>(), // FixtureType::Map => self.run_for::>(), // FixtureType::Cid => self.run_for::>(), @@ -268,7 +268,7 @@ impl Fixture { .expect(&self.format_err::("should not fail to encode dag")); let new_cid = self .cid - .derive_new(block.as_slice()) + .derive_from_reader(block.as_slice()) .expect(&"should not fail to generate a Cid for a block of bytes"); if self.codec.name() == "dag-json" { @@ -301,8 +301,8 @@ impl Fixture { { // next, decode the concrete type using the Matcher selector let mut ctx = self.setup_ctx(); - let matched_dag: T = Params::<'_, _, T>::new_select(self.cid) - .into_dag_iter(&mut ctx) + let matched_dag: T = Params::<'_, _>::new(&Selector::DEFAULT) + .select_in::(self.cid, &mut ctx) .expect(&self.format_err::("should not fail selection")) .next() .expect("should produce at least one dag") @@ -316,7 +316,7 @@ impl Fixture { .expect(&self.format_err::("should not fail to encode dag")); let new_cid = self .cid - .derive_new(block.as_slice()) + .derive_from_reader(block.as_slice()) .expect(&"should not fail to generate a Cid for a block of bytes"); if self.codec.name() == "dag-json" {