From b88b0eddd3d870fa6a2b44313d18d061abeaa53d Mon Sep 17 00:00:00 2001 From: nickray Date: Sat, 20 Feb 2021 00:53:06 +0000 Subject: [PATCH] deploy: 003068534e96af2ac866a956a01f31cece2c33ed --- flexiber_derive/index.html | 2 +- src/flexiber_derive/decodable.rs.html | 174 +++++++++++++++++------ src/flexiber_derive/encodable.rs.html | 128 +++++++++++++---- src/flexiber_derive/lib.rs.html | 190 ++++++++++++++++++++++++-- 4 files changed, 411 insertions(+), 83 deletions(-) diff --git a/flexiber_derive/index.html b/flexiber_derive/index.html index 1fc0efa..592c68e 100644 --- a/flexiber_derive/index.html +++ b/flexiber_derive/index.html @@ -1,7 +1,7 @@ flexiber_derive - Rust

[][src]Crate flexiber_derive

Custom derive support for the flexiber crate

+ Change settings

[][src]Crate flexiber_derive

Custom derive support for the flexiber crate

With #[tlv(slice)] set, Encodable should work for fields implementing AsRef<[u8]>, and Decodable should work for fields implementing TryFrom<[u8]>, even if the field is not Decodable or Encodable.

diff --git a/src/flexiber_derive/decodable.rs.html b/src/flexiber_derive/decodable.rs.html index 5e7147f..9316809 100644 --- a/src/flexiber_derive/decodable.rs.html +++ b/src/flexiber_derive/decodable.rs.html @@ -123,6 +123,51 @@ 120 121 122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167
 use proc_macro2::TokenStream;
 use quote::{quote, ToTokens};
@@ -168,30 +213,48 @@
         let field_name = &field.name;
         let tag = field.tag;
 
