speedy_derive/
lib.rs

1#![recursion_limit="128"]
2
3use std::collections::HashMap;
4use std::u32;
5
6extern crate proc_macro;
7extern crate proc_macro2;
8
9#[macro_use]
10extern crate syn;
11
12#[macro_use]
13extern crate quote;
14
15use proc_macro2::{Span, TokenStream};
16use quote::ToTokens;
17use syn::punctuated::Punctuated;
18use syn::spanned::Spanned;
19use syn::TypeParam;
20
21trait IterExt: Iterator + Sized {
22    fn collect_vec( self ) -> Vec< Self::Item > {
23        self.collect()
24    }
25}
26
27impl< T > IterExt for T where T: Iterator + Sized {}
28
29#[proc_macro_derive(Readable, attributes(speedy))]
30pub fn readable( input: proc_macro::TokenStream ) -> proc_macro::TokenStream {
31    let input = parse_macro_input!( input as syn::DeriveInput );
32    let tokens = impl_readable( input ).unwrap_or_else( |err| err.to_compile_error() );
33    proc_macro::TokenStream::from( tokens )
34}
35
36#[proc_macro_derive(Writable, attributes(speedy))]
37pub fn writable( input: proc_macro::TokenStream ) -> proc_macro::TokenStream {
38    let input = parse_macro_input!( input as syn::DeriveInput );
39    let tokens = impl_writable( input ).unwrap_or_else( |err| err.to_compile_error() );
40    proc_macro::TokenStream::from( tokens )
41}
42
43mod kw {
44    syn::custom_keyword!( length );
45    syn::custom_keyword!( default_on_eof );
46    syn::custom_keyword!( tag_type );
47    syn::custom_keyword!( length_type );
48    syn::custom_keyword!( tag );
49    syn::custom_keyword!( skip );
50    syn::custom_keyword!( constant_prefix );
51    syn::custom_keyword!( peek_tag );
52    syn::custom_keyword!( varint );
53    syn::custom_keyword!( unsafe_is_primitive );
54    syn::custom_keyword!( always );
55
56    syn::custom_keyword!( u7 );
57    syn::custom_keyword!( u8 );
58    syn::custom_keyword!( u16 );
59    syn::custom_keyword!( u32 );
60    syn::custom_keyword!( u64 );
61    syn::custom_keyword!( u64_varint );
62}
63
64#[derive(Copy, Clone, PartialEq)]
65enum Trait {
66    Readable,
67    Writable,
68    ZeroCopyable { is_packed: bool, is_forced: bool }
69}
70
71fn uses_generics( input: &syn::DeriveInput ) -> bool {
72    input.generics.type_params().next().is_some() ||
73    input.generics.lifetimes().next().is_some() ||
74    input.generics.const_params().next().is_some()
75}
76
77fn possibly_uses_generic_ty( generic_types: &[&syn::Ident], ty: &syn::Type ) -> bool {
78    match ty {
79        syn::Type::Path( syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments } } ) => {
80            segments.iter().any( |segment| {
81                if generic_types.iter().any( |&ident| *ident == segment.ident ) {
82                    return true;
83                }
84
85                match segment.arguments {
86                    syn::PathArguments::None => false,
87                    syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { ref args, .. } ) => {
88                        args.iter().any( |arg| {
89                            match arg {
90                                syn::GenericArgument::Lifetime( .. ) => false,
91                                syn::GenericArgument::Type( inner_ty ) => possibly_uses_generic_ty( generic_types, inner_ty ),
92                                syn::GenericArgument::AssocType( assoc_type ) => possibly_uses_generic_ty( generic_types, &assoc_type.ty ),
93                                // TODO: How to handle these?
94                                syn::GenericArgument::Constraint( .. ) => true,
95                                syn::GenericArgument::Const( .. ) => true,
96                                syn::GenericArgument::AssocConst(_) => true,
97                                _ => true,
98                            }
99                        })
100                    },
101                    _ => true
102                }
103            })
104        },
105        syn::Type::Slice( syn::TypeSlice { elem, .. } ) => possibly_uses_generic_ty( generic_types, &elem ),
106        syn::Type::Tuple( syn::TypeTuple { elems, .. } ) => elems.iter().any( |elem| possibly_uses_generic_ty( generic_types, elem ) ),
107        syn::Type::Reference( syn::TypeReference { elem, .. } ) => possibly_uses_generic_ty( generic_types, &elem ),
108        syn::Type::Paren( syn::TypeParen { elem, .. } ) => possibly_uses_generic_ty( generic_types, &elem ),
109        syn::Type::Ptr( syn::TypePtr { elem, .. } ) => possibly_uses_generic_ty( generic_types, &elem ),
110        syn::Type::Group( syn::TypeGroup { elem, .. } ) => possibly_uses_generic_ty( generic_types, &elem ),
111        syn::Type::Array( syn::TypeArray { elem, len, .. } ) => {
112            if possibly_uses_generic_ty( generic_types, &elem ) {
113                return true;
114            }
115
116            // This is probably too conservative.
117            match len {
118                syn::Expr::Lit( .. ) => false,
119                _ => true
120            }
121        },
122        syn::Type::Never( .. ) => false,
123        _ => true
124    }
125}
126
127#[test]
128fn test_possibly_uses_generic_ty() {
129    macro_rules! assert_test {
130        ($result:expr, $($token:tt)+) => {
131            assert_eq!(
132                possibly_uses_generic_ty( &[&syn::Ident::new( "T", proc_macro2::Span::call_site() )], &syn::parse2( quote! { $($token)+ } ).unwrap() ),
133                $result
134            );
135        }
136    }
137
138    assert_test!( false, String );
139    assert_test!( false, Cow<'a, BTreeMap<u8, u8>> );
140    assert_test!( false, Cow<'a, [u8]> );
141    assert_test!( false, () );
142    assert_test!( false, (u8) );
143    assert_test!( false, (u8, u8) );
144    assert_test!( false, &u8 );
145    assert_test!( false, *const u8 );
146    assert_test!( false, ! );
147    assert_test!( false, [u8; 2] );
148    assert_test!( true, T );
149    assert_test!( true, Dummy::T );
150    assert_test!( true, Cow<'a, BTreeMap<T, u8>> );
151    assert_test!( true, Cow<'a, BTreeMap<u8, T>> );
152    assert_test!( true, Cow<'a, [T]> );
153    assert_test!( true, (T) );
154    assert_test!( true, (u8, T) );
155    assert_test!( true, &T );
156    assert_test!( true, *const T );
157    assert_test!( true, [T; 2] );
158    assert_test!( true, Vec<T> );
159}
160
161fn is_guaranteed_non_recursive( ty: &syn::Type ) -> bool {
162    match ty {
163        syn::Type::Path( syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments } } ) => {
164            if segments.len() != 1 {
165                return false;
166            }
167
168            let segment = &segments[ 0 ];
169            let ident = segment.ident.to_string();
170            match ident.as_str() {
171                "String" | "Vec" | "BTreeSet" | "BTreeMap" | "HashSet" | "HashMap" |
172                "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "usize" | "isize" |
173                "str" => {},
174                _ => return false
175            }
176
177            match segment.arguments {
178                syn::PathArguments::None => true,
179                syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { ref args, .. } ) => {
180                    args.iter().all( |arg| {
181                            match arg {
182                                syn::GenericArgument::Lifetime( .. ) => true,
183                                syn::GenericArgument::Type( inner_ty ) => is_guaranteed_non_recursive( inner_ty ),
184                                syn::GenericArgument::AssocType( assoc_type ) => is_guaranteed_non_recursive( &assoc_type.ty ),
185                                // TODO: How to handle these?
186                                syn::GenericArgument::Constraint( .. ) => false,
187                                syn::GenericArgument::Const( .. ) => false,
188                                syn::GenericArgument::AssocConst(_) => false,
189                                _ => false,
190                            }
191                        })
192                },
193                _ => false
194            }
195        },
196        syn::Type::Slice( syn::TypeSlice { elem, .. } ) => is_guaranteed_non_recursive( &elem ),
197        syn::Type::Tuple( syn::TypeTuple { elems, .. } ) => elems.iter().all( |elem| is_guaranteed_non_recursive( elem ) ),
198        syn::Type::Reference( syn::TypeReference { elem, .. } ) => is_guaranteed_non_recursive( &elem ),
199        syn::Type::Paren( syn::TypeParen { elem, .. } ) => is_guaranteed_non_recursive( &elem ),
200        syn::Type::Ptr( syn::TypePtr { elem, .. } ) => is_guaranteed_non_recursive( &elem ),
201        syn::Type::Group( syn::TypeGroup { elem, .. } ) => is_guaranteed_non_recursive( &elem ),
202        syn::Type::Array( syn::TypeArray { elem, len, .. } ) => {
203            if !is_guaranteed_non_recursive( &elem ) {
204                return false;
205            }
206
207            // This is probably too conservative.
208            match len {
209                syn::Expr::Lit( .. ) => true,
210                _ => false
211            }
212        },
213        syn::Type::Never( .. ) => true,
214        _ => false
215    }
216}
217
218#[test]
219fn test_is_guaranteed_non_recursive() {
220    macro_rules! assert_test {
221        ($result:expr, $($token:tt)+) => {
222            assert_eq!(
223                is_guaranteed_non_recursive( &syn::parse2( quote! { $($token)+ } ).unwrap() ),
224                $result
225            );
226        }
227    }
228
229    assert_test!( true, String );
230    assert_test!( true, u8 );
231    assert_test!( true, () );
232    assert_test!( true, *const u8 );
233    assert_test!( true, [u8; 2] );
234    assert_test!( true, (u8, u16) );
235    assert_test!( true, ! );
236    assert_test!( true, Vec< u8 > );
237    assert_test!( false, T );
238    assert_test!( false, Vec< T > );
239}
240
241#[derive(Copy, Clone, PartialEq, Eq)]
242enum PrimitiveTy {
243    U8,
244    U16,
245    U32,
246    U64,
247    U128,
248    I8,
249    I16,
250    I32,
251    I64,
252    I128,
253    F32,
254    F64
255}
256
257fn parse_primitive_ty( ty: &syn::Type ) -> Option< PrimitiveTy > {
258    match ty {
259        syn::Type::Path( syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments } } ) => {
260            if segments.len() != 1 {
261                return None;
262            }
263
264            let segment = &segments[ 0 ];
265            let ident = segment.ident.to_string();
266            match ident.as_str() {
267                "u8" => Some( PrimitiveTy::U8 ),
268                "u16" => Some( PrimitiveTy::U16 ),
269                "u32" => Some( PrimitiveTy::U32 ),
270                "u64" => Some( PrimitiveTy::U64 ),
271                "u128" => Some( PrimitiveTy::U128 ),
272                "i8" => Some( PrimitiveTy::I8 ),
273                "i16" => Some( PrimitiveTy::I16 ),
274                "i32" => Some( PrimitiveTy::I32 ),
275                "i64" => Some( PrimitiveTy::I64 ),
276                "i128" => Some( PrimitiveTy::I128 ),
277                "f32" => Some( PrimitiveTy::F32 ),
278                "f64" => Some( PrimitiveTy::F64 ),
279                _ => None
280            }
281        },
282        _ => None
283    }
284}
285
286fn common_tokens( ast: &syn::DeriveInput, types: &[syn::Type], trait_variant: Trait ) -> (TokenStream, TokenStream, TokenStream) {
287    let impl_params = {
288        let lifetime_params = ast.generics.lifetimes().map( |alpha| quote! { #alpha } );
289        let type_params = ast.generics.type_params().map( |ty| { let ty_without_default = TypeParam { default: None, ..ty.clone() }; quote! { #ty_without_default } });
290        let params = lifetime_params.chain( type_params ).collect_vec();
291        quote! {
292            #(#params,)*
293        }
294    };
295
296    let ty_params = {
297        let lifetime_params = ast.generics.lifetimes().map( |alpha| quote! { #alpha } );
298        let type_params = ast.generics.type_params().map( |ty| { let ident = &ty.ident; quote! { #ident } } );
299        let params = lifetime_params.chain( type_params ).collect_vec();
300        if params.is_empty() {
301            quote! {}
302        } else {
303            quote! { < #(#params),* > }
304        }
305    };
306
307    let generics: Vec< _ > = ast.generics.type_params().map( |ty| &ty.ident ).collect();
308    let where_clause = {
309        let constraints = types.iter().filter_map( |ty| {
310            let possibly_generic = possibly_uses_generic_ty( &generics, ty );
311            match (trait_variant, possibly_generic) {
312                (Trait::Readable, true) => Some( quote! { #ty: speedy::Readable< 'a_, C_ > } ),
313                (Trait::Readable, false) => None,
314                (Trait::Writable, true) => Some( quote! { #ty: speedy::Writable< C_ > } ),
315                (Trait::Writable, false) => None,
316                (Trait::ZeroCopyable { is_packed, is_forced }, _) => {
317                    if is_forced || (is_packed && parse_primitive_ty( ty ).is_some()) {
318                        None
319                    } else {
320                        Some( quote! { #ty: speedy::private::ZeroCopyable< C_, T_ > } )
321                    }
322                },
323            }
324        });
325
326        let mut predicates = Vec::new();
327        if let Some( where_clause ) = ast.generics.where_clause.as_ref() {
328            predicates = where_clause.predicates.iter().map( |pred| quote! { #pred } ).collect();
329        }
330
331        if trait_variant == Trait::Readable {
332            for lifetime in ast.generics.lifetimes() {
333                predicates.push( quote! { 'a_: #lifetime } );
334                predicates.push( quote! { #lifetime: 'a_ } );
335            }
336        }
337
338        let items = constraints.chain( predicates.into_iter() ).collect_vec();
339        if items.is_empty() {
340            quote! {}
341        } else {
342            quote! { where #(#items),* }
343        }
344    };
345
346    (impl_params, ty_params, where_clause)
347}
348
349#[derive(Copy, Clone)]
350enum BasicType {
351    U7,
352    U8,
353    U16,
354    U32,
355    U64,
356    VarInt64
357}
358
359const DEFAULT_LENGTH_TYPE: BasicType = BasicType::U32;
360const DEFAULT_ENUM_TAG_TYPE: BasicType = BasicType::U32;
361
362impl syn::parse::Parse for BasicType {
363    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
364        let lookahead = input.lookahead1();
365        let ty = if lookahead.peek( kw::u7 ) {
366            input.parse::< kw::u7 >()?;
367            BasicType::U7
368        } else if lookahead.peek( kw::u8 ) {
369            input.parse::< kw::u8 >()?;
370            BasicType::U8
371        } else if lookahead.peek( kw::u16 ) {
372            input.parse::< kw::u16 >()?;
373            BasicType::U16
374        } else if lookahead.peek( kw::u32 ) {
375            input.parse::< kw::u32 >()?;
376            BasicType::U32
377        } else if lookahead.peek( kw::u64 ) {
378            input.parse::< kw::u64 >()?;
379            BasicType::U64
380        } else if lookahead.peek( kw::u64_varint ) {
381            input.parse::< kw::u64_varint >()?;
382            BasicType::VarInt64
383        } else {
384            return Err( lookahead.error() );
385        };
386
387        Ok( ty )
388    }
389}
390
391enum IsPrimitive {
392    Always,
393}
394
395impl syn::parse::Parse for IsPrimitive {
396    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
397        let lookahead = input.lookahead1();
398        let ty = if lookahead.peek( kw::always ) {
399            input.parse::< kw::always >()?;
400            IsPrimitive::Always
401        } else {
402            return Err( lookahead.error() );
403        };
404
405        Ok( ty )
406    }
407}
408
409enum ToplevelStructAttribute {
410    UnsafeIsPrimitive { key_token: kw::unsafe_is_primitive, kind: IsPrimitive },
411    StructAttribute( StructAttribute )
412}
413
414enum VariantAttribute {
415    Tag {
416        key_token: kw::tag,
417        tag: u64
418    }
419}
420
421enum StructAttribute {
422}
423
424enum EnumAttribute {
425    TagType {
426        key_token: kw::tag_type,
427        ty: BasicType
428    },
429    PeekTag {
430        key_token: kw::peek_tag
431    }
432}
433
434enum VariantOrStructAttribute {
435    Variant( VariantAttribute ),
436    Struct( StructAttribute )
437}
438
439fn parse_variant_attribute(
440    input: &syn::parse::ParseStream,
441    lookahead: &syn::parse::Lookahead1
442) -> syn::parse::Result< Option< VariantAttribute > >
443{
444    let attribute = if lookahead.peek( kw::tag ) {
445        let key_token = input.parse::< kw::tag >()?;
446        let _: Token![=] = input.parse()?;
447        let raw_tag: syn::LitInt = input.parse()?;
448        let tag = raw_tag.base10_parse::< u64 >().map_err( |err| {
449            syn::Error::new( raw_tag.span(), err )
450        })?;
451
452        VariantAttribute::Tag {
453            key_token,
454            tag
455        }
456    } else {
457        return Ok( None )
458    };
459
460    Ok( Some( attribute ) )
461}
462
463fn parse_struct_attribute(
464    _input: &syn::parse::ParseStream,
465    _lookahead: &syn::parse::Lookahead1
466) -> syn::parse::Result< Option< StructAttribute > >
467{
468    Ok( None )
469}
470
471fn parse_enum_attribute(
472    input: &syn::parse::ParseStream,
473    lookahead: &syn::parse::Lookahead1
474) -> syn::parse::Result< Option< EnumAttribute > >
475{
476    let attribute = if lookahead.peek( kw::tag_type ) {
477        let key_token = input.parse::< kw::tag_type >()?;
478        let _: Token![=] = input.parse()?;
479        let ty: BasicType = input.parse()?;
480
481        EnumAttribute::TagType {
482            key_token,
483            ty
484        }
485    } else if lookahead.peek( kw::peek_tag ) {
486        let key_token = input.parse::< kw::peek_tag >()?;
487        EnumAttribute::PeekTag {
488            key_token
489        }
490    } else {
491        return Ok( None )
492    };
493
494    Ok( Some( attribute ) )
495}
496
497impl syn::parse::Parse for ToplevelStructAttribute {
498    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
499        let lookahead = input.lookahead1();
500        if lookahead.peek( kw::unsafe_is_primitive ) {
501            let key_token = input.parse::< kw::unsafe_is_primitive >()?;
502            let _: Token![=] = input.parse()?;
503            let kind = input.parse::< IsPrimitive >()?;
504            Ok( ToplevelStructAttribute::UnsafeIsPrimitive { key_token, kind } )
505        } else if let Some( attr ) = parse_struct_attribute( &input, &lookahead )? {
506            Ok( ToplevelStructAttribute::StructAttribute( attr ) )
507        } else {
508            Err( lookahead.error() )
509        }
510    }
511}
512
513impl syn::parse::Parse for StructAttribute {
514    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
515        let lookahead = input.lookahead1();
516        parse_struct_attribute( &input, &lookahead )?.ok_or_else( || lookahead.error() )
517    }
518}
519
520impl syn::parse::Parse for EnumAttribute {
521    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
522        let lookahead = input.lookahead1();
523        parse_enum_attribute( &input, &lookahead )?.ok_or_else( || lookahead.error() )
524    }
525}
526
527impl syn::parse::Parse for VariantOrStructAttribute {
528    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
529        let lookahead = input.lookahead1();
530        if let Some( attr ) = parse_variant_attribute( &input, &lookahead )? {
531            return Ok( VariantOrStructAttribute::Variant( attr ) );
532        }
533
534        if let Some( attr ) = parse_struct_attribute( &input, &lookahead )? {
535            return Ok( VariantOrStructAttribute::Struct( attr ) );
536        }
537
538        Err( lookahead.error() )
539    }
540}
541
542struct VariantAttributes {
543    tag: Option< u64 >
544}
545
546struct StructAttributes {
547}
548
549struct EnumAttributes {
550    tag_type: Option< BasicType >,
551    peek_tag: bool
552}
553
554struct ToplevelStructAttributes {
555    is_primitive: Option< IsPrimitive >,
556    struct_attributes: StructAttributes
557}
558
559impl std::ops::Deref for ToplevelStructAttributes {
560    type Target = StructAttributes;
561    fn deref( &self ) -> &Self::Target {
562        &self.struct_attributes
563    }
564}
565
566fn check_repr( attrs: &[syn::Attribute], value: &str ) -> bool {
567    let mut result = false;
568    for raw_attr in attrs {
569        let path = raw_attr.meta.path().clone().into_token_stream().to_string();
570        if path != "repr" {
571            continue;
572        }
573
574        if let Ok(meta_list) = raw_attr.meta.require_list() {
575            result = meta_list.tokens.clone().into_token_stream().to_string() == value;
576        }
577    }
578
579    result
580}
581
582fn is_transparent( attrs: &[syn::Attribute] ) -> bool {
583    check_repr( attrs, "transparent" )
584}
585
586fn is_packed( attrs: &[syn::Attribute] ) -> bool {
587    check_repr( attrs, "packed" )
588}
589
590fn is_c( attrs: &[syn::Attribute] ) -> bool {
591    check_repr( attrs, "C" )
592}
593
594fn parse_attributes< T >( attrs: &[syn::Attribute] ) -> Result< Vec< T >, syn::Error > where T: syn::parse::Parse {
595    struct RawAttributes< T >( Punctuated< T, Token![,] > );
596
597    impl< T > syn::parse::Parse for RawAttributes< T > where T: syn::parse::Parse {
598        fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
599            let content;
600            parenthesized!( content in input );
601            Ok( RawAttributes( content.parse_terminated( T::parse, Token![,] )? ) )
602        }
603    }
604
605    let mut output = Vec::new();
606    for raw_attr in attrs {
607        let path = raw_attr.meta.path().clone().into_token_stream().to_string();
608        if path != "speedy" {
609            continue;
610        }
611
612        let meta_list = raw_attr.meta.require_list()?;
613        let parsed_attrs = syn::parse::Parser::parse2(
614            Punctuated::<T, Token![,]>::parse_terminated,
615            meta_list.tokens.clone(),
616        )?;
617        for attr in parsed_attrs {
618            output.push( attr );
619        }
620    }
621
622    Ok( output )
623}
624
625fn collect_variant_attributes( attrs: Vec< VariantAttribute > ) -> Result< VariantAttributes, syn::Error > {
626    let mut variant_tag = None;
627    for attr in attrs {
628        match attr {
629            VariantAttribute::Tag { key_token, tag } => {
630                if variant_tag.is_some() {
631                    let message = "Duplicate 'tag'";
632                    return Err( syn::Error::new( key_token.span(), message ) );
633                }
634                variant_tag = Some( tag );
635            }
636        }
637    }
638
639    Ok( VariantAttributes {
640        tag: variant_tag
641    })
642}
643
644fn collect_struct_attributes( attrs: Vec< StructAttribute > ) -> Result< StructAttributes, syn::Error > {
645    for _attr in attrs {
646    }
647
648    Ok( StructAttributes {
649    })
650}
651
652fn collect_toplevel_struct_attributes( attrs: Vec< ToplevelStructAttribute > ) -> Result< ToplevelStructAttributes, syn::Error > {
653    let mut struct_attributes = Vec::new();
654    let mut is_primitive = None;
655    for attr in attrs {
656        match attr {
657            ToplevelStructAttribute::UnsafeIsPrimitive { key_token, kind } => {
658                if is_primitive.is_some() {
659                    let message = "Duplicate 'unsafe_is_primitive'";
660                    return Err( syn::Error::new( key_token.span(), message ) );
661                }
662                is_primitive = Some( kind );
663            },
664            ToplevelStructAttribute::StructAttribute( attr ) => {
665                struct_attributes.push( attr );
666            }
667        }
668    }
669
670    let struct_attributes = collect_struct_attributes( struct_attributes )?;
671    Ok( ToplevelStructAttributes {
672        is_primitive,
673        struct_attributes
674    })
675}
676
677
678fn collect_enum_attributes( attrs: Vec< EnumAttribute > ) -> Result< EnumAttributes, syn::Error > {
679    let mut tag_type = None;
680    let mut peek_tag = false;
681    for attr in attrs {
682        match attr {
683            EnumAttribute::TagType { key_token, ty } => {
684                if tag_type.is_some() {
685                    let message = "Duplicate 'tag_type'";
686                    return Err( syn::Error::new( key_token.span(), message ) );
687                }
688                tag_type = Some( ty );
689            },
690            EnumAttribute::PeekTag { key_token } => {
691                if peek_tag {
692                    let message = "Duplicate 'peek_tag'";
693                    return Err( syn::Error::new( key_token.span(), message ) );
694                }
695                peek_tag = true;
696            }
697        }
698    }
699
700    Ok( EnumAttributes {
701        tag_type,
702        peek_tag
703    })
704}
705
706#[derive(PartialEq)]
707enum StructKind {
708    Unit,
709    Named,
710    Unnamed
711}
712
713struct Struct< 'a > {
714    fields: Vec< Field< 'a > >,
715    kind: StructKind
716}
717
718impl< 'a > Struct< 'a > {
719    fn new( fields: &'a syn::Fields, _attrs: &StructAttributes ) -> Result< Self, syn::Error > {
720        let structure = match fields {
721            syn::Fields::Unit => {
722                Struct {
723                    fields: Vec::new(),
724                    kind: StructKind::Unit
725                }
726            },
727            syn::Fields::Named( syn::FieldsNamed { ref named, .. } ) => {
728                Struct {
729                    fields: get_fields( named.into_iter() )?,
730                    kind: StructKind::Named
731                }
732            },
733            syn::Fields::Unnamed( syn::FieldsUnnamed { ref unnamed, .. } ) => {
734                Struct {
735                    fields: get_fields( unnamed.into_iter() )?,
736                    kind: StructKind::Unnamed
737                }
738            }
739        };
740
741        Ok( structure )
742    }
743
744    fn is_guaranteed_non_recursive( &self ) -> bool {
745        self.fields.iter().all( |field| field.is_guaranteed_non_recursive() )
746    }
747}
748
749struct Field< 'a > {
750    index: usize,
751    name: Option< &'a syn::Ident >,
752    raw_ty: &'a syn::Type,
753    default_on_eof: bool,
754    length: Option< LengthKind >,
755    length_type: Option< BasicType >,
756    ty: Opt< Ty >,
757    skip: bool,
758    varint: bool,
759    constant_prefix: Option< syn::LitByteStr >
760}
761
762impl< 'a > Field< 'a > {
763    fn can_be_primitive( &self ) -> bool {
764        self.default_on_eof == false &&
765        self.length.is_none() &&
766        self.length_type.is_none() &&
767        self.skip == false &&
768        self.varint == false &&
769        self.constant_prefix.is_none()
770    }
771
772    fn is_simple( &self ) -> bool {
773        parse_primitive_ty( self.raw_ty ).is_some()
774    }
775
776    fn var_name( &self ) -> syn::Ident {
777        if let Some( name ) = self.name {
778            name.clone()
779        } else {
780            syn::Ident::new( &format!( "t{}", self.index ), Span::call_site() )
781        }
782    }
783
784    fn name( &self ) -> syn::Member {
785        if let Some( name ) = self.name {
786            syn::Member::Named( name.clone() )
787        } else {
788            syn::Member::Unnamed( syn::Index { index: self.index as u32, span: Span::call_site() } )
789        }
790    }
791
792    fn bound_types( &self ) -> Vec< syn::Type > {
793        match self.ty.inner() {
794            | Ty::Array( inner_ty, .. )
795            | Ty::Vec( inner_ty )
796            | Ty::HashSet( inner_ty )
797            | Ty::BTreeSet( inner_ty )
798            | Ty::CowHashSet( _, inner_ty )
799            | Ty::CowBTreeSet( _, inner_ty )
800            | Ty::CowSlice( _, inner_ty )
801            | Ty::RefSlice( _, inner_ty )
802                => vec![ inner_ty.clone() ],
803            | Ty::HashMap( key_ty, value_ty )
804            | Ty::BTreeMap( key_ty, value_ty )
805            | Ty::CowHashMap( _, key_ty, value_ty )
806            | Ty::CowBTreeMap( _, key_ty, value_ty )
807                => vec![ key_ty.clone(), value_ty.clone() ],
808            | Ty::RefSliceU8( _ )
809            | Ty::RefStr( _ )
810            | Ty::String
811            | Ty::CowStr( .. )
812            | Ty::Primitive( .. )
813                => vec![],
814            | Ty::Ty( _ ) => vec![ self.raw_ty.clone() ]
815        }
816    }
817
818    fn is_guaranteed_non_recursive( &self ) -> bool {
819        is_guaranteed_non_recursive( &self.raw_ty )
820    }
821}
822
823enum LengthKind {
824    Expr( syn::Expr ),
825    UntilEndOfFile
826}
827
828impl syn::parse::Parse for LengthKind {
829    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
830        if input.peek( Token![..] ) {
831            let _: Token![..] = input.parse()?;
832            Ok( LengthKind::UntilEndOfFile )
833        } else {
834            let expr: syn::Expr = input.parse()?;
835            Ok( LengthKind::Expr( expr ) )
836        }
837    }
838}
839
840enum FieldAttribute {
841    DefaultOnEof {
842        key_span: Span
843    },
844    Length {
845        key_span: Span,
846        length_kind: LengthKind
847    },
848    LengthType {
849        key_span: Span,
850        ty: BasicType
851    },
852    Skip {
853        key_span: Span
854    },
855    ConstantPrefix {
856        key_span: Span,
857        prefix: syn::LitByteStr
858    },
859    VarInt {
860        key_span: Span
861    }
862}
863
864impl syn::parse::Parse for FieldAttribute {
865    fn parse( input: syn::parse::ParseStream ) -> syn::parse::Result< Self > {
866        let lookahead = input.lookahead1();
867        let value = if lookahead.peek( kw::default_on_eof ) {
868            let key_token = input.parse::< kw::default_on_eof >()?;
869            FieldAttribute::DefaultOnEof {
870                key_span: key_token.span()
871            }
872        } else if lookahead.peek( kw::length ) {
873            let key_token = input.parse::< kw::length >()?;
874            let _: Token![=] = input.parse()?;
875            let length_kind: LengthKind = input.parse()?;
876            FieldAttribute::Length {
877                key_span: key_token.span(),
878                length_kind
879            }
880        } else if lookahead.peek( kw::length_type ) {
881            let key_token = input.parse::< kw::length_type>()?;
882            let _: Token![=] = input.parse()?;
883            let ty: BasicType = input.parse()?;
884            FieldAttribute::LengthType {
885                key_span: key_token.span(),
886                ty
887            }
888        } else if lookahead.peek( kw::skip ) {
889            let key_token = input.parse::< kw::skip >()?;
890            FieldAttribute::Skip {
891                key_span: key_token.span()
892            }
893        } else if lookahead.peek( kw::constant_prefix ) {
894            let key_token = input.parse::< kw::constant_prefix >()?;
895            let _: Token![=] = input.parse()?;
896            let expr: syn::Expr = input.parse()?;
897            let value_span = expr.span();
898            let generic_error = || {
899                Err( syn::Error::new( value_span, "unsupported expression; only basic literals are supported" ) )
900            };
901
902            let prefix = match expr {
903                syn::Expr::Lit( literal ) => {
904                    let literal = literal.lit;
905                    match literal {
906                        syn::Lit::Str( literal ) => literal.value().into_bytes(),
907                        syn::Lit::ByteStr( literal ) => literal.value(),
908                        syn::Lit::Byte( literal ) => vec![ literal.value() ],
909                        syn::Lit::Char( literal ) => format!( "{}", literal.value() ).into_bytes(),
910                        syn::Lit::Bool( literal ) => vec![ if literal.value { 1 } else { 0 } ],
911                        syn::Lit::Int( literal ) => {
912                            if literal.suffix() == "u8" {
913                                vec![ literal.base10_parse::< u8 >().unwrap() ]
914                            } else {
915                                return Err( syn::Error::new( value_span, "integers are not supported; if you want to use a single byte constant then append either 'u8' or 'i8' to it" ) );
916                            }
917                        },
918                        syn::Lit::Float( _ ) => return Err( syn::Error::new( value_span, "floats are not supported" ) ),
919                        syn::Lit::Verbatim( _ ) => return Err( syn::Error::new( value_span, "verbatim literals are not supported" ) ),
920                        _ => return Err( syn::Error::new( value_span, "unsupported literal" ) )
921                    }
922                },
923                syn::Expr::Unary( syn::ExprUnary { op: syn::UnOp::Neg(_), expr, .. } ) => {
924                    match *expr {
925                        syn::Expr::Lit( syn::ExprLit { lit: literal, .. } ) => {
926                            match literal {
927                                syn::Lit::Int( literal ) => {
928                                    if literal.suffix() == "i8" {
929                                        vec![ (literal.base10_parse::< i8 >().unwrap() * -1) as u8 ]
930                                    } else if literal.suffix() == "u8" {
931                                        return generic_error()
932                                    } else {
933                                        return Err( syn::Error::new( value_span, "integers are not supported; if you want to use a single byte constant then append either 'u8' or 'i8' to it" ) );
934                                    }
935                                },
936                                _ => return generic_error()
937                            }
938                        },
939                        _ => return generic_error()
940                    }
941                },
942                _ => return generic_error()
943            };
944
945            FieldAttribute::ConstantPrefix {
946                key_span: key_token.span(),
947                prefix: syn::LitByteStr::new( &prefix, value_span )
948            }
949        } else if lookahead.peek( kw::varint ) {
950            let key_token = input.parse::< kw::varint >()?;
951            FieldAttribute::VarInt {
952                key_span: key_token.span()
953            }
954        } else {
955            return Err( lookahead.error() )
956        };
957
958        Ok( value )
959    }
960}
961
962enum Opt< T > {
963    Plain( T ),
964    Option( T )
965}
966
967impl< T > Opt< T > {
968    fn inner( &self ) -> &T {
969        match *self {
970            Opt::Option( ref inner ) => inner,
971            Opt::Plain( ref inner ) => inner
972        }
973    }
974}
975
976enum Ty {
977    String,
978    Vec( syn::Type ),
979    CowSlice( syn::Lifetime, syn::Type ),
980    CowStr( syn::Lifetime ),
981    HashMap( syn::Type, syn::Type ),
982    HashSet( syn::Type ),
983    BTreeMap( syn::Type, syn::Type ),
984    BTreeSet( syn::Type ),
985
986    CowHashMap( syn::Lifetime, syn::Type, syn::Type ),
987    CowHashSet( syn::Lifetime, syn::Type ),
988    CowBTreeMap( syn::Lifetime, syn::Type, syn::Type ),
989    CowBTreeSet( syn::Lifetime, syn::Type ),
990
991    RefSliceU8( syn::Lifetime ),
992    RefSlice( syn::Lifetime, syn::Type ),
993    RefStr( syn::Lifetime ),
994
995    Array( syn::Type, u32 ),
996
997    Primitive( PrimitiveTy ),
998    Ty( syn::Type )
999}
1000
1001fn extract_inner_ty( args: &Punctuated< syn::GenericArgument, syn::token::Comma > ) -> Option< &syn::Type > {
1002    if args.len() != 1 {
1003        return None;
1004    }
1005
1006    match args[ 0 ] {
1007        syn::GenericArgument::Type( ref ty ) => Some( ty ),
1008         _ => None
1009    }
1010}
1011
1012fn extract_inner_ty_2( args: &Punctuated< syn::GenericArgument, syn::token::Comma > ) -> Option< (&syn::Type, &syn::Type) > {
1013    if args.len() != 2 {
1014        return None;
1015    }
1016
1017    let ty_1 = match args[ 0 ] {
1018        syn::GenericArgument::Type( ref ty ) => ty,
1019         _ => return None
1020    };
1021
1022    let ty_2 = match args[ 1 ] {
1023        syn::GenericArgument::Type( ref ty ) => ty,
1024         _ => return None
1025    };
1026
1027    Some( (ty_1, ty_2) )
1028}
1029
1030fn extract_lifetime_and_inner_ty( args: &Punctuated< syn::GenericArgument, syn::token::Comma > ) -> Option< (&syn::Lifetime, &syn::Type) > {
1031    if args.len() != 2 {
1032        return None;
1033    }
1034
1035    let lifetime = match args[ 0 ] {
1036        syn::GenericArgument::Lifetime( ref lifetime ) => lifetime,
1037        _ => return None
1038    };
1039
1040    let ty = match args[ 1 ] {
1041        syn::GenericArgument::Type( ref ty ) => ty,
1042         _ => return None
1043    };
1044
1045    Some( (lifetime, ty) )
1046}
1047
1048fn extract_slice_inner_ty( ty: &syn::Type ) -> Option< &syn::Type > {
1049    match *ty {
1050        syn::Type::Slice( syn::TypeSlice { ref elem, .. } ) => {
1051            Some( &*elem )
1052        },
1053        _ => None
1054    }
1055}
1056
1057fn is_bare_ty( ty: &syn::Type, name: &str ) -> bool {
1058    match *ty {
1059        syn::Type::Path( syn::TypePath { path: syn::Path { leading_colon: None, ref segments }, qself: None } ) if segments.len() == 1 => {
1060            segments[ 0 ].ident == name && segments[ 0 ].arguments.is_empty()
1061        },
1062        _ => false
1063    }
1064}
1065
1066fn extract_option_inner_ty( ty: &syn::Type ) -> Option< &syn::Type > {
1067    match *ty {
1068        syn::Type::Path( syn::TypePath { path: syn::Path { leading_colon: None, ref segments }, qself: None } )
1069            if segments.len() == 1 && segments[ 0 ].ident == "Option" =>
1070        {
1071            match segments[ 0 ].arguments {
1072                syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { colon2_token: None, ref args, .. } ) if args.len() == 1 => {
1073                    match args[ 0 ] {
1074                        syn::GenericArgument::Type( ref ty ) => Some( ty ),
1075                        _ => None
1076                    }
1077                },
1078                _ => None
1079            }
1080        },
1081        _ => None
1082    }
1083}
1084
1085fn parse_ty( ty: &syn::Type ) -> Ty {
1086    parse_special_ty( ty ).unwrap_or_else( || Ty::Ty( ty.clone() ) )
1087}
1088
1089fn parse_special_ty( ty: &syn::Type ) -> Option< Ty > {
1090    if let Some( ty ) = parse_primitive_ty( ty ) {
1091        return Some( Ty::Primitive( ty ) );
1092    }
1093
1094    match *ty {
1095        syn::Type::Path( syn::TypePath { path: syn::Path { leading_colon: None, ref segments }, qself: None } ) if segments.len() == 1 => {
1096            let name = &segments[ 0 ].ident;
1097            match segments[ 0 ].arguments {
1098                syn::PathArguments::None => {
1099                    if name == "String" {
1100                        Some( Ty::String )
1101                    } else {
1102                        None
1103                    }
1104                },
1105                syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { colon2_token: None, ref args, .. } ) => {
1106                    if name == "Vec" {
1107                        Some( Ty::Vec( extract_inner_ty( args )?.clone() ) )
1108                    } else if name == "HashSet" {
1109                        Some( Ty::HashSet( extract_inner_ty( args )?.clone() ) )
1110                    } else if name == "BTreeSet" {
1111                        Some( Ty::BTreeSet( extract_inner_ty( args )?.clone() ) )
1112                    } else if name == "Cow" {
1113                        let (lifetime, ty) = extract_lifetime_and_inner_ty( args )?;
1114                        if let Some( inner_ty ) = extract_slice_inner_ty( ty ) {
1115                            Some( Ty::CowSlice( lifetime.clone(), inner_ty.clone() ) )
1116                        } else if is_bare_ty( ty, "str" ) {
1117                            Some( Ty::CowStr( lifetime.clone() ) )
1118                        } else {
1119                            match *ty {
1120                                syn::Type::Path( syn::TypePath { path: syn::Path { leading_colon: None, ref segments }, qself: None } ) if segments.len() == 1 => {
1121                                    let inner_name = &segments[ 0 ].ident;
1122                                    match segments[ 0 ].arguments {
1123                                        syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { colon2_token: None, ref args, .. } ) => {
1124                                            if inner_name == "HashSet" {
1125                                                Some( Ty::CowHashSet( lifetime.clone(), extract_inner_ty( args )?.clone() ) )
1126                                            } else if inner_name == "BTreeSet" {
1127                                                Some( Ty::CowBTreeSet( lifetime.clone(), extract_inner_ty( args )?.clone() ) )
1128                                            } else if inner_name == "HashMap" {
1129                                                let (key_ty, value_ty) = extract_inner_ty_2( args )?;
1130                                                Some( Ty::CowHashMap( lifetime.clone(), key_ty.clone(), value_ty.clone() ) )
1131                                            } else if inner_name == "BTreeMap" {
1132                                                let (key_ty, value_ty) = extract_inner_ty_2( args )?;
1133                                                Some( Ty::CowBTreeMap( lifetime.clone(), key_ty.clone(), value_ty.clone() ) )
1134                                            } else {
1135                                                None
1136                                            }
1137                                        },
1138                                        _ => None
1139                                    }
1140                                },
1141                                _ => None
1142                            }
1143                        }
1144                    } else if name == "HashMap" {
1145                        let (key_ty, value_ty) = extract_inner_ty_2( args )?;
1146                        Some( Ty::HashMap( key_ty.clone(), value_ty.clone() ) )
1147                    } else if name == "BTreeMap" {
1148                        let (key_ty, value_ty) = extract_inner_ty_2( args )?;
1149                        Some( Ty::BTreeMap( key_ty.clone(), value_ty.clone() ) )
1150                    } else {
1151                        None
1152                    }
1153                },
1154                _ => None
1155            }
1156        },
1157        syn::Type::Array( syn::TypeArray {
1158            ref elem,
1159            len: syn::Expr::Lit( syn::ExprLit {
1160                ref attrs,
1161                lit: syn::Lit::Int( ref literal )
1162            }),
1163            ..
1164        }) if attrs.is_empty() => {
1165            if let Ok( length ) = literal.base10_parse::< u32 >() {
1166                Some( Ty::Array( (**elem).clone(), length ) )
1167            } else {
1168                None
1169            }
1170        },
1171        syn::Type::Reference( syn::TypeReference {
1172            lifetime: Some( ref lifetime ),
1173            mutability: None,
1174            ref elem,
1175            ..
1176        }) => {
1177            if is_bare_ty( &*elem, "str" ) {
1178                Some( Ty::RefStr( lifetime.clone() ) )
1179            } else if let Some( inner_ty ) = extract_slice_inner_ty( &*elem ) {
1180                if is_bare_ty( inner_ty, "u8" ) {
1181                    Some( Ty::RefSliceU8( lifetime.clone() ) )
1182                } else {
1183                    Some( Ty::RefSlice( lifetime.clone(), inner_ty.clone() ) )
1184                }
1185            } else {
1186                None
1187            }
1188        },
1189        _ => None
1190    }
1191}
1192
1193fn get_fields< 'a, I: IntoIterator< Item = &'a syn::Field > + 'a >( fields: I ) -> Result< Vec< Field< 'a > >, syn::Error > {
1194    let mut length_until_eof_seen = false;
1195    let iter = fields.into_iter()
1196        .enumerate()
1197        .map( |(index, field)| {
1198            if length_until_eof_seen {
1199                let message = "The field with 'length = ..' has to be the last field; found another field";
1200                return Err( syn::Error::new( field.span(), message ) );
1201            }
1202
1203            let mut default_on_eof = None;
1204            let mut length = None;
1205            let mut length_type = None;
1206            let mut skip = false;
1207            let mut varint = false;
1208            let mut constant_prefix = None;
1209            for attr in parse_attributes::< FieldAttribute >( &field.attrs )? {
1210                match attr {
1211                    FieldAttribute::DefaultOnEof { key_span } => {
1212                        if default_on_eof.is_some() {
1213                            let message = "Duplicate 'default_on_eof'";
1214                            return Err( syn::Error::new( key_span, message ) );
1215                        }
1216
1217                        default_on_eof = Some( key_span );
1218                    }
1219                    FieldAttribute::Length { key_span, length_kind } => {
1220                        if length.is_some() {
1221                            let message = "Duplicate 'length'";
1222                            return Err( syn::Error::new( key_span, message ) );
1223                        }
1224
1225                        if matches!( length_kind, LengthKind::UntilEndOfFile ) {
1226                            length_until_eof_seen = true;
1227                        }
1228
1229                        length = Some( (key_span, length_kind) );
1230                    }
1231                    FieldAttribute::LengthType { key_span, ty } => {
1232                        if length_type.is_some() {
1233                            let message = "Duplicate 'length_type'";
1234                            return Err( syn::Error::new( key_span, message ) );
1235                        }
1236
1237                        length_type = Some( (key_span, ty) );
1238                    },
1239                    FieldAttribute::Skip { key_span: _key_span } => {
1240                        skip = true;
1241                    },
1242                    FieldAttribute::ConstantPrefix { key_span, prefix } => {
1243                        if constant_prefix.is_some() {
1244                            let message = "Duplicate 'constant_prefix'";
1245                            return Err( syn::Error::new( key_span, message ) );
1246                        }
1247                        constant_prefix = Some( prefix );
1248                    },
1249                    FieldAttribute::VarInt { key_span } => {
1250                        if parse_primitive_ty( &field.ty ) != Some( PrimitiveTy::U64 ) {
1251                            let message = "The 'varint' attribute can only be used on fields of type 'u64'";
1252                            return Err( syn::Error::new( key_span, message ) );
1253                        }
1254
1255                        varint = true;
1256                    }
1257                }
1258            }
1259
1260            if let Some( ref value ) = constant_prefix {
1261                if value.value().is_empty() {
1262                    constant_prefix = None;
1263                }
1264            }
1265
1266            if length_type.is_some() && length.is_some() {
1267                let (key_span, _) = length_type.unwrap();
1268                let message = "You cannot have both 'length_type' and 'length' on the same field";
1269                return Err( syn::Error::new( key_span, message ) );
1270            }
1271
1272            let ty = if let Some( ty ) = extract_option_inner_ty( &field.ty ) {
1273                Opt::Option( parse_ty( ty ) )
1274            } else {
1275                Opt::Plain( parse_ty( &field.ty ) )
1276            };
1277
1278            if length.is_some() {
1279                match ty {
1280                    | Opt::Plain( Ty::String )
1281                    | Opt::Plain( Ty::Vec( .. ) )
1282                    | Opt::Plain( Ty::CowSlice( .. ) )
1283                    | Opt::Plain( Ty::CowStr( .. ) )
1284                    | Opt::Plain( Ty::HashMap( .. ) )
1285                    | Opt::Plain( Ty::HashSet( .. ) )
1286                    | Opt::Plain( Ty::BTreeMap( .. ) )
1287                    | Opt::Plain( Ty::BTreeSet( .. ) )
1288                    | Opt::Plain( Ty::CowHashMap( .. ) )
1289                    | Opt::Plain( Ty::CowHashSet( .. ) )
1290                    | Opt::Plain( Ty::CowBTreeMap( .. ) )
1291                    | Opt::Plain( Ty::CowBTreeSet( .. ) )
1292                    | Opt::Plain( Ty::RefSliceU8( .. ) )
1293                    | Opt::Plain( Ty::RefSlice( .. ) )
1294                    | Opt::Plain( Ty::RefStr( .. ) )
1295                        => {},
1296
1297                    | Opt::Option( Ty::String )
1298                    | Opt::Option( Ty::Vec( .. ) )
1299                    | Opt::Option( Ty::CowSlice( .. ) )
1300                    | Opt::Option( Ty::CowStr( .. ) )
1301                    | Opt::Option( Ty::HashMap( .. ) )
1302                    | Opt::Option( Ty::HashSet( .. ) )
1303                    | Opt::Option( Ty::BTreeMap( .. ) )
1304                    | Opt::Option( Ty::BTreeSet( .. ) )
1305                    | Opt::Option( Ty::CowHashMap( .. ) )
1306                    | Opt::Option( Ty::CowHashSet( .. ) )
1307                    | Opt::Option( Ty::CowBTreeMap( .. ) )
1308                    | Opt::Option( Ty::CowBTreeSet( .. ) )
1309                    | Opt::Option( Ty::RefSliceU8( .. ) )
1310                    | Opt::Option( Ty::RefSlice( .. ) )
1311                    | Opt::Option( Ty::RefStr( .. ) )
1312                    | Opt::Plain( Ty::Array( .. ) )
1313                    | Opt::Option( Ty::Array( .. ) )
1314                    | Opt::Plain( Ty::Primitive( .. ) )
1315                    | Opt::Option( Ty::Primitive( .. ) )
1316                    | Opt::Plain( Ty::Ty( .. ) )
1317                    | Opt::Option( Ty::Ty( .. ) )
1318                    => {
1319                        return Err(
1320                            syn::Error::new(
1321                                field.ty.span(),
1322                                "The 'length' attribute is only supported for `Vec`, `String`, `Cow<[_]>`, `Cow<str>`, `HashMap`, `HashSet`, `BTreeMap`, `BTreeSet`, `Cow<HashMap>`, `Cow<HashSet>`, `Cow<BTreeMap>`, `Cow<BTreeSet>`, `&[u8]`, `&str`"
1323                            )
1324                        );
1325                    }
1326                }
1327            }
1328
1329            if length_type.is_some() {
1330                match ty {
1331                    | Opt::Plain( Ty::String )
1332                    | Opt::Plain( Ty::Vec( .. ) )
1333                    | Opt::Plain( Ty::CowSlice( .. ) )
1334                    | Opt::Plain( Ty::CowStr( .. ) )
1335                    | Opt::Plain( Ty::HashMap( .. ) )
1336                    | Opt::Plain( Ty::HashSet( .. ) )
1337                    | Opt::Plain( Ty::BTreeMap( .. ) )
1338                    | Opt::Plain( Ty::BTreeSet( .. ) )
1339                    | Opt::Plain( Ty::CowHashMap( .. ) )
1340                    | Opt::Plain( Ty::CowHashSet( .. ) )
1341                    | Opt::Plain( Ty::CowBTreeMap( .. ) )
1342                    | Opt::Plain( Ty::CowBTreeSet( .. ) )
1343                    | Opt::Plain( Ty::RefSliceU8( .. ) )
1344                    | Opt::Plain( Ty::RefSlice( .. ) )
1345                    | Opt::Plain( Ty::RefStr( .. ) )
1346                    | Opt::Option( Ty::String )
1347                    | Opt::Option( Ty::Vec( .. ) )
1348                    | Opt::Option( Ty::CowSlice( .. ) )
1349                    | Opt::Option( Ty::CowStr( .. ) )
1350                    | Opt::Option( Ty::HashMap( .. ) )
1351                    | Opt::Option( Ty::HashSet( .. ) )
1352                    | Opt::Option( Ty::BTreeMap( .. ) )
1353                    | Opt::Option( Ty::BTreeSet( .. ) )
1354                    | Opt::Option( Ty::CowHashMap( .. ) )
1355                    | Opt::Option( Ty::CowHashSet( .. ) )
1356                    | Opt::Option( Ty::CowBTreeMap( .. ) )
1357                    | Opt::Option( Ty::CowBTreeSet( .. ) )
1358                    | Opt::Option( Ty::RefSliceU8( .. ) )
1359                    | Opt::Option( Ty::RefSlice( .. ) )
1360                    | Opt::Option( Ty::RefStr( .. ) )
1361                        => {},
1362
1363                    | Opt::Plain( Ty::Array( .. ) )
1364                    | Opt::Option( Ty::Array( .. ) )
1365                    | Opt::Plain( Ty::Primitive( .. ) )
1366                    | Opt::Option( Ty::Primitive( .. ) )
1367                    | Opt::Plain( Ty::Ty( .. ) )
1368                    | Opt::Option( Ty::Ty( .. ) )
1369                    => {
1370                        return Err(
1371                            syn::Error::new(
1372                                field.ty.span(),
1373                                "The 'length_type' attribute is only supported for `Vec`, `String`, `Cow<[_]>`, `Cow<str>`, `HashMap`, `HashSet`, `BTreeMap`, `BTreeSet`, `Cow<HashMap>`, `Cow<HashSet>`, `Cow<BTreeMap>`, `Cow<BTreeSet>`, `&[u8]`, `&str` and for `Option<T>` where `T` is one of these types"
1374                            )
1375                        );
1376                    }
1377                }
1378            }
1379
1380            fn snd< T, U >( (_, b): (T, U) ) -> U {
1381                b
1382            }
1383
1384            Ok( Field {
1385                index,
1386                name: field.ident.as_ref(),
1387                raw_ty: &field.ty,
1388                default_on_eof: default_on_eof.is_some(),
1389                length: length.map( snd ),
1390                length_type: length_type.map( snd ),
1391                ty,
1392                skip,
1393                varint,
1394                constant_prefix
1395            })
1396        });
1397
1398    iter.collect()
1399}
1400
1401fn default_on_eof_body( body: TokenStream ) -> TokenStream {
1402    quote! {
1403        match #body {
1404            Ok( value ) => value,
1405            Err( ref error ) if speedy::IsEof::is_eof( error ) => std::default::Default::default(),
1406            Err( error ) => return Err( error )
1407        }
1408    }
1409}
1410
1411fn read_field_body( field: &Field ) -> TokenStream {
1412    if field.skip {
1413        return quote! {
1414            std::default::Default::default()
1415        };
1416    }
1417
1418    let read_length_body = match field.length {
1419        Some( LengthKind::Expr( ref length ) ) => Some( quote! { ((#length) as usize) } ),
1420        Some( LengthKind::UntilEndOfFile ) => None,
1421        None => {
1422            let read_length_fn = match field.length_type.unwrap_or( DEFAULT_LENGTH_TYPE ) {
1423                BasicType::U7 => quote! { read_length_u7 },
1424                BasicType::U8 => quote! { read_length_u8 },
1425                BasicType::U16 => quote! { read_length_u16 },
1426                BasicType::U32 => quote! { read_length_u32 },
1427                BasicType::U64 => quote! { read_length_u64 },
1428                BasicType::VarInt64 => quote! { read_length_u64_varint },
1429            };
1430
1431            let body = quote! {
1432                speedy::private::#read_length_fn( _reader_ )
1433            };
1434
1435            if field.default_on_eof {
1436                Some( default_on_eof_body( body ) )
1437            } else {
1438                Some( quote! { #body? } )
1439            }
1440        }
1441    };
1442
1443    let read_string = || {
1444        if let Some( ref read_length_body ) = read_length_body {
1445            quote! {{
1446                let _length_ = #read_length_body;
1447                _reader_.read_vec( _length_ ).and_then( speedy::private::vec_to_string )
1448            }}
1449        } else {
1450            quote! {{
1451                _reader_.read_vec_until_eof().and_then( speedy::private::vec_to_string )
1452            }}
1453        }
1454    };
1455
1456    let read_vec = || {
1457        if let Some( ref read_length_body ) = read_length_body {
1458            quote! {{
1459                let _length_ = #read_length_body;
1460                _reader_.read_vec( _length_ )
1461            }}
1462        } else {
1463            quote! {{
1464                _reader_.read_vec_until_eof()
1465            }}
1466        }
1467    };
1468
1469    let read_cow_slice = || {
1470        if let Some( ref read_length_body ) = read_length_body {
1471            quote! {{
1472                let _length_ = #read_length_body;
1473                _reader_.read_cow( _length_ )
1474            }}
1475        } else {
1476            quote! {{
1477                _reader_.read_cow_until_eof()
1478            }}
1479        }
1480    };
1481
1482    let read_cow_str = || {
1483        if let Some( ref read_length_body ) = read_length_body {
1484            quote! {{
1485                let _length_ = #read_length_body;
1486                _reader_.read_cow( _length_ ).and_then( speedy::private::cow_bytes_to_cow_str )
1487            }}
1488        } else {
1489            quote! {{
1490                _reader_.read_cow_until_eof().and_then( speedy::private::cow_bytes_to_cow_str )
1491            }}
1492        }
1493    };
1494
1495    let read_collection = || {
1496        if let Some( ref read_length_body ) = read_length_body {
1497            quote! {{
1498                let _length_ = #read_length_body;
1499                _reader_.read_collection( _length_ )
1500            }}
1501        } else {
1502            quote! {{
1503                _reader_.read_collection_until_eof()
1504            }}
1505        }
1506    };
1507
1508    let read_key_value_collection = || {
1509        if let Some( ref read_length_body ) = read_length_body {
1510            quote! {{
1511                let _length_ = #read_length_body;
1512                _reader_.read_key_value_collection( _length_ )
1513            }}
1514        } else {
1515            quote! {{
1516                _reader_.read_collection_until_eof()
1517            }}
1518        }
1519    };
1520
1521    let read_cow_collection = || {
1522        if let Some( ref read_length_body ) = read_length_body {
1523            quote! {{
1524                let _length_ = #read_length_body;
1525                _reader_.read_collection( _length_ ).map( std::borrow::Cow::Owned )
1526            }}
1527        } else {
1528            quote! {{
1529                _reader_.read_collection_until_eof().map( std::borrow::Cow::Owned )
1530            }}
1531        }
1532    };
1533
1534    let read_cow_key_value_collection = || {
1535        if let Some( ref read_length_body ) = read_length_body {
1536            quote! {{
1537                let _length_ = #read_length_body;
1538                _reader_.read_key_value_collection( _length_ ).map( std::borrow::Cow::Owned )
1539            }}
1540        } else {
1541            quote! {{
1542                _reader_.read_collection_until_eof().map( std::borrow::Cow::Owned )
1543            }}
1544        }
1545    };
1546
1547    let read_ref_slice_u8 = || {
1548        if let Some( ref read_length_body ) = read_length_body {
1549            quote! {{
1550                let _length_ = #read_length_body;
1551                _reader_.read_bytes_borrowed( _length_ ).ok_or_else( speedy::private::error_unsized ).and_then( |error| error )
1552            }}
1553        } else {
1554            quote! {{
1555                _reader_.read_bytes_borrowed_until_eof().ok_or_else( speedy::private::error_unsized )
1556            }}
1557        }
1558    };
1559
1560    let read_ref_str = || {
1561        if let Some( ref read_length_body ) = read_length_body {
1562            quote! {{
1563                let _length_ = #read_length_body;
1564                match _reader_.read_bytes_borrowed( _length_ ) {
1565                    Some( Ok( bytes ) ) => std::str::from_utf8( bytes ).map_err( speedy::private::error_invalid_str_utf8 ),
1566                    Some( Err( error ) ) => Err( error ),
1567                    None => Err( speedy::private::error_unsized() )
1568                }
1569            }}
1570        } else {
1571            quote! {{
1572                match _reader_.read_bytes_borrowed_until_eof() {
1573                    Some( bytes ) => std::str::from_utf8( bytes ).map_err( speedy::private::error_invalid_str_utf8 ),
1574                    None => Err( speedy::private::error_unsized() )
1575                }
1576            }}
1577        }
1578    };
1579
1580    let read_ref_slice = |inner_ty: &syn::Type| {
1581        let inner;
1582        if let Some( ref read_length_body ) = read_length_body {
1583            inner = quote! {{
1584                let _length_ = #read_length_body;
1585                _length_.checked_mul( std::mem::size_of::< #inner_ty >() )
1586                    .ok_or_else( speedy::private::error_out_of_range_length )
1587                    .and_then( |bytelength| {
1588                        _reader_.read_bytes_borrowed( bytelength )
1589                            .ok_or_else( speedy::private::error_unsized )
1590                            .and_then( |error| error )
1591                    })
1592                    .map( |slice| unsafe { std::slice::from_raw_parts( slice.as_ptr() as *const #inner_ty, _length_ ) } )
1593            }}
1594        } else {
1595            inner = quote! {{
1596                _reader_.read_bytes_borrowed_until_eof()
1597                    .ok_or_else( speedy::private::error_unsized )
1598                    .map( |slice| unsafe {
1599                        std::slice::from_raw_parts( slice.as_ptr() as *const #inner_ty, slice.len() / std::mem::size_of::< #inner_ty >() )
1600                    })
1601            }}
1602        }
1603
1604        quote! {{
1605            if std::mem::size_of::< #inner_ty >() != 1 && _reader_.endianness().conversion_necessary() {
1606                Err( speedy::private::error_endianness_mismatch() )
1607            } else {
1608                #inner
1609            }
1610        }}
1611    };
1612
1613    let read_array = |length: u32| {
1614        // TODO: This is quite inefficient; for primitive types we can do better.
1615        let readers = (0..length).map( |_| quote! {
1616            match _reader_.read_value() {
1617                Ok( value ) => value,
1618                Err( error ) => return Err( error )
1619            }
1620        });
1621
1622        quote! { (|| { Ok([
1623            #(#readers),*
1624        ])})() }
1625    };
1626
1627    let read_u64_varint = || {
1628        quote! {{
1629            _reader_.read_u64_varint()
1630        }}
1631    };
1632
1633    let read_option = |tokens: TokenStream|
1634        quote! {{
1635            _reader_.read_u8().and_then( |_flag_| {
1636                if _flag_ != 0 {
1637                    Ok( Some( #tokens? ) )
1638                } else {
1639                    Ok( None )
1640                }
1641            })
1642        }};
1643
1644    let body = match field.ty.inner() {
1645        Ty::String => read_string(),
1646        Ty::Vec( .. ) => read_vec(),
1647        Ty::CowSlice( .. ) => read_cow_slice(),
1648        Ty::CowStr( .. ) => read_cow_str(),
1649        Ty::HashMap( .. ) |
1650        Ty::BTreeMap( .. )  => read_key_value_collection(),
1651        Ty::HashSet( .. ) |
1652        Ty::BTreeSet( .. ) => read_collection(),
1653        Ty::CowHashMap( .. ) |
1654        Ty::CowBTreeMap( .. ) => read_cow_key_value_collection(),
1655        Ty::CowHashSet( .. ) |
1656        Ty::CowBTreeSet( .. ) => read_cow_collection(),
1657        Ty::RefSliceU8( .. ) => read_ref_slice_u8(),
1658        Ty::RefSlice( _, inner_ty ) => read_ref_slice( inner_ty ),
1659        Ty::RefStr( .. ) => read_ref_str(),
1660        Ty::Array( _, length ) => read_array( *length ),
1661        Ty::Primitive( .. ) if field.varint => read_u64_varint(),
1662        Ty::Primitive( .. ) |
1663        Ty::Ty( .. ) => {
1664            assert!( field.length.is_none() );
1665            quote! { _reader_.read_value() }
1666        }
1667    };
1668
1669    let body = match field.ty {
1670        Opt::Plain( _ ) => body,
1671        Opt::Option( _ ) => read_option( body )
1672    };
1673
1674    let body = if let Some( ref constant_prefix ) = field.constant_prefix {
1675        quote! {{
1676            speedy::private::read_constant( _reader_, #constant_prefix ).and_then( |_| #body )
1677        }}
1678    } else {
1679        body
1680    };
1681
1682    if field.default_on_eof {
1683        default_on_eof_body( body )
1684    } else {
1685        quote! { #body? }
1686    }
1687}
1688
1689fn readable_body< 'a >( types: &mut Vec< syn::Type >, st: &Struct< 'a > ) -> (TokenStream, TokenStream, TokenStream) {
1690    let mut field_names = Vec::new();
1691    let mut field_readers = Vec::new();
1692    let mut minimum_bytes_needed = Vec::new();
1693    for field in &st.fields {
1694        let read_value = read_field_body( field );
1695        let name = field.var_name();
1696        let raw_ty = field.raw_ty;
1697        field_readers.push( quote! { let #name: #raw_ty = #read_value; } );
1698        field_names.push( name );
1699        types.extend( field.bound_types() );
1700
1701        if let Some( minimum_bytes ) = get_minimum_bytes( &field ) {
1702            minimum_bytes_needed.push( minimum_bytes );
1703        }
1704    }
1705
1706    let body = quote! { #(#field_readers)* };
1707    let initializer = quote! { #(#field_names),* };
1708    let initializer = match st.kind {
1709        StructKind::Unit => initializer,
1710        StructKind::Unnamed => quote! { ( #initializer ) },
1711        StructKind::Named => quote! { { #initializer } }
1712    };
1713
1714    let minimum_bytes_needed = sum( minimum_bytes_needed );
1715    (body, initializer, minimum_bytes_needed)
1716}
1717
1718fn write_field_body( field: &Field ) -> TokenStream {
1719    let name = field.var_name();
1720    let write_length_body = match field.length {
1721        Some( LengthKind::Expr( ref length ) ) => {
1722            let field_name = format!( "{}", name );
1723            quote! {
1724                if !speedy::private::are_lengths_the_same( #name.len(), #length ) {
1725                    return Err( speedy::private::error_length_is_not_the_same_as_length_attribute( #field_name ) );
1726                }
1727            }
1728        },
1729        Some( LengthKind::UntilEndOfFile ) => quote! {},
1730        None => {
1731            let write_length_fn = match field.length_type.unwrap_or( DEFAULT_LENGTH_TYPE ) {
1732                BasicType::U7 => quote! { write_length_u7 },
1733                BasicType::U8 => quote! { write_length_u8 },
1734                BasicType::U16 => quote! { write_length_u16 },
1735                BasicType::U32 => quote! { write_length_u32 },
1736                BasicType::U64 => quote! { write_length_u64 },
1737                BasicType::VarInt64 => quote! { write_length_u64_varint }
1738            };
1739
1740            quote! { speedy::private::#write_length_fn( #name.len(), _writer_ )?; }
1741        }
1742    };
1743
1744    let write_str = ||
1745        quote! {{
1746            #write_length_body
1747            _writer_.write_slice( #name.as_bytes() )?;
1748        }};
1749
1750    let write_slice = ||
1751        quote! {{
1752            #write_length_body
1753            _writer_.write_slice( &#name )?;
1754        }};
1755
1756    let write_collection = ||
1757        quote! {{
1758            #write_length_body
1759            _writer_.write_collection( #name.iter() )?;
1760        }};
1761
1762    let write_array = ||
1763        quote! {{
1764            _writer_.write_slice( &#name[..] )?;
1765        }};
1766
1767    let write_u64_varint = ||
1768        quote! {{
1769            _writer_.write_u64_varint( *#name )?;
1770        }};
1771
1772    let write_option = |tokens: TokenStream|
1773        quote! {{
1774            if let Some( ref #name ) = #name {
1775                _writer_.write_u8( 1 )?;
1776                #tokens
1777            } else {
1778                _writer_.write_u8( 0 )?;
1779            }
1780        }};
1781
1782    let body = match field.ty.inner() {
1783        Ty::String |
1784        Ty::CowStr( .. ) |
1785        Ty::RefStr( .. )
1786            => write_str(),
1787        Ty::Vec( .. ) |
1788        Ty::CowSlice( .. ) |
1789        Ty::RefSliceU8( .. ) |
1790        Ty::RefSlice( .. )
1791            => write_slice(),
1792        Ty::HashMap( .. ) |
1793        Ty::HashSet( .. ) |
1794        Ty::BTreeMap( .. ) |
1795        Ty::BTreeSet( .. ) |
1796        Ty::CowHashMap( .. ) |
1797        Ty::CowHashSet( .. ) |
1798        Ty::CowBTreeMap( .. ) |
1799        Ty::CowBTreeSet( .. ) => write_collection(),
1800        Ty::Array( .. ) => write_array(),
1801        Ty::Primitive( .. ) if field.varint => write_u64_varint(),
1802        Ty::Primitive( .. ) |
1803        Ty::Ty( .. ) => {
1804            assert!( field.length.is_none() );
1805            quote! { _writer_.write_value( #name )?; }
1806        }
1807    };
1808
1809    let body = match field.ty {
1810        Opt::Plain( _ ) => body,
1811        Opt::Option( _ ) => write_option( body )
1812    };
1813
1814    let body = if let Some( ref constant_prefix ) = field.constant_prefix {
1815        quote! {{
1816            _writer_.write_slice( #constant_prefix )?;
1817            #body
1818        }}
1819    } else {
1820        body
1821    };
1822
1823    body
1824}
1825
1826fn writable_body< 'a >( types: &mut Vec< syn::Type >, st: &Struct< 'a > ) -> (TokenStream, TokenStream) {
1827    let mut field_names = Vec::new();
1828    let mut field_writers = Vec::new();
1829    for field in &st.fields {
1830        if field.skip {
1831            continue;
1832        }
1833
1834        let write_value = write_field_body( &field );
1835        types.extend( field.bound_types() );
1836
1837        field_names.push( field.var_name().clone() );
1838        field_writers.push( write_value );
1839    }
1840
1841    let body = quote! { #(#field_writers)* };
1842    let initializer = quote! { #(ref #field_names),* };
1843    let initializer = match st.kind {
1844        StructKind::Unit => initializer,
1845        StructKind::Unnamed => quote! { ( #initializer ) },
1846        StructKind::Named => quote! { { #initializer } }
1847    };
1848
1849    (body, initializer)
1850}
1851
1852struct Variant< 'a > {
1853    tag_expr: TokenStream,
1854    ident: &'a syn::Ident,
1855    structure: Struct< 'a >
1856}
1857
1858struct Enum< 'a > {
1859    tag_type: BasicType,
1860    peek_tag: bool,
1861    variants: Vec< Variant< 'a > >
1862}
1863
1864impl< 'a > Enum< 'a > {
1865    fn new(
1866        ident: &syn::Ident,
1867        attrs: &[syn::Attribute],
1868        raw_variants: &'a Punctuated< syn::Variant, syn::token::Comma >
1869    ) -> Result< Self, syn::Error > {
1870        let attrs = parse_attributes::< EnumAttribute >( attrs )?;
1871        let attrs = collect_enum_attributes( attrs )?;
1872        let tag_type = attrs.tag_type.unwrap_or( DEFAULT_ENUM_TAG_TYPE );
1873        let max = match tag_type {
1874            BasicType::U7 => 0b01111111 as u64,
1875            BasicType::U8 => std::u8::MAX as u64,
1876            BasicType::U16 => std::u16::MAX as u64,
1877            BasicType::U32 => std::u32::MAX as u64,
1878            BasicType::U64 => std::u64::MAX,
1879            BasicType::VarInt64 => std::u64::MAX
1880        };
1881
1882        let mut previous_tag = None;
1883        let mut tag_to_full_name = HashMap::new();
1884        let mut variants = Vec::new();
1885        for variant in raw_variants {
1886            let mut struct_attrs = Vec::new();
1887            let mut variant_attrs = Vec::new();
1888            for attr in parse_attributes::< VariantOrStructAttribute >( &variant.attrs )? {
1889                match attr {
1890                    VariantOrStructAttribute::Struct( attr ) => struct_attrs.push( attr ),
1891                    VariantOrStructAttribute::Variant( attr ) => variant_attrs.push( attr )
1892                }
1893            }
1894
1895            let variant_attrs = collect_variant_attributes( variant_attrs )?;
1896
1897            let full_name = format!( "{}::{}", ident, variant.ident );
1898            let tag = if let Some( tag ) = variant_attrs.tag {
1899                if tag > max {
1900                    let message = format!( "Enum discriminant `{}` is too big!", full_name );
1901                    return Err( syn::Error::new( variant.span(), message ) );
1902                }
1903                tag
1904            } else {
1905                match variant.discriminant {
1906                    None => {
1907                        let tag = if let Some( previous_tag ) = previous_tag {
1908                            if previous_tag >= max {
1909                                let message = format!( "Enum discriminant `{}` is too big!", full_name );
1910                                return Err( syn::Error::new( variant.span(), message ) );
1911                            }
1912
1913                            previous_tag + 1
1914                        } else {
1915                            0
1916                        };
1917
1918                        tag
1919                    },
1920                    Some( (_, syn::Expr::Lit( syn::ExprLit { lit: syn::Lit::Int( ref raw_value ), .. } )) ) => {
1921                        let tag = raw_value.base10_parse::< u64 >().map_err( |err| {
1922                            syn::Error::new( raw_value.span(), err )
1923                        })?;
1924                        if tag > max {
1925                            let message = format!( "Enum discriminant `{}` is too big!", full_name );
1926                            return Err( syn::Error::new( raw_value.span(), message ) );
1927                        }
1928
1929                        tag
1930                    },
1931                    Some((_, ref expr)) => {
1932                        let message = format!( "Enum discriminant `{}` is currently unsupported!", full_name );
1933                        return Err( syn::Error::new( expr.span(), message ) );
1934                    }
1935                }
1936            };
1937
1938            previous_tag = Some( tag );
1939            if let Some( other_full_name ) = tag_to_full_name.get( &tag ) {
1940                let message = format!( "Two discriminants with the same value of '{}': `{}`, `{}`", tag, full_name, other_full_name );
1941                return Err( syn::Error::new( variant.span(), message ) );
1942            }
1943
1944            tag_to_full_name.insert( tag, full_name );
1945            let tag_expr = match tag_type {
1946                BasicType::U7 | BasicType::U8 => {
1947                    let tag = tag as u8;
1948                    quote! { #tag }
1949                },
1950                BasicType::U16 => {
1951                    let tag = tag as u16;
1952                    quote! { #tag }
1953                },
1954                BasicType::U32 => {
1955                    let tag = tag as u32;
1956                    quote! { #tag }
1957                },
1958                BasicType::U64 | BasicType::VarInt64 => {
1959                    let tag = tag as u64;
1960                    quote! { #tag }
1961                }
1962            };
1963
1964            let struct_attrs = collect_struct_attributes( struct_attrs )?;
1965            let structure = Struct::new( &variant.fields, &struct_attrs )?;
1966            variants.push( Variant {
1967                tag_expr,
1968                ident: &variant.ident,
1969                structure
1970            });
1971        }
1972
1973        Ok( Enum {
1974            tag_type,
1975            peek_tag: attrs.peek_tag,
1976            variants
1977        })
1978    }
1979}
1980
1981fn get_minimum_bytes( field: &Field ) -> Option< TokenStream > {
1982    if field.default_on_eof || field.length.is_some() || field.skip {
1983        None
1984    } else {
1985        let mut length = match field.ty {
1986            Opt::Option( .. ) => {
1987                quote! { 1 }
1988            },
1989            Opt::Plain( ref ty ) => {
1990                match ty {
1991                    | Ty::String
1992                    | Ty::Vec( .. )
1993                    | Ty::CowSlice( .. )
1994                    | Ty::CowStr( .. )
1995                    | Ty::HashMap( .. )
1996                    | Ty::HashSet( .. )
1997                    | Ty::BTreeMap( .. )
1998                    | Ty::BTreeSet( .. )
1999                    | Ty::CowHashMap( .. )
2000                    | Ty::CowHashSet( .. )
2001                    | Ty::CowBTreeMap( .. )
2002                    | Ty::CowBTreeSet( .. )
2003                    | Ty::RefSliceU8( .. )
2004                    | Ty::RefSlice( .. )
2005                    | Ty::RefStr( .. )
2006                    => {
2007                        let size: usize = match field.length_type.unwrap_or( DEFAULT_LENGTH_TYPE ) {
2008                            BasicType::U7 | BasicType::U8 | BasicType::VarInt64 => 1,
2009                            BasicType::U16 => 2,
2010                            BasicType::U32 => 4,
2011                            BasicType::U64 => 8
2012                        };
2013
2014                        quote! { #size }
2015                    },
2016                    | Ty::Array( ty, length ) => {
2017                        let length = *length as usize;
2018                        quote! { <#ty as speedy::Readable< 'a_, C_ >>::minimum_bytes_needed() * #length }
2019                    },
2020                    | Ty::Primitive( .. ) if field.varint => quote! { 1 },
2021                    | Ty::Primitive( .. )
2022                    | Ty::Ty( .. ) => {
2023                        let raw_ty = &field.raw_ty;
2024                        quote! { <#raw_ty as speedy::Readable< 'a_, C_ >>::minimum_bytes_needed() }
2025                    }
2026                }
2027            }
2028        };
2029
2030        if let Some( ref constant_prefix ) = field.constant_prefix {
2031            let extra_length = constant_prefix.value().len();
2032            length = quote! { #length + #extra_length };
2033        }
2034
2035        Some( length )
2036    }
2037}
2038
2039fn sum< I >( values: I ) -> TokenStream where I: IntoIterator< Item = TokenStream >, <I as IntoIterator>::IntoIter: ExactSizeIterator {
2040    let iter = values.into_iter();
2041    if iter.len() == 0 {
2042        quote! { 0 }
2043    } else {
2044        quote! {{
2045            let mut out = 0;
2046            #(out += #iter;)*
2047            out
2048        }}
2049    }
2050}
2051
2052fn min< I >( values: I ) -> TokenStream where I: IntoIterator< Item = TokenStream >, <I as IntoIterator>::IntoIter: ExactSizeIterator {
2053    let iter = values.into_iter();
2054    if iter.len() == 0 {
2055        quote! { 0 }
2056    } else {
2057        quote! {{
2058            let mut out = 0;
2059            #(out = std::cmp::min( out, #iter );)*
2060            out
2061        }}
2062    }
2063}
2064
2065fn generate_is_primitive( fields: &[Field], is_writable: bool, check_order: bool, is_forced: bool ) -> TokenStream {
2066    if fields.is_empty() || is_forced {
2067        return quote! { true };
2068    }
2069
2070    let mut is_primitive = Vec::new();
2071    let mut fields_size = Vec::new();
2072    let mut fields_offsets = Vec::new();
2073    for field in fields {
2074        if !is_primitive.is_empty() {
2075            is_primitive.push( quote! { && });
2076            fields_size.push( quote! { + });
2077        }
2078
2079        let ty = &field.raw_ty;
2080        if is_writable {
2081            is_primitive.push( quote! {
2082                <#ty as speedy::Writable< C_ >>::speedy_is_primitive()
2083            });
2084        } else {
2085            is_primitive.push( quote! {
2086                <#ty as speedy::Readable< 'a_, C_ >>::speedy_is_primitive()
2087            });
2088        }
2089
2090        fields_size.push( quote! {
2091            std::mem::size_of::< #ty >()
2092        });
2093
2094        let name = field.name();
2095        fields_offsets.push( quote! {
2096            speedy::private::offset_of!( Self, #name )
2097        });
2098    }
2099
2100    is_primitive.push( quote! {
2101        && (#(#fields_size)*) == std::mem::size_of::< Self >()
2102    });
2103
2104    if check_order {
2105        for window in fields_offsets.windows( 2 ) {
2106            let a = &window[0];
2107            let b = &window[1];
2108            is_primitive.push( quote! {
2109                && #a <= #b
2110            });
2111        }
2112    }
2113
2114    quote! {
2115        #(#is_primitive)*
2116    }
2117}
2118
2119struct IsPrimitiveResult {
2120    is_ty_packed: bool,
2121    is_ty_transparent: bool,
2122    is_ty_potentially_primitive: bool,
2123    check_order: bool,
2124    impl_zerocopyable: bool,
2125    is_forced: bool
2126}
2127
2128fn check_is_primitive( input: &syn::DeriveInput, structure: &Struct, attrs: &ToplevelStructAttributes ) -> IsPrimitiveResult {
2129    let is_ty_packed = is_packed( &input.attrs );
2130    let is_ty_transparent = structure.fields.len() == 1 && is_transparent( &input.attrs );
2131    let is_ty_c = is_c( &input.attrs );
2132    let is_ty_simple = structure.fields.iter().all( |field| field.is_simple() );
2133    let check_order = !is_ty_transparent && !is_ty_packed && !is_ty_c;
2134
2135    let mut is_forced = false;
2136    match attrs.is_primitive {
2137        None => {},
2138        Some( IsPrimitive::Always ) => {
2139            is_forced = true;
2140        }
2141    }
2142
2143    let can_be_primitive = is_forced || structure.fields.iter().all( |field| field.can_be_primitive() );
2144    IsPrimitiveResult {
2145        is_ty_packed,
2146        is_ty_transparent,
2147        is_ty_potentially_primitive: can_be_primitive && (is_forced || is_ty_transparent || is_ty_packed || is_ty_c || is_ty_simple || (!uses_generics( &input ) && structure.fields.len() <= 4)),
2148        check_order,
2149        impl_zerocopyable: is_ty_packed || is_ty_transparent || is_forced,
2150        is_forced
2151    }
2152}
2153
2154fn impl_readable( input: syn::DeriveInput ) -> Result< TokenStream, syn::Error > {
2155    let name = &input.ident;
2156    let mut types = Vec::new();
2157
2158    let (reader_body, minimum_bytes_needed_body, impl_primitive, impl_zerocopyable) = match &input.data {
2159        syn::Data::Struct( syn::DataStruct { ref fields, .. } ) => {
2160            let attrs = parse_attributes::< ToplevelStructAttribute >( &input.attrs )?;
2161            let attrs = collect_toplevel_struct_attributes( attrs )?;
2162            let structure = Struct::new( fields, &attrs )?;
2163            let is_primitive = check_is_primitive( &input, &structure, &attrs );
2164            let (body, initializer, minimum_bytes) = readable_body( &mut types, &structure );
2165            let reader_body = quote! {
2166                #body
2167                Ok( #name #initializer )
2168            };
2169
2170            let mut field_types = Vec::new();
2171            for field in &structure.fields {
2172                field_types.push( field.raw_ty.clone() );
2173            }
2174
2175            let impl_primitive = if is_primitive.is_ty_transparent {
2176                let field_ty = &structure.fields[ 0 ].raw_ty;
2177                quote! {
2178                    #[inline(always)]
2179                    fn speedy_is_primitive() -> bool {
2180                        <#field_ty as speedy::Readable< 'a_, C_ >>::speedy_is_primitive()
2181                    }
2182
2183                    #[inline]
2184                    unsafe fn speedy_slice_from_bytes( slice: &[u8] ) -> &[Self] {
2185                        let slice = <#field_ty as speedy::Readable< 'a_, C_ >>::speedy_slice_from_bytes( slice );
2186                        std::slice::from_raw_parts( slice.as_ptr() as *const Self, slice.len() )
2187                    }
2188
2189                    #[inline(always)]
2190                    fn speedy_convert_slice_endianness( endianness: speedy::Endianness, slice: &mut [Self] ) {
2191                        unsafe {
2192                            let slice = std::slice::from_raw_parts_mut( slice.as_mut_ptr() as *mut #field_ty, slice.len() );
2193                            <#field_ty as speedy::Readable< 'a_, C_ >>::speedy_convert_slice_endianness( endianness, slice )
2194                        }
2195                    }
2196                }
2197            } else if is_primitive.is_ty_potentially_primitive {
2198                let is_primitive = generate_is_primitive( &structure.fields, false, is_primitive.check_order, is_primitive.is_forced );
2199                let mut body_flip_endianness = Vec::new();
2200                for field in &structure.fields {
2201                    let ty = &field.raw_ty;
2202                    let name = field.name();
2203
2204                    body_flip_endianness.push( quote! {
2205                        unsafe {
2206                            <#ty as speedy::Readable< 'a_, C_ >>::speedy_flip_endianness(
2207                                std::ptr::addr_of_mut!( (*itself).#name )
2208                            );
2209                        }
2210                    });
2211                }
2212
2213                quote! {
2214                    #[inline(always)]
2215                    fn speedy_is_primitive() -> bool {
2216                        #is_primitive
2217                    }
2218
2219                    #[inline]
2220                    unsafe fn speedy_slice_from_bytes( slice: &[u8] ) -> &[Self] {
2221                        unsafe {
2222                            std::slice::from_raw_parts( slice.as_ptr() as *const Self, slice.len() / std::mem::size_of::< Self >() )
2223                        }
2224                    }
2225
2226                    #[inline(always)]
2227                    unsafe fn speedy_flip_endianness( itself: *mut Self ) {
2228                        unsafe {
2229                            #(#body_flip_endianness)*
2230                        }
2231                    }
2232
2233                    #[inline(always)]
2234                    fn speedy_convert_slice_endianness( endianness: speedy::Endianness, slice: &mut [Self] ) {
2235                        if endianness.conversion_necessary() {
2236                            for value in slice {
2237                                unsafe {
2238                                    <Self as speedy::Readable< 'a_, C_ >>::speedy_flip_endianness( value );
2239                                }
2240                            }
2241                        }
2242                    }
2243                }
2244            } else {
2245                quote! {}
2246            };
2247
2248            let impl_zerocopyable = if is_primitive.impl_zerocopyable {
2249                let (impl_params, ty_params, where_clause) = common_tokens( &input, &field_types, Trait::ZeroCopyable { is_packed: is_primitive.is_ty_packed, is_forced: is_primitive.is_forced } );
2250                quote! {
2251                    unsafe impl< #impl_params C_, T_ > speedy::private::ZeroCopyable< C_, T_ > for #name #ty_params #where_clause {}
2252                }
2253            } else {
2254                quote! {}
2255            };
2256
2257            (reader_body, minimum_bytes, impl_primitive, impl_zerocopyable)
2258        },
2259        syn::Data::Enum( syn::DataEnum { variants, .. } ) => {
2260            let enumeration = Enum::new( &name, &input.attrs, &variants )?;
2261            let mut variant_matches = Vec::with_capacity( variants.len() );
2262            let mut variant_minimum_sizes = Vec::with_capacity( variants.len() );
2263            for variant in enumeration.variants {
2264                let tag = variant.tag_expr;
2265                let unqualified_ident = &variant.ident;
2266                let variant_path = quote! { #name::#unqualified_ident };
2267                let (body, initializer, minimum_bytes) = readable_body( &mut types, &variant.structure );
2268                variant_matches.push( quote! {
2269                    #tag => {
2270                        #body
2271                        Ok( #variant_path #initializer )
2272                    }
2273                });
2274
2275                if variant.structure.kind != StructKind::Unit {
2276                    if variant.structure.is_guaranteed_non_recursive() {
2277                        variant_minimum_sizes.push( minimum_bytes );
2278                    }
2279                }
2280            }
2281
2282            let tag_size = match enumeration.tag_type {
2283                BasicType::U64 => 8_usize,
2284                BasicType::U32 => 4_usize,
2285                BasicType::U16 => 2_usize,
2286                BasicType::U8 => 1_usize,
2287                BasicType::U7 => 1_usize,
2288                BasicType::VarInt64 => 1_usize,
2289            };
2290
2291            let tag_reader = match (enumeration.peek_tag, enumeration.tag_type) {
2292                (false, BasicType::U64) => quote! { read_u64 },
2293                (false, BasicType::U32) => quote! { read_u32 },
2294                (false, BasicType::U16) => quote! { read_u16 },
2295                (false, BasicType::U8) => quote! { read_u8 },
2296                (false, BasicType::U7) => quote! { read_u8 },
2297                (false, BasicType::VarInt64) => quote! { read_u64_varint },
2298
2299                (true, BasicType::U64) => quote! { peek_u64 },
2300                (true, BasicType::U32) => quote! { peek_u32 },
2301                (true, BasicType::U16) => quote! { peek_u16 },
2302                (true, BasicType::U8) => quote! { peek_u8 },
2303                (true, BasicType::U7) => quote! { peek_u8 },
2304                (true, BasicType::VarInt64) => quote! { peek_u64_varint },
2305            };
2306
2307            let reader_body = quote! {
2308                let kind_ = _reader_.#tag_reader()?;
2309                match kind_ {
2310                    #(#variant_matches),*
2311                    _ => Err( speedy::private::error_invalid_enum_variant() )
2312                }
2313            };
2314            let minimum_bytes_needed_body = min( variant_minimum_sizes.into_iter() );
2315            let minimum_bytes_needed_body =
2316                if !enumeration.peek_tag {
2317                    quote! { (#minimum_bytes_needed_body) + #tag_size }
2318                } else {
2319                    quote! { std::cmp::max( #minimum_bytes_needed_body, #tag_size ) }
2320                };
2321
2322            (reader_body, minimum_bytes_needed_body, quote! {}, quote! {})
2323        },
2324        syn::Data::Union( syn::DataUnion { union_token, .. } ) => {
2325            let message = "Unions are not supported!";
2326            return Err( syn::Error::new( union_token.span(), message ) );
2327        }
2328    };
2329
2330    let (impl_params, ty_params, where_clause) = common_tokens( &input, &types, Trait::Readable );
2331    let output = quote! {
2332        impl< 'a_, #impl_params C_: speedy::Context > speedy::Readable< 'a_, C_ > for #name #ty_params #where_clause {
2333            #[inline]
2334            fn read_from< R_: speedy::Reader< 'a_, C_ > >( _reader_: &mut R_ ) -> std::result::Result< Self, C_::Error > {
2335                #reader_body
2336            }
2337
2338            #[inline]
2339            fn minimum_bytes_needed() -> usize {
2340                #minimum_bytes_needed_body
2341            }
2342
2343            #impl_primitive
2344        }
2345
2346        #impl_zerocopyable
2347    };
2348
2349    Ok( output )
2350}
2351
2352fn assign_to_variables< 'a >( fields: impl IntoIterator< Item = &'a Field< 'a > >, is_packed: bool ) -> TokenStream {
2353    let fields: Vec< _ > = fields.into_iter().filter(|field| !field.skip).map( |field| {
2354        let var_name = field.var_name();
2355        let name = field.name();
2356
2357        if !is_packed {
2358            quote! {
2359                let #var_name = &self.#name;
2360            }
2361        } else {
2362            quote! {
2363                let #var_name = self.#name;
2364                let #var_name = &#var_name;
2365            }
2366        }
2367    }).collect();
2368
2369    quote! {
2370        #(#fields)*
2371    }
2372}
2373
2374fn impl_writable( input: syn::DeriveInput ) -> Result< TokenStream, syn::Error > {
2375    let name = &input.ident;
2376    let mut types = Vec::new();
2377    let (writer_body, impl_primitive) = match input.data {
2378        syn::Data::Struct( syn::DataStruct { ref fields, .. } ) => {
2379            let attrs = parse_attributes::< ToplevelStructAttribute >( &input.attrs )?;
2380            let attrs = collect_toplevel_struct_attributes( attrs )?;
2381            let st = Struct::new( fields, &attrs )?;
2382            let is_primitive = check_is_primitive( &input, &st, &attrs );
2383            let assignments = assign_to_variables( &st.fields, is_primitive.is_ty_packed );
2384            let (body, _) = writable_body( &mut types, &st );
2385
2386            let impl_primitive =
2387                if is_primitive.is_ty_transparent {
2388                    let field_ty = &st.fields[ 0 ].raw_ty;
2389                    quote! {
2390                        #[inline(always)]
2391                        fn speedy_is_primitive() -> bool {
2392                            <#field_ty as speedy::Writable< C_ >>::speedy_is_primitive()
2393                        }
2394
2395                        #[inline(always)]
2396                        unsafe fn speedy_slice_as_bytes( slice: &[Self] ) -> &[u8] where Self: Sized {
2397                            unsafe {
2398                                std::slice::from_raw_parts( slice.as_ptr() as *const u8, slice.len() * std::mem::size_of::< Self >() )
2399                            }
2400                        }
2401                    }
2402
2403                } else if is_primitive.is_ty_potentially_primitive {
2404                    let is_primitive = generate_is_primitive( &st.fields, true, is_primitive.check_order, is_primitive.is_forced );
2405                    quote! {
2406                        #[inline(always)]
2407                        fn speedy_is_primitive() -> bool {
2408                            #is_primitive
2409                        }
2410
2411                        #[inline(always)]
2412                        unsafe fn speedy_slice_as_bytes( slice: &[Self] ) -> &[u8] where Self: Sized {
2413                            unsafe {
2414                                std::slice::from_raw_parts( slice.as_ptr() as *const u8, slice.len() * std::mem::size_of::< Self >() )
2415                            }
2416                        }
2417                    }
2418                } else {
2419                    quote! {}
2420                };
2421
2422            let impl_body = quote! {
2423                #assignments
2424                #body
2425            };
2426
2427            (impl_body, impl_primitive)
2428        },
2429        syn::Data::Enum( syn::DataEnum { ref variants, .. } ) => {
2430            let enumeration = Enum::new( &name, &input.attrs, &variants )?;
2431            let tag_writer = match enumeration.tag_type {
2432                BasicType::U64 => quote! { write_u64 },
2433                BasicType::U32 => quote! { write_u32 },
2434                BasicType::U16 => quote! { write_u16 },
2435                BasicType::U8 => quote! { write_u8 },
2436                BasicType::U7 => quote! { write_u8 },
2437                BasicType::VarInt64 => quote! { write_u64_varint },
2438            };
2439
2440            let variants: Result< Vec< _ >, syn::Error > = enumeration.variants.iter()
2441                .map( |variant| {
2442                    let unqualified_ident = &variant.ident;
2443                    let tag_expr = &variant.tag_expr;
2444                    let variant_path = quote! { #name::#unqualified_ident };
2445                    let (body, initializer) = writable_body( &mut types, &variant.structure );
2446                    let write_tag =
2447                        if !enumeration.peek_tag {
2448                            quote! { _writer_.#tag_writer( #tag_expr )?; }
2449                        } else {
2450                            quote! {}
2451                        };
2452
2453                    let snippet = quote! {
2454                        #variant_path #initializer => {
2455                            #write_tag
2456                            #body
2457                        }
2458                    };
2459
2460                    Ok( snippet )
2461                })
2462                .collect();
2463            let variants = variants?;
2464            (quote! { match *self { #(#variants),* } }, quote! {})
2465        },
2466        syn::Data::Union( syn::DataUnion { union_token, .. } ) => {
2467            let message = "Unions are not supported!";
2468            return Err( syn::Error::new( union_token.span(), message ) );
2469        }
2470    };
2471
2472    let (impl_params, ty_params, where_clause) = common_tokens( &input, &types, Trait::Writable );
2473    let output = quote! {
2474        impl< #impl_params C_: speedy::Context > speedy::Writable< C_ > for #name #ty_params #where_clause {
2475            #[inline]
2476            fn write_to< T_: ?Sized + speedy::Writer< C_ > >( &self, _writer_: &mut T_ ) -> std::result::Result< (), C_::Error > {
2477                #writer_body
2478                Ok(())
2479            }
2480
2481            #impl_primitive
2482        }
2483    };
2484
2485    Ok( output )
2486}