فهرست منبع

util/serial: Implement derive macros also for unnamed fields.

parazyd 4 سال پیش
والد
کامیت
bf622aad39
2فایلهای تغییر یافته به همراه48 افزوده شده و 12 حذف شده
  1. 37 4
      src/util/derive-internal/src/lib.rs
  2. 11 8
      src/util/serial.rs

+ 37 - 4
src/util/derive-internal/src/lib.rs

@@ -1,7 +1,7 @@
 //! Derive (de)serialization for structs, see src/util/derive
-use proc_macro2::TokenStream as TokenStream2;
+use proc_macro2::{Span, TokenStream as TokenStream2};
 use quote::quote;
-use syn::{Fields, Ident, ItemStruct, WhereClause};
+use syn::{Fields, Ident, Index, ItemStruct, WhereClause};
 
 pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStream2> {
     let name = &input.ident;
@@ -42,7 +42,28 @@ pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStre
             };
             body.extend(ret)
         }
-        Fields::Unnamed(_fields) => todo!(),
+        Fields::Unnamed(fields) => {
+            let ln = quote! {
+                let mut len = 0;
+            };
+            body.extend(ln);
+
+            for field_idx in 0..fields.unnamed.len() {
+                let field_idx = Index {
+                    index: u32::try_from(field_idx).expect("up to 2^32 fields are supported"),
+                    span: Span::call_site(),
+                };
+                let delta = quote! {
+                    len += self.#field_idx.encode(&mut s)?;
+                };
+                body.extend(delta);
+            }
+
+            let ret = quote! {
+                Ok(len)
+            };
+            body.extend(ret)
+        }
         Fields::Unit => {}
     }
 
@@ -91,7 +112,19 @@ pub fn struct_de(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStrea
                 Self { #body }
             }
         }
-        Fields::Unnamed(_fields) => todo!(),
+        Fields::Unnamed(fields) => {
+            let mut body = TokenStream2::new();
+            for _ in 0..fields.unnamed.len() {
+                let delta = quote! {
+                    #cratename::util::serial::Decodable::decode(&mut d)?,
+                };
+                body.extend(delta);
+            }
+
+            quote! {
+                Self( #body )
+            }
+        }
         Fields::Unit => {
             quote! {
                 Self {}

+ 11 - 8
src/util/serial.rs

@@ -837,34 +837,37 @@ mod tests {
         );
     }
 
-    #[derive(Clone, SerialEncodable, SerialDecodable)]
+    #[derive(Debug, PartialEq, Clone, SerialEncodable, SerialDecodable)]
     struct TestDerive0 {
         foo: String,
         bar: u64,
     }
 
-    #[derive(Clone, SerialEncodable, SerialDecodable)]
+    #[derive(Debug, PartialEq, Clone, SerialEncodable, SerialDecodable)]
     struct TestDerive1 {
         baz: TestDerive0,
         meh: bool,
     }
 
+    #[derive(Debug, PartialEq, Clone, SerialEncodable, SerialDecodable)]
+    struct TestDerive2(u64);
+
     #[test]
     fn serialize_deserialize_struct() {
         let t0 = TestDerive0 { foo: String::from("Andrew"), bar: 42 };
-
         let t1 = TestDerive1 { baz: t0.clone(), meh: false };
+        let t2 = TestDerive2(u64::MAX);
 
         let t0_bytes = serialize(&t0);
         let t1_bytes = serialize(&t1);
+        let t2_bytes = serialize(&t2);
 
         let t0_de: TestDerive0 = deserialize(&t0_bytes).unwrap();
         let t1_de: TestDerive1 = deserialize(&t1_bytes).unwrap();
+        let t2_de: TestDerive2 = deserialize(&t2_bytes).unwrap();
 
-        assert_eq!(t0.foo, t0_de.foo);
-        assert_eq!(t0.bar, t0_de.bar);
-        assert_eq!(t0.foo, t1_de.baz.foo);
-        assert_eq!(t0.bar, t1_de.baz.bar);
-        assert_eq!(t1.meh, t1_de.meh);
+        assert_eq!(t0, t0_de);
+        assert_eq!(t1, t1_de);
+        assert_eq!(t2, t2_de);
     }
 }