-        let class = tag.class as u8;
-        let constructed = tag.constructed;
-        let tag_number = tag.number;
+        let field_decoder = match tag {
+            Tag::Ber(tag) => {
+                let class = tag.class as u8;
+                let constructed = tag.constructed;
+                let tag_number = tag.number;
 
-        let field_decoder = if field.slice {
-            quote! {
-                let tag = ::flexiber::Tag::from(
-                    flexiber::Class::try_from(#class).unwrap(),
-                    #constructed,
-                    #tag_number
-                );
-                let #field_name =
-                    decoder.decode_tagged_slice(tag)?.try_into().unwrap();
-                        // .map_err(|_| flexiber::ErrorKind::Length { tag })?;
+                if field.slice {
+                    quote! {
+                        let tag = ::flexiber::Tag::from(
+                            flexiber::Class::try_from(#class).unwrap(),
+                            #constructed,
+                            #tag_number
+                        );
+                        let #field_name =
+                            decoder.decode_tagged_slice(tag)?.try_into().unwrap();
+                                // .map_err(|_| flexiber::ErrorKind::Length { tag })?;
+                    }
+                } else {
+                    quote! {
+                        let tag = ::flexiber::Tag::from(
+                            flexiber::Class::try_from(#class).unwrap(),
+                            #constructed,
+                            #tag_number
+                        );
+
+                        let #field_name = decoder.decode_tagged_value(tag)?;
+                    }
+                }
             }
-        } else {
-            quote! {
-                let tag = ::flexiber::Tag::from(
-                    flexiber::Class::try_from(#class).unwrap(),
-                    #constructed,
-                    #tag_number
-                );
-
-                let #field_name = decoder.decode_tagged_value(tag)?;
+            Tag::Simple(tag) => {
+                let field_tag = tag.0;
+                if field.slice {
+                    quote! { let #field_name =
+                        decoder.decode_tagged_slice(::flexiber::SimpleTag::try_from(#field_tag).unwrap())?.try_into()
+                            .map_err(|_| {
+                                use flexiber::TagLike;
+                                flexiber::ErrorKind::Length { tag: flexiber::SimpleTag::try_from(#field_tag).unwrap().embedding() }
+                            })?;
+                    }
+                } else {
+                    quote! { let #field_name = decoder.decode_tagged_value(::flexiber::SimpleTag::try_from(#field_tag).unwrap())?; }
+                }
             }
         };
         field_decoder.to_tokens(&mut self.decode_fields);
@@ -208,30 +271,57 @@
 
         if let Some(tag) = tag {
 
-            let class = tag.class as u8;
-            let constructed = tag.constructed;
-            let tag_number = tag.number;
+            match tag {
+                Tag::Ber(tag) => {
+                    let class = tag.class as u8;
+                    let constructed = tag.constructed;
+                    let tag_number = tag.number;
 
-            s.gen_impl(quote! {
-                gen impl<'a> core::convert::TryFrom<flexiber::TaggedSlice<'a>> for @Self {
-                    type Error = flexiber::Error;
+                    s.gen_impl(quote! {
+                        gen impl<'a> core::convert::TryFrom<flexiber::TaggedSlice<'a>> for @Self {
+                            type Error = flexiber::Error;
 
-                    fn try_from(tagged_slice: flexiber::TaggedSlice<'a>) -> flexiber::Result<Self> {
-                        use core::convert::TryInto;
-                        let tag = ::flexiber::Tag::from(
-                            flexiber::Class::try_from(#class).unwrap(),
-                            #constructed,
-                            #tag_number
-                        );
-                        tagged_slice.tag().assert_eq(tag)?;
-                        tagged_slice.decode_nested(|decoder| {
-                            #decode_fields
+                            fn try_from(tagged_slice: flexiber::TaggedSlice<'a>) -> flexiber::Result<Self> {
+                                use core::convert::TryInto;
+                                use flexiber::TagLike;
+                                let tag = ::flexiber::Tag::from(
+                                    flexiber::Class::try_from(#class).unwrap(),
+                                    #constructed,
+                                    #tag_number
+                                );
+                                tagged_slice.tag().assert_eq(tag)?;
+                                tagged_slice.decode_nested(|decoder| {
+                                    #decode_fields
 
-                            Ok(Self { #decode_result })
-                        })
-                    }
+                                    Ok(Self { #decode_result })
+                                })
+                            }
+                        }
+                    })
                 }
-            })
+                Tag::Simple(tag) => {
+                    let tag = tag.0;
+                    s.gen_impl(quote! {
+                        gen impl<'a> Decodable<'a> for @Self {
+                            fn decode(decoder: &mut Decoder<'a>) -> Result<Self> {
+                                flexiber::TaggedSlice::<'a, flexiber::SimpleTag>::decode(decoder)
+                                    .and_then(|tagged_slice| {
+                                        use core::convert::TryInto;
+                                        use flexiber::TagLike;
+                                        tagged_slice.tag().assert_eq(flexiber::SimpleTag::try_from(#tag).unwrap())?;
+                                        tagged_slice.decode_nested(|decoder| {
+                                            #decode_fields
+
+                                            Ok(Self { #decode_result })
+                                        })
+                                    })
+                                    .or_else(|e| decoder.error(e.kind()))
+                            }
+
+                        }
+                    })
+                }
+            }
         } else {
             s.gen_impl(quote! {
                 gen impl<'a> flexiber::Decodable<'a> for @Self {
diff --git a/src/flexiber_derive/encodable.rs.html b/src/flexiber_derive/encodable.rs.html
index cbf009d..acaf72d 100644
--- a/src/flexiber_derive/encodable.rs.html
+++ b/src/flexiber_derive/encodable.rs.html
@@ -111,6 +111,43 @@
 108
 109
 110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
 
 use proc_macro2::TokenStream;
 use quote::{quote, ToTokens};
@@ -152,14 +189,26 @@
         let field_name = &field.name;
         let tag = field.tag;
 
-        let class = tag.class as u8;
-        let constructed = tag.constructed;
-        let tag_number = tag.number;
+        let field_encoder = match tag {
+            Tag::Ber(tag) => {
+                let class = tag.class as u8;
+                let constructed = tag.constructed;
+                let tag_number = tag.number;
 
-        let field_encoder = if field.slice {
-            quote! { &(::flexiber::TaggedSlice::from(flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number), &self.#field_name)?), }
-        } else {
-            quote! { &(::flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number).with_value(&self.#field_name)), }
+                if field.slice {
+                    quote! { &(::flexiber::TaggedSlice::from(flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number), &self.#field_name)?), }
+                } else {
+                    quote! { &(::flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number).with_value(&self.#field_name)), }
+                }
+            }
+            Tag::Simple(tag) => {
+                let field_tag = tag.0;
+                if field.slice {
+                    quote! { &(::flexiber::TaggedSlice::from(flexiber::SimpleTag::try_from(#field_tag).unwrap(), &self.#field_name)?), }
+                } else {
+                    quote! { &(::flexiber::SimpleTag::try_from(#field_tag).unwrap().with_value(&self.#field_name)), }
+                }
+            }
         };
         field_encoder.to_tokens(&mut self.encode_fields);
     }
@@ -171,28 +220,53 @@
         let encode_fields = self.encode_fields;
 
         if let Some(tag) = tag {
-            let class = tag.class as u8;
-            let constructed = tag.constructed;
-            let tag_number = tag.number;
-            s.gen_impl(quote! {
-                gen impl flexiber::Tagged for @Self {
-                    fn tag() -> flexiber::Tag {
-                        // TODO(nickray): FIXME FIXME
-                        use core::convert::TryFrom;
-                        flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number)
-                    }
-                }
+            match tag {
+                Tag::Ber(tag) => {
+                    let class = tag.class as u8;
+                    let constructed = tag.constructed;
+                    let tag_number = tag.number;
+                    s.gen_impl(quote! {
+                        gen impl flexiber::Tagged for @Self {
+                            fn tag() -> flexiber::Tag {
+                                // TODO(nickray): FIXME FIXME
+                                use core::convert::TryFrom;
+                                flexiber::Tag::from(flexiber::Class::try_from(#class).unwrap(), #constructed, #tag_number)
+                            }
+                        }
 
-                gen impl flexiber::Container for @Self {
-                    fn fields<F, T>(&self, field_encoder: F) -> flexiber::Result<T>
-                    where
-                        F: FnOnce(&[&dyn flexiber::Encodable]) -> flexiber::Result<T>,
-                    {
-                        use core::convert::TryFrom;
-                        field_encoder(&[#encode_fields])
-                    }
+                        gen impl flexiber::Container for @Self {
+                            fn fields<F, T>(&self, field_encoder: F) -> flexiber::Result<T>
+                            where
+                                F: FnOnce(&[&dyn flexiber::Encodable]) -> flexiber::Result<T>,
+                            {
+                                use core::convert::TryFrom;
+                                field_encoder(&[#encode_fields])
+                            }
+                        }
+                    })
                 }
-            })
+                Tag::Simple(tag) => {
+                    let tag = tag.0;
+                    s.gen_impl(quote! {
+                        gen impl flexiber::Tagged for @Self {
+                            fn tag() -> flexiber::Tag {
+                                use core::convert::TryFrom;
+                                flexiber::Tag::try_from(#tag).unwrap()
+                            }
+                        }
+
+                        gen impl flexiber::Container for @Self {
+                            fn fields<F, T>(&self, field_encoder: F) -> flexiber::Result<T>
+                            where
+                                F: FnOnce(&[&dyn flexiber::Encodable]) -> flexiber::Result<T>,
+                            {
+                                use core::convert::TryFrom;
+                                field_encoder(&[#encode_fields])
+                            }
+                        }
+                    })
+                }
+            }
         } else {
             s.gen_impl(quote! {
                 gen impl flexiber::Container for @Self {
diff --git a/src/flexiber_derive/lib.rs.html b/src/flexiber_derive/lib.rs.html
index bddd601..84c4def 100644
--- a/src/flexiber_derive/lib.rs.html
+++ b/src/flexiber_derive/lib.rs.html
@@ -199,6 +199,88 @@
 196
 197
 198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
 
 //! Custom derive support for the `flexiber` crate
 //!
@@ -270,12 +352,39 @@
 }
 
 #[derive(Clone, Copy, Debug, Default)]
-struct Tag {
+struct BerTag {
     class: Class,
     constructed: bool,
     number: u16,
 }
 
+#[derive(Clone, Copy, Debug, Default)]
+struct SimpleTag(u8);
+
+#[derive(Clone, Copy, Debug)]
+enum Tag {
+    Ber(BerTag),
+    Simple(SimpleTag),
+}
+
+impl From<BerTag> for Tag {
+    fn from(tag: BerTag) -> Self {
+        Self::Ber(tag)
+    }
+}
+
+impl From<SimpleTag> for Tag {
+    fn from(tag: SimpleTag) -> Self {
+        Self::Simple(tag)
+    }
+}
+
+impl Default for Tag {
+    fn default() -> Self {
+        Self::Ber(BerTag::default())
+    }
+}
+
 #[derive(Clone, Copy, Debug)]
 #[repr(u8)]
 enum Class {
@@ -337,17 +446,53 @@
                             if path.is_ident("slice") {
                                 slice = true;
                             } else if path.is_ident("universal") {
-                                tag.class = Class::Universal;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.class = Class::Universal;
+                                    tag.into()
+                                };
                             } else if path.is_ident("application") {
-                                tag.class = Class::Application;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.class = Class::Application;
+                                    tag.into()
+                                };
                             } else if path.is_ident("context") {
-                                tag.class = Class::Context;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.class = Class::Context;
+                                    tag.into()
+                                };
                             } else if path.is_ident("private") {
-                                tag.class = Class::Private;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.class = Class::Private;
+                                    tag.into()
+                                };
                             } else if path.is_ident("constructed") {
-                                tag.constructed = true;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.constructed = true;
+                                    tag.into()
+                                };
                             } else if path.is_ident("primitive") {
-                                tag.constructed = false;
+                                tag = {
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.constructed = false;
+                                    tag.into()
+                                };
                             } else {
                                 panic!("unknown `tlv` attribute for field `{}`: {:?}", name, path);
                             }
@@ -358,15 +503,34 @@
                             ..
                         })) => {
                             // Parse the `type = "..."` attribute
-                            if !path.is_ident("number") {
+                            if path.is_ident("number") {
+                                tag = {
+                                    let possibly_with_prefix = lit_str.value();
+                                    let without_prefix = possibly_with_prefix.trim_start_matches("0x");
+                                    let tag_number = u16::from_str_radix(without_prefix, 16).expect("tag values must be between one and 254");
+                                    let mut tag = if let Tag::Ber(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.number = tag_number;
+                                    tag_number_is_set = true;
+                                    tag.into()
+                                }
+                            } else if path.is_ident("simple") {
+                                tag = {
+                                    let possibly_with_prefix = lit_str.value();
+                                    let without_prefix = possibly_with_prefix.trim_start_matches("0x");
+                                    let tag_number = u8::from_str_radix(without_prefix, 16).expect("tag values must be between one and 254");
+                                    let mut tag = if let Tag::Simple(tag) = tag {
+                                        tag
+                                    } else { Default::default() };
+                                    tag.0 = tag_number;
+                                    tag_number_is_set = true;
+                                    tag.into()
+                                };
+                            } else {
                                 panic!("unknown `tlv` attribute for field `{}`: {:?}", name, path);
                             }
 
-                            let possibly_with_prefix = lit_str.value();
-                            let without_prefix = possibly_with_prefix.trim_start_matches("0x");
-                            let tag_number = u16::from_str_radix(without_prefix, 16).expect("tag values must be between one and 254");
-                            tag.number = tag_number;
-                            tag_number_is_set = true;
                         }
                         other => panic!(
                             "a malformed `tlv` attribute for field `{}`: {:?}",