Skip to content

Commit 754e39b

Browse files
committed
WIP
Signed-off-by: Toralf Wittner <[email protected]>
1 parent 7e102c5 commit 754e39b

File tree

7 files changed

+93
-25
lines changed

7 files changed

+93
-25
lines changed

minicbor-derive/src/attrs.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub use encoding::Encoding;
1919
pub use idx::Idx;
2020

2121
use crate::attrs::codec::{Decode, Encode};
22+
use crate::{is_decode_bound, is_encode_bound, is_length_bound};
2223

2324
/// Recognised attributes.
2425
#[derive(Debug, Clone)]
@@ -311,8 +312,32 @@ impl Attributes {
311312
} else if meta.path.is_ident("bound") {
312313
let s: LitStr = meta.value()?.parse()?;
313314
let t: syn::TypeParam = s.parse()?;
314-
let m = iter::once((t.ident.clone(), t)).collect::<HashMap<_, _>>();
315-
let b = TypeParams::All { encode: m.clone(), length: m.clone(), decode: m };
315+
let b = TypeParams::All {
316+
encode: {
317+
let mut e = t.clone();
318+
e.bounds = e.bounds
319+
.into_iter()
320+
.filter(|b| !(is_decode_bound(b) || is_length_bound(b)))
321+
.collect();
322+
HashMap::from_iter([(e.ident.clone(), e)])
323+
},
324+
length: {
325+
let mut e = t.clone();
326+
e.bounds = e.bounds
327+
.into_iter()
328+
.filter(|b| !(is_encode_bound(b) || is_decode_bound(b)))
329+
.collect();
330+
HashMap::from_iter([(e.ident.clone(), e)])
331+
},
332+
decode: {
333+
let mut d = t;
334+
d.bounds = d.bounds
335+
.into_iter()
336+
.filter(|b| !(is_encode_bound(b) || is_length_bound(b)))
337+
.collect();
338+
HashMap::from_iter([(d.ident.clone(), d)])
339+
}
340+
};
316341
attrs.try_insert(Kind::TypeParam, Value::TypeParam(b, meta.path.span()))?
317342
} else if meta.path.is_ident("context_bound") {
318343
let s: LitStr = meta.value()?.parse()?;

minicbor-derive/src/attrs/codec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl CustomCodec {
166166
CustomCodec::Encode(e) => e.require_bound,
167167
CustomCodec::Decode(_) => true,
168168
CustomCodec::Both(e, _) => e.require_bound,
169-
CustomCodec::Module(..) => true
169+
CustomCodec::Module(..) => false
170170
}
171171
}
172172

@@ -175,7 +175,7 @@ impl CustomCodec {
175175
CustomCodec::Encode(_) => true,
176176
CustomCodec::Decode(d) => d.require_bound,
177177
CustomCodec::Both(_, d) => d.require_bound,
178-
CustomCodec::Module(..) => true
178+
CustomCodec::Module(..) => false
179179
}
180180
}
181181
}

