Add generic bound support to derive

This commit is contained in:
Lena Hellström 2021-09-20 15:58:16 +02:00
parent f914b3e580
commit 8241e6c656
3 changed files with 25 additions and 10 deletions

View File

@ -1,15 +1,16 @@
use crate::Result; use crate::Result;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote; use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, Ident}; use syn::{spanned::Spanned, Generics, Ident};
pub struct DeriveStruct { pub struct DeriveStruct {
name: Ident, name: Ident,
generics: Generics,
fields: Vec<Ident>, fields: Vec<Ident>,
} }
impl DeriveStruct { impl DeriveStruct {
pub fn parse(name: Ident, str: syn::DataStruct) -> Result<Self> { pub fn parse(name: Ident, generics: Generics, str: syn::DataStruct) -> Result<Self> {
let fields = match str.fields { let fields = match str.fields {
syn::Fields::Named(fields) => fields syn::Fields::Named(fields) => fields
.named .named
@ -24,11 +25,21 @@ impl DeriveStruct {
.collect(), .collect(),
syn::Fields::Unit => Vec::new(), syn::Fields::Unit => Vec::new(),
}; };
Ok(Self { name, fields }) Ok(Self {
name,
generics,
fields,
})
} }
pub fn to_encodable(self) -> Result<TokenStream> { pub fn to_encodable(self) -> Result<TokenStream> {
let DeriveStruct { name, fields } = self; let DeriveStruct {
name,
generics,
fields,
} = self;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let fields = fields let fields = fields
.into_iter() .into_iter()
@ -40,7 +51,7 @@ impl DeriveStruct {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let result = quote! { let result = quote! {
impl bincode::enc::Encodeable for #name { impl #impl_generics bincode::enc::Encodeable for #name #ty_generics #where_clause {
fn encode<E: bincode::enc::Encode>(&self, mut encoder: E) -> Result<(), bincode::error::EncodeError> { fn encode<E: bincode::enc::Encode>(&self, mut encoder: E) -> Result<(), bincode::error::EncodeError> {
#(#fields)* #(#fields)*
Ok(()) Ok(())

View File

@ -21,7 +21,8 @@ pub fn derive_encodable(input: TokenStream) -> TokenStream {
fn derive_encodable_inner(input: DeriveInput) -> Result<TokenStream> { fn derive_encodable_inner(input: DeriveInput) -> Result<TokenStream> {
match input.data { match input.data {
syn::Data::Struct(struct_definition) => { syn::Data::Struct(struct_definition) => {
DeriveStruct::parse(input.ident, struct_definition).and_then(|str| str.to_encodable()) DeriveStruct::parse(input.ident, input.generics, struct_definition)
.and_then(|str| str.to_encodable())
} }
syn::Data::Enum(enum_definition) => { syn::Data::Enum(enum_definition) => {
DeriveEnum::parse(input.ident, enum_definition).and_then(|str| str.to_encodable()) DeriveEnum::parse(input.ident, enum_definition).and_then(|str| str.to_encodable())
@ -39,7 +40,8 @@ pub fn derive_decodable(input: TokenStream) -> TokenStream {
fn derive_decodable_inner(input: DeriveInput) -> Result<TokenStream> { fn derive_decodable_inner(input: DeriveInput) -> Result<TokenStream> {
match input.data { match input.data {
syn::Data::Struct(struct_definition) => { syn::Data::Struct(struct_definition) => {
DeriveStruct::parse(input.ident, struct_definition).and_then(|str| str.to_decodable()) DeriveStruct::parse(input.ident, input.generics, struct_definition)
.and_then(|str| str.to_decodable())
} }
syn::Data::Enum(enum_definition) => { syn::Data::Enum(enum_definition) => {
DeriveEnum::parse(input.ident, enum_definition).and_then(|str| str.to_decodable()) DeriveEnum::parse(input.ident, enum_definition).and_then(|str| str.to_decodable())

View File

@ -1,6 +1,8 @@
use bincode::enc::Encodeable;
#[derive(bincode::Encodable, PartialEq, Debug)] #[derive(bincode::Encodable, PartialEq, Debug)]
pub struct Test { pub struct Test<T: Encodeable> {
a: i32, a: T,
b: u32, b: u32,
c: u8, c: u8,
} }