From 031d47903c87393d8f22dae92d7f650e125df5f2 Mon Sep 17 00:00:00 2001 From: jadebenn Date: Wed, 6 Aug 2025 21:46:22 -0500 Subject: [PATCH] run rustfmt on endio_derive --- endio_derive/Cargo.lock | 47 ++++++ endio_derive/src/deserialize.rs | 270 +++++++++++++++--------------- endio_derive/src/lib.rs | 122 +++++++------- endio_derive/src/serialize.rs | 281 +++++++++++++++++--------------- 4 files changed, 405 insertions(+), 315 deletions(-) create mode 100644 endio_derive/Cargo.lock diff --git a/endio_derive/Cargo.lock b/endio_derive/Cargo.lock new file mode 100644 index 0000000..d243888 --- /dev/null +++ b/endio_derive/Cargo.lock @@ -0,0 +1,47 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "endio_derive" +version = "0.3.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff --git a/endio_derive/src/deserialize.rs b/endio_derive/src/deserialize.rs index 2870645..768120a 100644 --- a/endio_derive/src/deserialize.rs +++ b/endio_derive/src/deserialize.rs @@ -1,158 +1,172 @@ use proc_macro2::{Ident, TokenStream}; use quote::quote; -use syn::{parse_macro_input, parse_quote, Data, DataEnum, DeriveInput, Fields, LitInt, WhereClause}; +use syn::{ + Data, DataEnum, DeriveInput, Fields, LitInt, WhereClause, parse_macro_input, parse_quote, +}; -use crate::{get_field_padding, get_pre_disc_padding, get_post_disc_padding, get_trailing_padding}; +use crate::{get_field_padding, get_post_disc_padding, get_pre_disc_padding, get_trailing_padding}; pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let mut input = parse_macro_input!(input as DeriveInput); - let where_generics = &mut input.generics.clone(); - let mut where_clause = where_generics.make_where_clause(); + let mut input = parse_macro_input!(input as DeriveInput); + let where_generics = &mut input.generics.clone(); + let mut where_clause = where_generics.make_where_clause(); - let name = &input.ident; + let name = &input.ident; - let deser_code = match &input.data { - Data::Struct(data) => { - add_where_clauses_fields(&mut where_clause, &data.fields); - gen_deser_code_struct(&data.fields) - } - Data::Enum(data) => { - let ty = crate::get_enum_type(&input); - add_where_clauses_enum(&mut where_clause, data, &ty); - let pre_disc_padding = get_pre_disc_padding(&input); - let post_disc_padding = get_post_disc_padding(&input); - gen_deser_code_enum(data, &name, &ty, &pre_disc_padding, &post_disc_padding) - } - Data::Union(_) => unimplemented!(), - }; + let deser_code = match &input.data { + Data::Struct(data) => { + add_where_clauses_fields(&mut where_clause, &data.fields); + gen_deser_code_struct(&data.fields) + } + Data::Enum(data) => { + let ty = crate::get_enum_type(&input); + add_where_clauses_enum(&mut where_clause, data, &ty); + let pre_disc_padding = get_pre_disc_padding(&input); + let post_disc_padding = get_post_disc_padding(&input); + gen_deser_code_enum(data, &name, &ty, &pre_disc_padding, &post_disc_padding) + } + Data::Union(_) => unimplemented!(), + }; - let trailing_padding = get_trailing_padding(&input); - let read_padding = gen_read_padding(&trailing_padding); + let trailing_padding = get_trailing_padding(&input); + let read_padding = gen_read_padding(&trailing_padding); - let (_, ty_generics, where_clause) = where_generics.split_for_impl(); + let (_, ty_generics, where_clause) = where_generics.split_for_impl(); - // todo[hygiene]: replace __ENDIO_ENDIANNESS, __ENDIO_READER with unique ident - input.generics.params.push(parse_quote!(__ENDIO_ENDIANNESS: ::endio::Endianness)); - input.generics.params.push(parse_quote!(__ENDIO_READER: ::std::io::Read + ::endio::ERead<__ENDIO_ENDIANNESS>)); - let (impl_generics, _, _) = input.generics.split_for_impl(); + // todo[hygiene]: replace __ENDIO_ENDIANNESS, __ENDIO_READER with unique ident + input + .generics + .params + .push(parse_quote!(__ENDIO_ENDIANNESS: ::endio::Endianness)); + input + .generics + .params + .push(parse_quote!(__ENDIO_READER: ::std::io::Read + ::endio::ERead<__ENDIO_ENDIANNESS>)); + let (impl_generics, _, _) = input.generics.split_for_impl(); - let expanded = quote! { - impl #impl_generics ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER> for #name #ty_generics #where_clause { - fn deserialize(reader: &mut __ENDIO_READER) -> ::std::io::Result { - #deser_code - #read_padding - Ok(ret) - } - } - }; + let expanded = quote! { + impl #impl_generics ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER> for #name #ty_generics #where_clause { + fn deserialize(reader: &mut __ENDIO_READER) -> ::std::io::Result { + #deser_code + #read_padding + Ok(ret) + } + } + }; - expanded.into() + expanded.into() } fn add_where_clauses_fields(where_clause: &mut WhereClause, fields: &Fields) { - match fields { - Fields::Named(fields) => { - for f in &fields.named { - let ty = &f.ty; - where_clause.predicates.push( - parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>) - ); - } - } - Fields::Unnamed(fields) => { - for f in &fields.unnamed { - let ty = &f.ty; - where_clause.predicates.push( - parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>) - ); - } - } - Fields::Unit => {} - } + match fields { + Fields::Named(fields) => { + for f in &fields.named { + let ty = &f.ty; + where_clause.predicates.push( + parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>), + ); + } + } + Fields::Unnamed(fields) => { + for f in &fields.unnamed { + let ty = &f.ty; + where_clause.predicates.push( + parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>), + ); + } + } + Fields::Unit => {} + } } fn gen_deser_code_fields(fields: &Fields) -> TokenStream { - match fields { - Fields::Named(fields) => { - let mut deser = vec![]; - for f in &fields.named { - let ident = &f.ident; - let padding = get_field_padding(f); - let read_padding = gen_read_padding(&padding); - deser.push(quote! { #ident: { - #read_padding - ::endio::ERead::read(reader)? - }, }); - } - quote! { { #(#deser)* } } - } - Fields::Unnamed(fields) => { - let mut deser = vec![]; - for f in &fields.unnamed { - let padding = get_field_padding(f); - let read_padding = gen_read_padding(&padding); - deser.push(quote! { { - #read_padding - ::endio::ERead::read(reader)? - }, }); - } - quote! { ( #(#deser)* ) } - } - Fields::Unit => { - quote! { } - } - } + match fields { + Fields::Named(fields) => { + let mut deser = vec![]; + for f in &fields.named { + let ident = &f.ident; + let padding = get_field_padding(f); + let read_padding = gen_read_padding(&padding); + deser.push(quote! { #ident: { + #read_padding + ::endio::ERead::read(reader)? + }, }); + } + quote! { { #(#deser)* } } + } + Fields::Unnamed(fields) => { + let mut deser = vec![]; + for f in &fields.unnamed { + let padding = get_field_padding(f); + let read_padding = gen_read_padding(&padding); + deser.push(quote! { { + #read_padding + ::endio::ERead::read(reader)? + }, }); + } + quote! { ( #(#deser)* ) } + } + Fields::Unit => { + quote! {} + } + } } fn gen_deser_code_struct(fields: &Fields) -> TokenStream { - let deser_code = gen_deser_code_fields(fields); - quote! { let ret = Self #deser_code; } + let deser_code = gen_deser_code_fields(fields); + quote! { let ret = Self #deser_code; } } fn add_where_clauses_enum(where_clause: &mut WhereClause, data: &DataEnum, ty: &Ident) { - where_clause.predicates.push( - parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>) - ); - for var in &data.variants { - add_where_clauses_fields(where_clause, &var.fields); - } + where_clause + .predicates + .push(parse_quote!(#ty: ::endio::Deserialize<__ENDIO_ENDIANNESS, __ENDIO_READER>)); + for var in &data.variants { + add_where_clauses_fields(where_clause, &var.fields); + } } -fn gen_deser_code_enum(data: &DataEnum, name: &Ident, ty: &Ident, pre_disc_padding: &Option, post_disc_padding: &Option) -> TokenStream { - let last_disc: syn::ExprLit = parse_quote! { 0 }; - let mut last_disc = &last_disc.into(); - let mut disc_offset = 0; - let mut arms = vec![]; - for f in &data.variants { - let ident = &f.ident; - if let Some((_, x)) = &f.discriminant { - last_disc = x; - disc_offset = 0; - } - let deser_fields = gen_deser_code_fields(&f.fields); - let arm = quote! { disc if disc == (#last_disc + (#disc_offset as #ty)) => Self::#ident #deser_fields, }; - disc_offset += 1; - arms.push(arm); - } - let read_pre_padding = gen_read_padding(pre_disc_padding); - let read_post_padding = gen_read_padding(post_disc_padding); - quote! { - #read_pre_padding - let disc: #ty = ::endio::ERead::read(reader)?; - #read_post_padding - let ret = match disc { - #(#arms)* - _ => return ::std::result::Result::Err(::std::io::Error::new(::std::io::ErrorKind::InvalidData, format!("invalid discriminant value for {}: {}", stringify!(#name), disc))) - }; - } +fn gen_deser_code_enum( + data: &DataEnum, + name: &Ident, + ty: &Ident, + pre_disc_padding: &Option, + post_disc_padding: &Option, +) -> TokenStream { + let last_disc: syn::ExprLit = parse_quote! { 0 }; + let mut last_disc = &last_disc.into(); + let mut disc_offset = 0; + let mut arms = vec![]; + for f in &data.variants { + let ident = &f.ident; + if let Some((_, x)) = &f.discriminant { + last_disc = x; + disc_offset = 0; + } + let deser_fields = gen_deser_code_fields(&f.fields); + let arm = quote! { disc if disc == (#last_disc + (#disc_offset as #ty)) => Self::#ident #deser_fields, }; + disc_offset += 1; + arms.push(arm); + } + let read_pre_padding = gen_read_padding(pre_disc_padding); + let read_post_padding = gen_read_padding(post_disc_padding); + quote! { + #read_pre_padding + let disc: #ty = ::endio::ERead::read(reader)?; + #read_post_padding + let ret = match disc { + #(#arms)* + _ => return ::std::result::Result::Err(::std::io::Error::new(::std::io::ErrorKind::InvalidData, format!("invalid discriminant value for {}: {}", stringify!(#name), disc))) + }; + } } fn gen_read_padding(padding: &Option) -> TokenStream { - match padding { - Some(x) => quote! { - let mut padding = [0; #x]; - ::std::io::Read::read_exact(reader, &mut padding)?; - }, - None => quote! { }, - } + match padding { + Some(x) => quote! { + let mut padding = [0; #x]; + ::std::io::Read::read_exact(reader, &mut padding)?; + }, + None => quote! {}, + } } diff --git a/endio_derive/src/lib.rs b/endio_derive/src/lib.rs index ae77f2c..0d57919 100644 --- a/endio_derive/src/lib.rs +++ b/endio_derive/src/lib.rs @@ -5,84 +5,90 @@ use proc_macro::TokenStream; use proc_macro2::Ident; use syn::{Attribute, DeriveInput, Field, Lit, LitInt, Meta, NestedMeta}; -#[proc_macro_derive(Deserialize, attributes(padding, pre_disc_padding, post_disc_padding, trailing_padding))] +#[proc_macro_derive( + Deserialize, + attributes(padding, pre_disc_padding, post_disc_padding, trailing_padding) +)] pub fn derive_deserialize(input: TokenStream) -> TokenStream { - deserialize::derive(input) + deserialize::derive(input) } -#[proc_macro_derive(Serialize, attributes(padding, pre_disc_padding, post_disc_padding, trailing_padding))] +#[proc_macro_derive( + Serialize, + attributes(padding, pre_disc_padding, post_disc_padding, trailing_padding) +)] pub fn derive_serialize(input: TokenStream) -> TokenStream { - serialize::derive(input) + serialize::derive(input) } fn get_enum_type(input: &DeriveInput) -> Ident { - for attr in &input.attrs { - if !attr.path.is_ident("repr") { - continue; - } - let meta = match attr.parse_meta() { - Err(_) => panic!("encountered unparseable repr attribute"), - Ok(x) => x, - }; - let list = match meta { - Meta::List(x) => x, - _ => continue, - }; - if list.nested.is_empty() { - panic!("encountered repr attribute with no arguments"); - } - for nested_meta in list.nested { - let meta = match nested_meta { - NestedMeta::Meta(x) => x, - NestedMeta::Lit(_) => continue, - }; - let path = match meta { - Meta::Path(x) => x, - _ => continue, - }; - if path.is_ident("C") || path.is_ident("transparent") { - continue; - } - return (*path.get_ident().expect("invalid repr attribute argument")).clone(); - } - } - panic!("You need to add a repr attribute to specify the discriminant type, e.g. #[repr(u16)]"); + for attr in &input.attrs { + if !attr.path.is_ident("repr") { + continue; + } + let meta = match attr.parse_meta() { + Err(_) => panic!("encountered unparseable repr attribute"), + Ok(x) => x, + }; + let list = match meta { + Meta::List(x) => x, + _ => continue, + }; + if list.nested.is_empty() { + panic!("encountered repr attribute with no arguments"); + } + for nested_meta in list.nested { + let meta = match nested_meta { + NestedMeta::Meta(x) => x, + NestedMeta::Lit(_) => continue, + }; + let path = match meta { + Meta::Path(x) => x, + _ => continue, + }; + if path.is_ident("C") || path.is_ident("transparent") { + continue; + } + return (*path.get_ident().expect("invalid repr attribute argument")).clone(); + } + } + panic!("You need to add a repr attribute to specify the discriminant type, e.g. #[repr(u16)]"); } fn get_padding(attrs: &Vec, attr_name: &str) -> Option { - for attr in attrs { - if !attr.path.is_ident(attr_name) { - continue; - } - let meta = match attr.parse_meta() { - Err(_) => panic!("encountered unparseable {} attribute", attr_name), - Ok(x) => x, - }; - let lit = match meta { - Meta::NameValue(x) => x.lit, - _ => panic!("{} needs to be name=value", attr_name), - }; - let int_lit = match lit { - Lit::Int(x) => x, - _ => panic!("{} needs to be an integer", attr_name), - }; - return Some(int_lit); - } - None + for attr in attrs { + if !attr.path.is_ident(attr_name) { + continue; + } + let meta = match attr.parse_meta() { + Err(_) => panic!("encountered unparseable {} attribute", attr_name), + Ok(x) => x, + }; + let lit = match meta { + Meta::NameValue(x) => x.lit, + _ => panic!("{} needs to be name=value", attr_name), + }; + let int_lit = match lit { + Lit::Int(x) => x, + _ => panic!("{} needs to be an integer", attr_name), + }; + return Some(int_lit); + } + None } fn get_field_padding(input: &Field) -> Option { - get_padding(&input.attrs, "padding") + get_padding(&input.attrs, "padding") } fn get_pre_disc_padding(input: &DeriveInput) -> Option { - get_padding(&input.attrs, "pre_disc_padding") + get_padding(&input.attrs, "pre_disc_padding") } fn get_post_disc_padding(input: &DeriveInput) -> Option { - get_padding(&input.attrs, "post_disc_padding") + get_padding(&input.attrs, "post_disc_padding") } fn get_trailing_padding(input: &DeriveInput) -> Option { - get_padding(&input.attrs, "trailing_padding") + get_padding(&input.attrs, "trailing_padding") } diff --git a/endio_derive/src/serialize.rs b/endio_derive/src/serialize.rs index 2bd2973..0aaa1c9 100644 --- a/endio_derive/src/serialize.rs +++ b/endio_derive/src/serialize.rs @@ -1,163 +1,186 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; -use syn::{parse_macro_input, parse_quote, Data, DataEnum, DeriveInput, Fields, LitInt, Generics, WhereClause}; +use syn::{ + Data, DataEnum, DeriveInput, Fields, Generics, LitInt, WhereClause, parse_macro_input, + parse_quote, +}; -use crate::{get_field_padding, get_pre_disc_padding, get_post_disc_padding, get_trailing_padding}; +use crate::{get_field_padding, get_post_disc_padding, get_pre_disc_padding, get_trailing_padding}; pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let mut input = parse_macro_input!(input as DeriveInput); - let where_generics = &mut input.generics.clone(); - let mut where_clause = where_generics.make_where_clause(); - let ser_code; + let mut input = parse_macro_input!(input as DeriveInput); + let where_generics = &mut input.generics.clone(); + let mut where_clause = where_generics.make_where_clause(); + let ser_code; - let name = &input.ident; + let name = &input.ident; - match &input.data { - Data::Struct(data) => { - add_where_clauses_fields(&mut where_clause, &data.fields); - ser_code = gen_ser_code_struct(&data.fields, &name); - } - Data::Enum(data) => { - let ty = crate::get_enum_type(&input); - add_where_clauses_enum(&mut where_clause, data, &ty); - let pre_disc_padding = get_pre_disc_padding(&input); - let post_disc_padding = get_post_disc_padding(&input); - ser_code = gen_ser_code_enum(data, &name, &ty, &pre_disc_padding, &post_disc_padding, &input.generics); - } - Data::Union(_) => unimplemented!(), - }; + match &input.data { + Data::Struct(data) => { + add_where_clauses_fields(&mut where_clause, &data.fields); + ser_code = gen_ser_code_struct(&data.fields, &name); + } + Data::Enum(data) => { + let ty = crate::get_enum_type(&input); + add_where_clauses_enum(&mut where_clause, data, &ty); + let pre_disc_padding = get_pre_disc_padding(&input); + let post_disc_padding = get_post_disc_padding(&input); + ser_code = gen_ser_code_enum( + data, + &name, + &ty, + &pre_disc_padding, + &post_disc_padding, + &input.generics, + ); + } + Data::Union(_) => unimplemented!(), + }; - let trailing_padding = get_trailing_padding(&input); - let write_padding = gen_write_padding(&trailing_padding); + let trailing_padding = get_trailing_padding(&input); + let write_padding = gen_write_padding(&trailing_padding); - let (_, ty_generics, where_clause) = where_generics.split_for_impl(); + let (_, ty_generics, where_clause) = where_generics.split_for_impl(); - // todo[hygiene]: replace __ENDIO_LIFETIME, __ENDIO_ENDIANNESS, __ENDIO_WRITER with unique ident - input.generics.params.push(parse_quote!('__ENDIO_LIFETIME)); - input.generics.params.push(parse_quote!(__ENDIO_ENDIANNESS: ::endio::Endianness)); - input.generics.params.push(parse_quote!(__ENDIO_WRITER: ::std::io::Write + ::endio::EWrite<__ENDIO_ENDIANNESS>)); - let (impl_generics, _, _) = input.generics.split_for_impl(); + // todo[hygiene]: replace __ENDIO_LIFETIME, __ENDIO_ENDIANNESS, __ENDIO_WRITER with unique ident + input.generics.params.push(parse_quote!('__ENDIO_LIFETIME)); + input + .generics + .params + .push(parse_quote!(__ENDIO_ENDIANNESS: ::endio::Endianness)); + input + .generics + .params + .push(parse_quote!(__ENDIO_WRITER: ::std::io::Write + ::endio::EWrite<__ENDIO_ENDIANNESS>)); + let (impl_generics, _, _) = input.generics.split_for_impl(); - let expanded = quote! { - impl #impl_generics ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER> for &'__ENDIO_LIFETIME #name #ty_generics #where_clause { - fn serialize(self, writer: &mut __ENDIO_WRITER) -> ::std::io::Result<()> { - #ser_code - #write_padding - Ok(()) - } - } - }; + let expanded = quote! { + impl #impl_generics ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER> for &'__ENDIO_LIFETIME #name #ty_generics #where_clause { + fn serialize(self, writer: &mut __ENDIO_WRITER) -> ::std::io::Result<()> { + #ser_code + #write_padding + Ok(()) + } + } + }; - expanded.into() + expanded.into() } fn add_where_clauses_fields(where_clause: &mut WhereClause, fields: &Fields) { - match fields { - Fields::Named(fields) => { - for f in &fields.named { - let ty = &f.ty; - where_clause.predicates.push( + match fields { + Fields::Named(fields) => { + for f in &fields.named { + let ty = &f.ty; + where_clause.predicates.push( parse_quote!(&'__ENDIO_LIFETIME #ty: ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER>) ); - } - } - Fields::Unnamed(fields) => { - for f in &fields.unnamed { - let ty = &f.ty; - where_clause.predicates.push( + } + } + Fields::Unnamed(fields) => { + for f in &fields.unnamed { + let ty = &f.ty; + where_clause.predicates.push( parse_quote!(&'__ENDIO_LIFETIME #ty: ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER>) ); - } - } - Fields::Unit => {} - } + } + } + Fields::Unit => {} + } } fn gen_ser_code_fields(fields: &Fields) -> TokenStream { - match fields { - Fields::Named(fields) => { - let mut pat = vec![]; - let mut ser = vec![]; - for f in &fields.named { - let ident = &f.ident; - let padding = get_field_padding(f); - let write_padding = gen_write_padding(&padding); - pat.push(quote! { #ident, }); - ser.push(quote! { - #write_padding - ::endio::EWrite::write(writer, #ident)?; - }); - } - quote! { { #(#pat)* } => { #(#ser)* } } - } - Fields::Unnamed(fields) => { - let mut index = String::from("a"); - let mut pat = vec![]; - let mut ser = vec![]; - for f in &fields.unnamed { - let ident = Ident::new(&index, Span::call_site()); - let padding = get_field_padding(f); - let write_padding = gen_write_padding(&padding); - pat.push(quote! { #ident, }); - ser.push(quote! { - #write_padding - ::endio::EWrite::write(writer, #ident)?; - }); - index += "a"; - } - quote! { ( #(#pat)* ) => { #(#ser)* } } - } - Fields::Unit => { - quote! { => {} } - } - } + match fields { + Fields::Named(fields) => { + let mut pat = vec![]; + let mut ser = vec![]; + for f in &fields.named { + let ident = &f.ident; + let padding = get_field_padding(f); + let write_padding = gen_write_padding(&padding); + pat.push(quote! { #ident, }); + ser.push(quote! { + #write_padding + ::endio::EWrite::write(writer, #ident)?; + }); + } + quote! { { #(#pat)* } => { #(#ser)* } } + } + Fields::Unnamed(fields) => { + let mut index = String::from("a"); + let mut pat = vec![]; + let mut ser = vec![]; + for f in &fields.unnamed { + let ident = Ident::new(&index, Span::call_site()); + let padding = get_field_padding(f); + let write_padding = gen_write_padding(&padding); + pat.push(quote! { #ident, }); + ser.push(quote! { + #write_padding + ::endio::EWrite::write(writer, #ident)?; + }); + index += "a"; + } + quote! { ( #(#pat)* ) => { #(#ser)* } } + } + Fields::Unit => { + quote! { => {} } + } + } } fn gen_ser_code_struct(fields: &Fields, name: &Ident) -> TokenStream { - let ser_code = gen_ser_code_fields(fields); - quote! { - match self { - #name #ser_code - } - } + let ser_code = gen_ser_code_fields(fields); + quote! { + match self { + #name #ser_code + } + } } fn add_where_clauses_enum(where_clause: &mut WhereClause, data: &DataEnum, ty: &Ident) { - where_clause.predicates.push( - parse_quote!(#ty: ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER>) - ); - for var in &data.variants { - add_where_clauses_fields(where_clause, &var.fields); - } + where_clause + .predicates + .push(parse_quote!(#ty: ::endio::Serialize<__ENDIO_ENDIANNESS, __ENDIO_WRITER>)); + for var in &data.variants { + add_where_clauses_fields(where_clause, &var.fields); + } } -fn gen_ser_code_enum(data: &DataEnum, name: &Ident, ty: &Ident, pre_disc_padding: &Option, post_disc_padding: &Option, generics: &Generics) -> TokenStream { - let mut arms = vec![]; - for f in &data.variants { - let ident = &f.ident; - let ser_fields = gen_ser_code_fields(&f.fields); - let expanded = quote! { #name::#ident #ser_fields }; - arms.push(expanded); - } - let write_pre_padding = gen_write_padding(pre_disc_padding); - let write_post_padding = gen_write_padding(post_disc_padding); - quote! { - #write_pre_padding - let disc = unsafe { *(self as *const #name #generics as *const #ty) }; - ::endio::EWrite::write(writer, disc)?; - #write_post_padding - match self { - #(#arms)* - } - } +fn gen_ser_code_enum( + data: &DataEnum, + name: &Ident, + ty: &Ident, + pre_disc_padding: &Option, + post_disc_padding: &Option, + generics: &Generics, +) -> TokenStream { + let mut arms = vec![]; + for f in &data.variants { + let ident = &f.ident; + let ser_fields = gen_ser_code_fields(&f.fields); + let expanded = quote! { #name::#ident #ser_fields }; + arms.push(expanded); + } + let write_pre_padding = gen_write_padding(pre_disc_padding); + let write_post_padding = gen_write_padding(post_disc_padding); + quote! { + #write_pre_padding + let disc = unsafe { *(self as *const #name #generics as *const #ty) }; + ::endio::EWrite::write(writer, disc)?; + #write_post_padding + match self { + #(#arms)* + } + } } fn gen_write_padding(padding: &Option) -> TokenStream { - match padding { - Some(x) => quote! { - let mut padding = [0; #x]; - ::std::io::Write::write_all(writer, &padding)?; - }, - None => quote! { }, - } + match padding { + Some(x) => quote! { + let mut padding = [0; #x]; + ::std::io::Write::write_all(writer, &padding)?; + }, + None => quote! {}, + } }