Procházet zdrojové kódy

util/derive/serial: WIP add support for enum

ghassmo před 4 roky
rodič
revize
43f1d14077

+ 2 - 0
example/serial_derive/.gitignore

@@ -0,0 +1,2 @@
+target/*
+Cargo.lock

+ 11 - 0
example/serial_derive/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "serial_derive"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+darkfi = {path = "../../", features = ["util"]}
+
+[workspace]

+ 14 - 0
example/serial_derive/src/main.rs

@@ -0,0 +1,14 @@
+use darkfi::util::serial::{
+    serialize, Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt,
+};
+
+#[derive(SerialEncodable)]
+enum Test {
+    Type1(u32),
+    Type2,
+    Type3,
+}
+
+fn main() {
+    println!("Hello, world!");
+}

+ 39 - 1
src/util/derive-internal/src/lib.rs

@@ -1,7 +1,44 @@
 //! Derive (de)serialization for structs, see src/util/derive
 //! Derive (de)serialization for structs, see src/util/derive
 use proc_macro2::{Span, TokenStream as TokenStream2};
 use proc_macro2::{Span, TokenStream as TokenStream2};
 use quote::quote;
 use quote::quote;
-use syn::{Fields, Ident, Index, ItemStruct, WhereClause};
+use syn::{Fields, Ident, Index, ItemEnum, ItemStruct, WhereClause};
+
+pub fn enum_ser(input: &ItemEnum, cratename: Ident) -> syn::Result<TokenStream2> {
+    let name = &input.ident;
+    let (_impl_generics, _ty_generics, where_clause) = input.generics.split_for_impl();
+    let mut where_clause = where_clause.map_or_else(
+        || WhereClause { where_token: Default::default(), predicates: Default::default() },
+        Clone::clone,
+    );
+
+    let mut body = TokenStream2::new();
+
+    let ln = quote! {
+        let mut len = 0;
+    };
+    body.extend(ln);
+
+    for var in input.variants.iter() {
+        match &var.fields {
+            Fields::Named(_) => {}
+            Fields::Unnamed(_) => {}
+            Fields::Unit => {}
+        }
+    }
+
+    let ret = quote! {
+        Ok(len)
+    };
+    body.extend(ret);
+
+    Ok(quote! {
+        impl #cratename::util::serial::Encodable for #name #where_clause {
+            fn encode<S: std::io::Write>(&self, mut s: S) -> #cratename::Result<usize> {
+                #body
+            }
+        }
+    })
+}
 
 
 pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStream2> {
 pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStream2> {
     let name = &input.ident;
     let name = &input.ident;
@@ -12,6 +49,7 @@ pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStre
     );
     );
 
 
     let mut body = TokenStream2::new();
     let mut body = TokenStream2::new();
+
     match &input.fields {
     match &input.fields {
         Fields::Named(fields) => {
         Fields::Named(fields) => {
             let ln = quote! {
             let ln = quote! {

+ 6 - 7
src/util/derive/src/lib.rs

@@ -2,9 +2,9 @@ extern crate proc_macro;
 use proc_macro::TokenStream;
 use proc_macro::TokenStream;
 use proc_macro2::Span;
 use proc_macro2::Span;
 use proc_macro_crate::{crate_name, FoundCrate};
 use proc_macro_crate::{crate_name, FoundCrate};
-use syn::{Ident, ItemStruct};
+use syn::{Ident, Item, ItemStruct};
 
 
-use darkfi_derive_internal::{struct_de, struct_ser};
+use darkfi_derive_internal::{enum_ser, struct_de, struct_ser};
 
 
 #[proc_macro_derive(SerialEncodable, attributes(skip_serialize))]
 #[proc_macro_derive(SerialEncodable, attributes(skip_serialize))]
 pub fn darkfi_serialize(input: TokenStream) -> TokenStream {
 pub fn darkfi_serialize(input: TokenStream) -> TokenStream {
@@ -17,11 +17,10 @@ pub fn darkfi_serialize(input: TokenStream) -> TokenStream {
 
 
     let cratename = Ident::new(&found_crate, Span::call_site());
     let cratename = Ident::new(&found_crate, Span::call_site());
 
 
-    let res = if let Ok(input) = syn::parse::<ItemStruct>(input) {
-        struct_ser(&input, cratename)
-    } else {
-        // For now we only allow derive on structs
-        todo!("Implement Enum and Union")
+    let res = match syn::parse(input).unwrap() {
+        Item::Struct(strc) => struct_ser(&strc, cratename),
+        Item::Enum(enu) => enum_ser(&enu, cratename),
+        _ => todo!("Not implemented type"),
     };
     };
 
 
     TokenStream::from(match res {
     TokenStream::from(match res {