util/derive/serial: WIP add support for enum

This commit is contained in:
ghassmo
2022-08-18 14:05:50 +04:00
parent 9fb4f8570e
commit 43f1d14077
5 changed files with 72 additions and 8 deletions

2
example/serial_derive/.gitignore vendored Normal file
View File

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

View File

@@ -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]

View File

@@ -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!");
}

View File

@@ -1,7 +1,44 @@
//! Derive (de)serialization for structs, see src/util/derive
use proc_macro2::{Span, TokenStream as TokenStream2};
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> {
let name = &input.ident;
@@ -12,6 +49,7 @@ pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result<TokenStre
);
let mut body = TokenStream2::new();
match &input.fields {
Fields::Named(fields) => {
let ln = quote! {

View File

@@ -2,9 +2,9 @@ extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::Span;
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))]
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 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 {