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 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 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 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 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 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}