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