minicbor-derive/src/blacklist.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl Blacklist {
1818
/// - Type parameters of fields with a custom encode, decode or cbor_len function.
1919
/// - Fields that are skipped over.
2020
/// - Fields with a `PhantomData` type.
21-
pub(crate) fn new(mode: Mode, fields: &Fields, g: &syn::Generics) -> Self {
21+
pub(crate) fn full(mode: Mode, fields: &Fields, g: &syn::Generics) -> Self {
2222
Self::empty()
2323
.with_mode(mode, fields, g)
2424
.with_skipped(fields, g)
@@ -85,8 +85,8 @@ impl Blacklist {
8585
///
8686
/// Any types in negative position, i.e. blacklisted in the given fields
8787
/// argument will be add to the blacklist.
88-
pub(crate) fn merge(&mut self, f: &Fields, g: &syn::Generics, b: Self) -> &mut Self {
89-
for t in collect_type_params(g, f.fields()).difference(&b) {
88+
pub(crate) fn merge(&mut self, f: &Fields, g: &syn::Generics, b: Blacklist) -> &mut Self {
89+
for t in collect_type_params(g, f.fields().chain(f.skipped())).difference(&b) {
9090
self.0.remove(t);
9191
}
9292
for t in b.0 {

minicbor-derive/src/cbor_len.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn on_struct(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream
3636
let attrs = Attributes::try_from_iter(Level::Struct, inp.attrs.iter())?;
3737
let fields = Fields::try_from(name.span(), data.fields.iter(), &[&attrs])?;
3838

39-
let blacklist = Blacklist::new(Mode::Length, &fields, &inp.generics);
39+
let blacklist = Blacklist::full(Mode::Length, &fields, &inp.generics);
4040
let cbor_len_bound = gen_cbor_len_bound()?;
4141
let params = inp.generics.type_params_mut();
4242
add_bound_to_type_params(Mode::Length, cbor_len_bound, params, &blacklist, fields.fields().attributes());
@@ -46,7 +46,7 @@ fn on_struct(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream
4646
let params = inp.generics.type_params_mut();
4747
add_bound_to_type_params(Mode::Length, encode_bound, params, &blacklist, fields.fields().attributes());
4848

49-
let generics = add_typeparam(&inp.generics, gen_ctx_param()?, attrs.context_bound());
49+
let generics = add_typeparam(&inp.generics, gen_ctx_param(), attrs.context_bound());
5050
let impl_generics = generics.split_for_impl().0;
5151
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();
5252

@@ -96,7 +96,7 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
9696
let mut rows = Vec::new();
9797
for ((var, idx), attrs) in data.variants.iter().zip(variants.indices.iter()).zip(&variants.attrs) {
9898
let fields = Fields::try_from(var.ident.span(), var.fields.iter(), &[attrs, &enum_attrs])?;
99-
blacklist_len.merge(&fields, &inp.generics, Blacklist::new(Mode::Length, &fields, &inp.generics));
99+
blacklist_len.merge(&fields, &inp.generics, Blacklist::full(Mode::Length, &fields, &inp.generics));
100100
blacklist_enc.add(HashSet::from(blacklist_is_nil_params(&inp.generics, &fields)));
101101
let con = &var.ident;
102102
let encoding = attrs.encoding().unwrap_or(enum_encoding);
@@ -164,7 +164,7 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
164164
let params = inp.generics.type_params_mut();
165165
add_bound_to_type_params(Mode::Length, encode_bound, params, &blacklist_enc, &field_attrs);
166166

167-
let generics = add_typeparam(&inp.generics, gen_ctx_param()?, enum_attrs.context_bound());
167+
let generics = add_typeparam(&inp.generics, gen_ctx_param(), enum_attrs.context_bound());
168168
let impl_generics = generics.split_for_impl().0;
169169
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();
170170

minicbor-derive/src/decode.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn on_struct(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream
4646
}
4747
}
4848

49-
let blacklist = Blacklist::new(Mode::Decode, &fields, &inp.generics);
49+
let blacklist = Blacklist::full(Mode::Decode, &fields, &inp.generics);
5050
let bound = gen_decode_bound();
5151
let params = inp.generics.type_params_mut();
5252
add_bound_to_type_params(Mode::Decode, bound, params, &blacklist, fields.fields().attributes());
@@ -70,7 +70,7 @@ fn on_struct(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream
7070
);
7171

7272
let generics = add_lifetime(&inp.generics, lifetime);
73-
let generics = add_typeparam(&generics, gen_ctx_param()?, attrs.context_bound());
73+
let generics = add_typeparam(&generics, gen_ctx_param(), attrs.context_bound());
7474
let impl_generics = generics.split_for_impl().0;
7575

7676
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();
@@ -175,7 +175,7 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
175175
lifetime.bounds.push(l.clone())
176176
}
177177
}
178-
decode_blacklist.merge(&fields, &inp.generics, Blacklist::new(Mode::Decode, &fields, &inp.generics));
178+
decode_blacklist.merge(&fields, &inp.generics, Blacklist::full(Mode::Decode, &fields, &inp.generics));
179179
default_blacklist.merge(&fields, &inp.generics, Blacklist::empty()
180180
.with_mode(Mode::Decode, &fields, &inp.generics)
181181
.with_phantoms(&fields, &inp.generics));
@@ -240,7 +240,7 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
240240
);
241241

242242
let generics = add_lifetime(&inp.generics, lifetime);
243-
let generics = add_typeparam(&generics, gen_ctx_param()?, enum_attrs.context_bound());
243+
let generics = add_typeparam(&generics, gen_ctx_param(), enum_attrs.context_bound());
244244
let impl_generics = generics.split_for_impl().0;
245245

246246
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();

minicbor-derive/src/encode.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ fn on_struct(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream
3636
let attrs = Attributes::try_from_iter(Level::Struct, inp.attrs.iter())?;
3737
let encoding = attrs.encoding().unwrap_or_default();
3838
let fields = Fields::try_from(name.span(), data.fields.iter(), &[&attrs])?;
39-
let blacklist = Blacklist::new(Mode::Encode, &fields, &inp.generics);
39+
let blacklist = Blacklist::full(Mode::Encode, &fields, &inp.generics);
4040

41-
let bound = gen_encode_bound()?;
41+
let bound = gen_encode_bound();
4242
let params = inp.generics.type_params_mut();
4343
add_bound_to_type_params(Mode::Encode, bound, params, &blacklist, fields.fields().attributes());
4444

45-
let generics = add_typeparam(&inp.generics, gen_ctx_param()?, attrs.context_bound());
45+
let generics = add_typeparam(&inp.generics, gen_ctx_param(), attrs.context_bound());
4646
let impl_generics = generics.split_for_impl().0;
4747

4848
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();
@@ -96,7 +96,7 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
9696

9797
for ((var, idx), attrs) in data.variants.iter().zip(variants.indices.iter()).zip(&variants.attrs) {
9898
let fields = Fields::try_from(var.ident.span(), var.fields.iter(), &[attrs, &enum_attrs])?;
99-
blacklist.merge(&fields, &inp.generics, Blacklist::new(Mode::Encode, &fields, &inp.generics));
99+
blacklist.merge(&fields, &inp.generics, Blacklist::full(Mode::Encode, &fields, &inp.generics));
100100
let con = &var.ident;
101101
let encoding = attrs.encoding().unwrap_or(enum_encoding);
102102
let tag = encode_tag(attrs);
@@ -205,12 +205,12 @@ fn on_enum(inp: &mut syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
205205
}
206206

207207
{
208-
let bound = gen_encode_bound()?;
208+
let bound = gen_encode_bound();
209209
let params = inp.generics.type_params_mut();
210210
add_bound_to_type_params(Mode::Encode, bound, params, &blacklist, &field_attrs);
211211
}
212212

213-
let generics = add_typeparam(&inp.generics, gen_ctx_param()?, enum_attrs.context_bound());
213+
let generics = add_typeparam(&inp.generics, gen_ctx_param(), enum_attrs.context_bound());
214214
let impl_generics = generics.split_for_impl().0;
215215

216216
let (_, typ_generics, where_clause) = inp.generics.split_for_impl();
@@ -632,8 +632,8 @@ fn make_transparent_impl
632632
})
633633
}
634634

635-
fn gen_encode_bound() -> syn::Result<syn::TypeParamBound> {
636-
syn::parse_str("minicbor::Encode<Ctx>")
635+
fn gen_encode_bound() -> syn::TypeParamBound {
636+
syn::parse_quote!(minicbor::Encode<Ctx>)
637637
}
638638

639639
pub(crate) fn is_nil(ty: &syn::Type, codec: Option<&CustomCodec>) -> proc_macro2::TokenStream {

minicbor-derive/src/lib.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,49 @@ fn is_byte_slice(ty: &syn::Type) -> bool {
637637
}
638638
}
639639

640+
/// Does the given bound match `Encode<Ctx>`?
641+
fn is_encode_bound(bound: &syn::TypeParamBound) -> bool {
642+
if let syn::TypeParamBound::Trait(t) = bound
643+
&& let Some(s) = t.path.segments.last()
644+
&& s.ident == "Encode"
645+
&& let syn::PathArguments::AngleBracketed(b) = &s.arguments
646+
&& b.args.len() == 1
647+
&& let syn::GenericArgument::Type(syn::Type::Path(p)) = &b.args[0]
648+
{
649+
return p.path.is_ident("Ctx")
650+
}
651+
false
652+
}
653+
654+
/// Does the given bound match `CborLen<Ctx>`?
655+
fn is_length_bound(bound: &syn::TypeParamBound) -> bool {
656+
if let syn::TypeParamBound::Trait(t) = bound
657+
&& let Some(s) = t.path.segments.last()
658+
&& s.ident == "CborLen"
659+
&& let syn::PathArguments::AngleBracketed(b) = &s.arguments
660+
&& b.args.len() == 1
661+
&& let syn::GenericArgument::Type(syn::Type::Path(p)) = &b.args[0]
662+
{
663+
return p.path.is_ident("Ctx")
664+
}
665+
false
666+
}
667+
668+
/// Does the given bound match `Decode<'bytes, Ctx>`?
669+
fn is_decode_bound(bound: &syn::TypeParamBound) -> bool {
670+
if let syn::TypeParamBound::Trait(t) = bound
671+
&& let Some(s) = t.path.segments.last()
672+
&& s.ident == "Decode"
673+
&& let syn::PathArguments::AngleBracketed(b) = &s.arguments
674+
&& b.args.len() == 2
675+
&& let syn::GenericArgument::Lifetime(lt) = &b.args[0]
676+
&& let syn::GenericArgument::Type(syn::Type::Path(p)) = &b.args[1]
677+
{
678+
return lt.ident == "bytes" && p.path.is_ident("Ctx")
679+
}
680+
false
681+
}
682+
640683
/// Traverse all field types and collect all type parameters along the way.
641684
fn collect_type_params<'a, I>(all: &syn::Generics, fields: I) -> HashSet<syn::Ident>
642685
where
@@ -718,8 +761,8 @@ where
718761
g2
719762
}
720763

721-
fn gen_ctx_param() -> syn::Result<syn::TypeParam> {
722-
syn::parse_str("Ctx")
764+
fn gen_ctx_param() -> syn::TypeParam {
765+
syn::parse_quote!(Ctx)
723766
}
724767

725768
fn is_phantom_data(t: &syn::Type) -> bool {

0 commit comments

Comments
 (0)