• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #![recursion_limit = "256"]
6 extern crate proc_macro;
7 
8 use std::vec::Vec;
9 
10 use proc_macro2::{Span, TokenStream};
11 use quote::quote;
12 use syn::{parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, Ident};
13 
14 /// The function that derives the recursive implementation for struct or enum.
15 #[proc_macro_derive(MsgOnSocket)]
msg_on_socket_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream16 pub fn msg_on_socket_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
17     let input = parse_macro_input!(input as DeriveInput);
18     let impl_for_input = socket_msg_impl(input);
19     impl_for_input.into()
20 }
21 
socket_msg_impl(input: DeriveInput) -> TokenStream22 fn socket_msg_impl(input: DeriveInput) -> TokenStream {
23     if !input.generics.params.is_empty() {
24         return quote! {
25             compile_error!("derive(SocketMsg) does not support generic parameters");
26         };
27     }
28     match input.data {
29         Data::Struct(ds) => {
30             if is_named_struct(&ds) {
31                 impl_for_named_struct(input.ident, ds)
32             } else {
33                 impl_for_tuple_struct(input.ident, ds)
34             }
35         }
36         Data::Enum(de) => impl_for_enum(input.ident, de),
37         _ => quote! {
38             compile_error!("derive(SocketMsg) only support struct and enum");
39         },
40     }
41 }
42 
is_named_struct(ds: &DataStruct) -> bool43 fn is_named_struct(ds: &DataStruct) -> bool {
44     match &ds.fields {
45         Fields::Named(_f) => true,
46         _ => false,
47     }
48 }
49 
50 /************************** Named Struct Impls ********************************************/
impl_for_named_struct(name: Ident, ds: DataStruct) -> TokenStream51 fn impl_for_named_struct(name: Ident, ds: DataStruct) -> TokenStream {
52     let fields = get_struct_fields(ds);
53     let fields_types = get_types_from_fields_vec(&fields);
54     let buffer_sizes_impls = define_buffer_size_for_struct(&fields_types);
55 
56     let read_buffer = define_read_buffer_for_struct(&name, &fields);
57     let write_buffer = define_write_buffer_for_struct(&name, &fields);
58     quote! {
59         impl msg_socket::MsgOnSocket for #name {
60             #buffer_sizes_impls
61             #read_buffer
62             #write_buffer
63         }
64     }
65 }
66 
get_types_from_fields_vec(v: &[(Ident, syn::Type)]) -> Vec<syn::Type>67 fn get_types_from_fields_vec(v: &[(Ident, syn::Type)]) -> Vec<syn::Type> {
68     let mut fields_types = Vec::new();
69     for (_i, t) in v {
70         fields_types.push(t.clone());
71     }
72     fields_types
73 }
74 
75 // Flatten struct fields.
76 // "myfield : Type" -> \(ident\("myfield"\), Token\(Type\)\)
get_struct_fields(ds: DataStruct) -> Vec<(Ident, syn::Type)>77 fn get_struct_fields(ds: DataStruct) -> Vec<(Ident, syn::Type)> {
78     let fields = match ds.fields {
79         Fields::Named(fields_named) => fields_named.named,
80         _ => {
81             panic!("Struct must have named fields");
82         }
83     };
84     let mut vec = Vec::new();
85     for field in fields {
86         let ident = match field.ident {
87             Some(ident) => ident,
88             None => panic!("Unknown Error."),
89         };
90         let ty = field.ty;
91         vec.push((ident, ty));
92     }
93     vec
94 }
95 
define_buffer_size_for_struct(field_types: &[syn::Type]) -> TokenStream96 fn define_buffer_size_for_struct(field_types: &[syn::Type]) -> TokenStream {
97     let (msg_size, max_fd_count) = get_fields_buffer_size_sum(field_types);
98     quote! {
99         fn msg_size() -> usize {
100             #msg_size
101         }
102         fn max_fd_count() -> usize {
103             #max_fd_count
104         }
105     }
106 }
107 
define_read_buffer_for_struct(_name: &Ident, fields: &[(Ident, syn::Type)]) -> TokenStream108 fn define_read_buffer_for_struct(_name: &Ident, fields: &[(Ident, syn::Type)]) -> TokenStream {
109     let mut read_fields = Vec::new();
110     let mut init_fields = Vec::new();
111     for f in fields {
112         let read_field = read_from_buffer_and_move_offset(&f.0, &f.1);
113         read_fields.push(read_field);
114         let name = f.0.clone();
115         init_fields.push(quote!(#name));
116     }
117     quote! {
118         unsafe fn read_from_buffer(
119             buffer: &[u8],
120             fds: &[std::os::unix::io::RawFd],
121         ) -> msg_socket::MsgResult<(Self, usize)> {
122             let mut __offset = 0usize;
123             let mut __fd_offset = 0usize;
124             #(#read_fields)*
125             Ok((
126                 Self {
127                     #(#init_fields),*
128                 },
129                 __fd_offset
130             ))
131         }
132     }
133 }
134 
define_write_buffer_for_struct(_name: &Ident, fields: &[(Ident, syn::Type)]) -> TokenStream135 fn define_write_buffer_for_struct(_name: &Ident, fields: &[(Ident, syn::Type)]) -> TokenStream {
136     let mut write_fields = Vec::new();
137     for f in fields {
138         let write_field = write_to_buffer_and_move_offset(&f.0, &f.1);
139         write_fields.push(write_field);
140     }
141     quote! {
142         fn write_to_buffer(
143             &self,
144             buffer: &mut [u8],
145             fds: &mut [std::os::unix::io::RawFd],
146         ) -> msg_socket::MsgResult<usize> {
147             let mut __offset = 0usize;
148             let mut __fd_offset = 0usize;
149             #(#write_fields)*
150             Ok(__fd_offset)
151         }
152     }
153 }
154 
155 /************************** Enum Impls ********************************************/
impl_for_enum(name: Ident, de: DataEnum) -> TokenStream156 fn impl_for_enum(name: Ident, de: DataEnum) -> TokenStream {
157     let variants = get_enum_variant_types(&de);
158     let buffer_sizes_impls = define_buffer_size_for_enum(&variants);
159 
160     let read_buffer = define_read_buffer_for_enum(&name, &de);
161     let write_buffer = define_write_buffer_for_enum(&name, &de);
162     quote! {
163         impl msg_socket::MsgOnSocket for #name {
164             #buffer_sizes_impls
165             #read_buffer
166             #write_buffer
167         }
168     }
169 }
170 
define_buffer_size_for_enum(variants: &[(Ident, Vec<syn::Type>)]) -> TokenStream171 fn define_buffer_size_for_enum(variants: &[(Ident, Vec<syn::Type>)]) -> TokenStream {
172     let mut variant_buffer_sizes = Vec::new();
173     let mut variant_fd_sizes = Vec::new();
174     for v in variants {
175         let (msg_size_impl, fd_count_impl) = get_fields_buffer_size_sum(&v.1);
176         variant_buffer_sizes.push(msg_size_impl);
177         variant_fd_sizes.push(fd_count_impl);
178     }
179     quote! {
180         fn msg_size() -> usize {
181             // First byte is used for variant.
182             [#(#variant_buffer_sizes,)*].iter().max().unwrap().clone() as usize + 1
183         }
184         fn max_fd_count() -> usize {
185             [#(#variant_fd_sizes,)*].iter().max().unwrap().clone() as usize
186         }
187     }
188 }
189 
190 // Flatten enum variants. Return value = \[variant_name, \[types_of_this_variant\]\]
get_enum_variant_types(de: &DataEnum) -> Vec<(Ident, Vec<syn::Type>)>191 fn get_enum_variant_types(de: &DataEnum) -> Vec<(Ident, Vec<syn::Type>)> {
192     let mut variants = Vec::new();
193     let de = de.clone();
194     for v in de.variants {
195         let name = v.ident;
196         match v.fields {
197             Fields::Unnamed(fields) => {
198                 let mut vec = Vec::new();
199                 for field in fields.unnamed {
200                     let ty = field.ty;
201                     vec.push(ty);
202                 }
203                 variants.push((name, vec));
204             }
205             Fields::Unit => {
206                 variants.push((name, Vec::new()));
207                 continue;
208             }
209             Fields::Named(fields) => {
210                 let mut vec = Vec::new();
211                 for field in fields.named {
212                     let ty = field.ty;
213                     vec.push(ty);
214                 }
215                 variants.push((name, vec));
216             }
217         };
218     }
219     variants
220 }
221 
define_read_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream222 fn define_read_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream {
223     let mut match_variants = Vec::new();
224     let de = de.clone();
225     let mut i = 0u8;
226     for v in de.variants {
227         let variant_name = v.ident;
228         match v.fields {
229             Fields::Named(fields) => {
230                 let mut tmp_names = Vec::new();
231                 let mut read_tmps = Vec::new();
232                 for f in fields.named {
233                     tmp_names.push(f.ident.clone());
234                     let read_tmp = read_from_buffer_and_move_offset(&f.ident.unwrap(), &f.ty);
235                     read_tmps.push(read_tmp);
236                 }
237                 let v = quote! {
238                     #i => {
239                         let mut __offset = 1usize;
240                         let mut __fd_offset = 0usize;
241                         #(#read_tmps)*
242                         Ok((#name::#variant_name { #(#tmp_names),* }, __fd_offset))
243                     }
244                 };
245                 match_variants.push(v);
246             }
247             Fields::Unnamed(fields) => {
248                 let mut tmp_names = Vec::new();
249                 let mut read_tmps = Vec::new();
250                 let mut j = 0usize;
251                 for f in fields.unnamed {
252                     let tmp_name = format!("enum_variant_tmp{}", j);
253                     let tmp_name = Ident::new(&tmp_name, Span::call_site());
254                     tmp_names.push(tmp_name.clone());
255                     let read_tmp = read_from_buffer_and_move_offset(&tmp_name, &f.ty);
256                     read_tmps.push(read_tmp);
257                     j += 1;
258                 }
259 
260                 let v = quote! {
261                     #i => {
262                         let mut __offset = 1usize;
263                         let mut __fd_offset = 0usize;
264                         #(#read_tmps)*
265                         Ok((#name::#variant_name( #(#tmp_names),*), __fd_offset))
266                     }
267                 };
268                 match_variants.push(v);
269             }
270             Fields::Unit => {
271                 let v = quote! {
272                     #i => Ok((#name::#variant_name, 0)),
273                 };
274                 match_variants.push(v);
275             }
276         }
277         i += 1;
278     }
279     quote! {
280         unsafe fn read_from_buffer(
281             buffer: &[u8],
282             fds: &[std::os::unix::io::RawFd],
283         ) -> msg_socket::MsgResult<(Self, usize)> {
284             let v = buffer[0];
285             match v {
286                 #(#match_variants)*
287                 _ => Err(msg_socket::MsgError::InvalidType),
288             }
289         }
290     }
291 }
292 
define_write_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream293 fn define_write_buffer_for_enum(name: &Ident, de: &DataEnum) -> TokenStream {
294     let mut match_variants = Vec::new();
295     let mut i = 0u8;
296     let de = de.clone();
297     for v in de.variants {
298         let variant_name = v.ident;
299         match v.fields {
300             Fields::Named(fields) => {
301                 let mut tmp_names = Vec::new();
302                 let mut write_tmps = Vec::new();
303                 for f in fields.named {
304                     tmp_names.push(f.ident.clone().unwrap());
305                     let write_tmp = enum_write_to_buffer_and_move_offset(&f.ident.unwrap(), &f.ty);
306                     write_tmps.push(write_tmp);
307                 }
308 
309                 let v = quote! {
310                     #name::#variant_name { #(#tmp_names),* } => {
311                         buffer[0] = #i;
312                         let mut __offset = 1usize;
313                         let mut __fd_offset = 0usize;
314                         #(#write_tmps)*
315                         Ok(__fd_offset)
316                     }
317                 };
318                 match_variants.push(v);
319             }
320             Fields::Unnamed(fields) => {
321                 let mut tmp_names = Vec::new();
322                 let mut write_tmps = Vec::new();
323                 let mut j = 0usize;
324                 for f in fields.unnamed {
325                     let tmp_name = format!("enum_variant_tmp{}", j);
326                     let tmp_name = Ident::new(&tmp_name, Span::call_site());
327                     tmp_names.push(tmp_name.clone());
328                     let write_tmp = enum_write_to_buffer_and_move_offset(&tmp_name, &f.ty);
329                     write_tmps.push(write_tmp);
330                     j += 1;
331                 }
332 
333                 let v = quote! {
334                     #name::#variant_name(#(#tmp_names),*) => {
335                         buffer[0] = #i;
336                         let mut __offset = 1usize;
337                         let mut __fd_offset = 0usize;
338                         #(#write_tmps)*
339                         Ok(__fd_offset)
340                     }
341                 };
342                 match_variants.push(v);
343             }
344             Fields::Unit => {
345                 let v = quote! {
346                     #name::#variant_name => {
347                         buffer[0] = #i;
348                         Ok(0)
349                     }
350                 };
351                 match_variants.push(v);
352             }
353         }
354         i += 1;
355     }
356 
357     quote! {
358         fn write_to_buffer(
359             &self,
360             buffer: &mut [u8],
361             fds: &mut [std::os::unix::io::RawFd],
362         ) -> msg_socket::MsgResult<usize> {
363             match self {
364                 #(#match_variants)*
365             }
366         }
367     }
368 }
369 
enum_write_to_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream370 fn enum_write_to_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream {
371     quote! {
372         let o = #name.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
373         __offset += <#ty>::msg_size();
374         __fd_offset += o;
375     }
376 }
377 
378 /************************** Tuple Impls ********************************************/
impl_for_tuple_struct(name: Ident, ds: DataStruct) -> TokenStream379 fn impl_for_tuple_struct(name: Ident, ds: DataStruct) -> TokenStream {
380     let types = get_tuple_types(ds);
381 
382     let buffer_sizes_impls = define_buffer_size_for_struct(&types);
383 
384     let read_buffer = define_read_buffer_for_tuples(&name, &types);
385     let write_buffer = define_write_buffer_for_tuples(&name, &types);
386     quote! {
387         impl msg_socket::MsgOnSocket for #name {
388             #buffer_sizes_impls
389             #read_buffer
390             #write_buffer
391         }
392     }
393 }
394 
get_tuple_types(ds: DataStruct) -> Vec<syn::Type>395 fn get_tuple_types(ds: DataStruct) -> Vec<syn::Type> {
396     let mut types = Vec::new();
397     let fields = match ds.fields {
398         Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed,
399         _ => {
400             panic!("Tuple struct must have unnamed fields.");
401         }
402     };
403     for field in fields {
404         let ty = field.ty;
405         types.push(ty);
406     }
407     types
408 }
409 
define_read_buffer_for_tuples(name: &Ident, fields: &[syn::Type]) -> TokenStream410 fn define_read_buffer_for_tuples(name: &Ident, fields: &[syn::Type]) -> TokenStream {
411     let mut read_fields = Vec::new();
412     let mut init_fields = Vec::new();
413     for i in 0..fields.len() {
414         let tmp_name = format!("tuple_tmp{}", i);
415         let tmp_name = Ident::new(&tmp_name, Span::call_site());
416         let read_field = read_from_buffer_and_move_offset(&tmp_name, &fields[i]);
417         read_fields.push(read_field);
418         init_fields.push(quote!(#tmp_name));
419     }
420 
421     quote! {
422         unsafe fn read_from_buffer(
423             buffer: &[u8],
424             fds: &[std::os::unix::io::RawFd],
425         ) -> msg_socket::MsgResult<(Self, usize)> {
426             let mut __offset = 0usize;
427             let mut __fd_offset = 0usize;
428             #(#read_fields)*
429             Ok((
430                 #name (
431                     #(#init_fields),*
432                 ),
433                 __fd_offset
434             ))
435         }
436     }
437 }
438 
define_write_buffer_for_tuples(name: &Ident, fields: &[syn::Type]) -> TokenStream439 fn define_write_buffer_for_tuples(name: &Ident, fields: &[syn::Type]) -> TokenStream {
440     let mut write_fields = Vec::new();
441     let mut tmp_names = Vec::new();
442     for i in 0..fields.len() {
443         let tmp_name = format!("tuple_tmp{}", i);
444         let tmp_name = Ident::new(&tmp_name, Span::call_site());
445         let write_field = enum_write_to_buffer_and_move_offset(&tmp_name, &fields[i]);
446         write_fields.push(write_field);
447         tmp_names.push(tmp_name);
448     }
449     quote! {
450         fn write_to_buffer(
451             &self,
452             buffer: &mut [u8],
453             fds: &mut [std::os::unix::io::RawFd],
454         ) -> msg_socket::MsgResult<usize> {
455             let mut __offset = 0usize;
456             let mut __fd_offset = 0usize;
457             let #name( #(#tmp_names),* ) = self;
458             #(#write_fields)*
459             Ok(__fd_offset)
460         }
461     }
462 }
463 /************************** Helpers ********************************************/
get_fields_buffer_size_sum(field_types: &[syn::Type]) -> (TokenStream, TokenStream)464 fn get_fields_buffer_size_sum(field_types: &[syn::Type]) -> (TokenStream, TokenStream) {
465     if field_types.len() > 0 {
466         (
467             quote! {
468                 #( <#field_types>::msg_size() as usize )+*
469             },
470             quote! {
471                 #( <#field_types>::max_fd_count() as usize )+*
472             },
473         )
474     } else {
475         (quote!(0), quote!(0))
476     }
477 }
478 
read_from_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream479 fn read_from_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream {
480     quote! {
481         let t = <#ty>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
482         __offset += <#ty>::msg_size();
483         __fd_offset += t.1;
484         let #name = t.0;
485     }
486 }
487 
write_to_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream488 fn write_to_buffer_and_move_offset(name: &Ident, ty: &syn::Type) -> TokenStream {
489     quote! {
490         let o = self.#name.write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
491         __offset += <#ty>::msg_size();
492         __fd_offset += o;
493     }
494 }
495 
496 #[cfg(test)]
497 mod tests {
498     use crate::socket_msg_impl;
499     use quote::quote;
500     use syn::{parse_quote, DeriveInput};
501 
502     #[test]
end_to_end_struct_test()503     fn end_to_end_struct_test() {
504         let input: DeriveInput = parse_quote! {
505             struct MyMsg {
506                 a: u8,
507                 b: RawFd,
508                 c: u32,
509             }
510         };
511 
512         let expected = quote! {
513             impl msg_socket::MsgOnSocket for MyMsg {
514                 fn msg_size() -> usize {
515                     <u8>::msg_size() as usize
516                         + <RawFd>::msg_size() as usize
517                         + <u32>::msg_size() as usize
518                 }
519                 fn max_fd_count() -> usize {
520                     <u8>::max_fd_count() as usize
521                         + <RawFd>::max_fd_count() as usize
522                         + <u32>::max_fd_count() as usize
523                 }
524                 unsafe fn read_from_buffer(
525                     buffer: &[u8],
526                     fds: &[std::os::unix::io::RawFd],
527                 ) -> msg_socket::MsgResult<(Self, usize)> {
528                     let mut __offset = 0usize;
529                     let mut __fd_offset = 0usize;
530                     let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
531                     __offset += <u8>::msg_size();
532                     __fd_offset += t.1;
533                     let a = t.0;
534                     let t = <RawFd>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
535                     __offset += <RawFd>::msg_size();
536                     __fd_offset += t.1;
537                     let b = t.0;
538                     let t = <u32>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
539                     __offset += <u32>::msg_size();
540                     __fd_offset += t.1;
541                     let c = t.0;
542                     Ok((Self { a, b, c }, __fd_offset))
543                 }
544                 fn write_to_buffer(
545                     &self,
546                     buffer: &mut [u8],
547                     fds: &mut [std::os::unix::io::RawFd],
548                 ) -> msg_socket::MsgResult<usize> {
549                     let mut __offset = 0usize;
550                     let mut __fd_offset = 0usize;
551                     let o = self.a
552                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
553                     __offset += <u8>::msg_size();
554                     __fd_offset += o;
555                     let o = self.b
556                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
557                     __offset += <RawFd>::msg_size();
558                     __fd_offset += o;
559                     let o = self.c
560                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
561                     __offset += <u32>::msg_size();
562                     __fd_offset += o;
563                     Ok(__fd_offset)
564                 }
565             }
566         };
567 
568         assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
569     }
570 
571     #[test]
end_to_end_tuple_struct_test()572     fn end_to_end_tuple_struct_test() {
573         let input: DeriveInput = parse_quote! {
574             struct MyMsg(u8, u32, File);
575         };
576 
577         let expected = quote! {
578             impl msg_socket::MsgOnSocket for MyMsg {
579                 fn msg_size() -> usize {
580                     <u8>::msg_size() as usize
581                         + <u32>::msg_size() as usize
582                         + <File>::msg_size() as usize
583                 }
584                 fn max_fd_count() -> usize {
585                     <u8>::max_fd_count() as usize
586                         + <u32>::max_fd_count() as usize
587                         + <File>::max_fd_count() as usize
588                 }
589                 unsafe fn read_from_buffer(
590                     buffer: &[u8],
591                     fds: &[std::os::unix::io::RawFd],
592                 ) -> msg_socket::MsgResult<(Self, usize)> {
593                     let mut __offset = 0usize;
594                     let mut __fd_offset = 0usize;
595                     let t = <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
596                     __offset += <u8>::msg_size();
597                     __fd_offset += t.1;
598                     let tuple_tmp0 = t.0;
599                     let t = <u32>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
600                     __offset += <u32>::msg_size();
601                     __fd_offset += t.1;
602                     let tuple_tmp1 = t.0;
603                     let t = <File>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
604                     __offset += <File>::msg_size();
605                     __fd_offset += t.1;
606                     let tuple_tmp2 = t.0;
607                     Ok((MyMsg(tuple_tmp0, tuple_tmp1, tuple_tmp2), __fd_offset))
608                 }
609                 fn write_to_buffer(
610                     &self,
611                     buffer: &mut [u8],
612                     fds: &mut [std::os::unix::io::RawFd],
613                 ) -> msg_socket::MsgResult<usize> {
614                     let mut __offset = 0usize;
615                     let mut __fd_offset = 0usize;
616                     let MyMsg(tuple_tmp0, tuple_tmp1, tuple_tmp2) = self;
617                     let o = tuple_tmp0
618                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
619                     __offset += <u8>::msg_size();
620                     __fd_offset += o;
621                     let o = tuple_tmp1
622                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
623                     __offset += <u32>::msg_size();
624                     __fd_offset += o;
625                     let o = tuple_tmp2
626                         .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
627                     __offset += <File>::msg_size();
628                     __fd_offset += o;
629                     Ok(__fd_offset)
630                 }
631             }
632         };
633 
634         assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
635     }
636 
637     #[test]
end_to_end_enum_test()638     fn end_to_end_enum_test() {
639         let input: DeriveInput = parse_quote! {
640             enum MyMsg {
641                 A(u8),
642                 B,
643                 C {
644                     f0: u8,
645                     f1: RawFd,
646                 },
647             }
648         };
649 
650         let expected = quote! {
651             impl msg_socket::MsgOnSocket for MyMsg {
652                 fn msg_size() -> usize {
653                     [
654                         <u8>::msg_size() as usize,
655                         0,
656                         <u8>::msg_size() as usize + <RawFd>::msg_size() as usize,
657                     ].iter()
658                         .max().unwrap().clone() as usize+ 1
659                 }
660                 fn max_fd_count() -> usize {
661                     [
662                         <u8>::max_fd_count() as usize,
663                         0,
664                         <u8>::max_fd_count() as usize + <RawFd>::max_fd_count() as usize,
665                     ].iter()
666                         .max().unwrap().clone() as usize
667                 }
668                 unsafe fn read_from_buffer(
669                     buffer: &[u8],
670                     fds: &[std::os::unix::io::RawFd],
671                 ) -> msg_socket::MsgResult<(Self, usize)> {
672                     let v = buffer[0];
673                     match v {
674                         0u8 => {
675                             let mut __offset = 1usize;
676                             let mut __fd_offset = 0usize;
677                             let t =
678                                 <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
679                             __offset += <u8>::msg_size();
680                             __fd_offset += t.1;
681                             let enum_variant_tmp0 = t.0;
682                             Ok((MyMsg::A(enum_variant_tmp0), __fd_offset))
683                         }
684                         1u8 => Ok((MyMsg::B, 0)),
685                         2u8 => {
686                             let mut __offset = 1usize;
687                             let mut __fd_offset = 0usize;
688                             let t =
689                                 <u8>::read_from_buffer(&buffer[__offset..], &fds[__fd_offset..])?;
690                             __offset += <u8>::msg_size();
691                             __fd_offset += t.1;
692                             let f0 = t.0;
693                             let t = <RawFd>::read_from_buffer(
694                                 &buffer[__offset..],
695                                 &fds[__fd_offset..]
696                             )?;
697                             __offset += <RawFd>::msg_size();
698                             __fd_offset += t.1;
699                             let f1 = t.0;
700                             Ok((MyMsg::C { f0, f1 }, __fd_offset))
701                         }
702                         _ => Err(msg_socket::MsgError::InvalidType),
703                     }
704                 }
705                 fn write_to_buffer(
706                     &self,
707                     buffer: &mut [u8],
708                     fds: &mut [std::os::unix::io::RawFd],
709                 ) -> msg_socket::MsgResult<usize> {
710                     match self {
711                         MyMsg::A(enum_variant_tmp0) => {
712                             buffer[0] = 0u8;
713                             let mut __offset = 1usize;
714                             let mut __fd_offset = 0usize;
715                             let o = enum_variant_tmp0
716                                 .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
717                             __offset += <u8>::msg_size();
718                             __fd_offset += o;
719                             Ok(__fd_offset)
720                         }
721                         MyMsg::B => {
722                             buffer[0] = 1u8;
723                             Ok(0)
724                         }
725                         MyMsg::C { f0, f1 } => {
726                             buffer[0] = 2u8;
727                             let mut __offset = 1usize;
728                             let mut __fd_offset = 0usize;
729                             let o = f0
730                                 .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
731                             __offset += <u8>::msg_size();
732                             __fd_offset += o;
733                             let o = f1
734                                 .write_to_buffer(&mut buffer[__offset..], &mut fds[__fd_offset..])?;
735                             __offset += <RawFd>::msg_size();
736                             __fd_offset += o;
737                             Ok(__fd_offset)
738                         }
739                     }
740                 }
741             }
742 
743         };
744 
745         assert_eq!(socket_msg_impl(input).to_string(), expected.to_string());
746     }
747 }
748