1use crate::get_possible_wrappers;
2#[allow(unused_imports)]
3use crate::snake_to_pascal_case;
4use itertools::Itertools;
5use proc_macro2::{Ident, TokenStream};
6use quote::{format_ident, quote, ToTokens};
7use std::collections::{BTreeMap, BTreeSet};
8use std::ops::Deref;
9use std::str::FromStr;
10use syn::{parse_str, Type};
11
12pub const COMMON_CODE: &str = include_str!("common.rs");
13pub const CLIENT_BINDINGS: &str = include_str!("../bindings/client.rs");
14pub const ARCHIVE_BINDINGS: &str = include_str!("../bindings/archive.rs");
15pub const MEDIA_DRIVER_BINDINGS: &str = include_str!("../bindings/media-driver.rs");
16
17#[derive(Debug, Clone, Default)]
18pub struct CBinding {
19 pub wrappers: BTreeMap<String, CWrapper>,
20 pub methods: Vec<Method>,
21 pub handlers: Vec<CHandler>,
22}
23
24#[derive(Debug, Clone, Eq, PartialEq)]
25pub struct Method {
26 pub fn_name: String,
27 pub struct_method_name: String,
28 pub return_type: Arg,
29 pub arguments: Vec<Arg>,
30 pub docs: BTreeSet<String>,
31}
32
33#[derive(Debug, Clone, Eq, PartialEq)]
34pub enum ArgProcessing {
35 Handler(Vec<Arg>),
36 StringWithLength(Vec<Arg>),
37 ByteArrayWithLength(Vec<Arg>),
38 Default,
39}
40
41#[derive(Debug, Clone, Eq, PartialEq)]
42pub struct Arg {
43 pub name: String,
44 pub c_type: String,
45 pub processing: ArgProcessing,
46}
47
48impl Arg {
49 pub fn is_primitive(&self) -> bool {
50 static PRIMITIVE_TYPES: &[&str] = &[
51 "i64", "u64", "f32", "f64", "i32", "i16", "u32", "u16", "bool", "usize", "isize",
52 ];
53 PRIMITIVE_TYPES.iter().any(|&f| self.c_type.ends_with(f))
54 }
55}
56
57impl Arg {
58 const C_INT_RETURN_TYPE_STR: &'static str = ":: std :: os :: raw :: c_int";
59 const C_CHAR_STR: &'static str = "* const :: std :: os :: raw :: c_char";
60 const C_MUT_CHAR_STR: &'static str = "* mut :: std :: os :: raw :: c_char";
61 const C_BYTE_ARRAY: &'static str = "* const u8";
62 const C_BYTE_MUT_ARRAY: &'static str = "* mut u8";
63 const STAR_MUT: &'static str = "* mut";
64 const DOUBLE_STAR_MUT: &'static str = "* mut * mut";
65 const C_VOID: &'static str = "* mut :: std :: os :: raw :: c_void";
66
67 pub fn is_any_pointer(&self) -> bool {
68 self.c_type.starts_with("* const") || self.c_type.starts_with("* mut")
69 }
70
71 pub fn is_c_string(&self) -> bool {
72 self.c_type == Self::C_CHAR_STR
73 }
74
75 pub fn is_c_string_any(&self) -> bool {
76 self.is_c_string() || self.is_mut_c_string()
77 }
78
79 pub fn is_mut_c_string(&self) -> bool {
80 self.c_type == Self::C_MUT_CHAR_STR
81 }
82
83 pub fn is_usize(&self) -> bool {
84 self.c_type == "usize"
85 }
86
87 pub fn is_byte_array(&self) -> bool {
88 self.c_type == Self::C_BYTE_ARRAY || self.c_type == Self::C_BYTE_MUT_ARRAY
89 }
90
91 pub fn is_mut_byte_array(&self) -> bool {
92 self.c_type == Self::C_BYTE_MUT_ARRAY
93 }
94
95 pub fn is_c_raw_int(&self) -> bool {
96 self.c_type == Self::C_INT_RETURN_TYPE_STR
97 }
98
99 pub fn is_mut_pointer(&self) -> bool {
100 self.c_type.starts_with(Self::STAR_MUT)
101 }
102
103 pub fn is_double_mut_pointer(&self) -> bool {
104 self.c_type.starts_with(Self::DOUBLE_STAR_MUT)
105 }
106
107 pub fn is_single_mut_pointer(&self) -> bool {
108 self.is_mut_pointer() && !self.is_double_mut_pointer()
109 }
110
111 pub fn is_c_void(&self) -> bool {
112 self.c_type == Self::C_VOID
113 }
114}
115
116impl Deref for Arg {
117 type Target = str;
118
119 fn deref(&self) -> &Self::Target {
120 &self.c_type
121 }
122}
123
124impl Arg {
125 pub fn as_ident(&self) -> Ident {
126 Ident::new(&self.name, proc_macro2::Span::call_site())
127 }
128
129 pub fn as_type(&self) -> Type {
130 parse_str(&self.c_type).expect("Invalid argument type")
131 }
132}
133
134#[derive(Debug, Clone)]
135pub struct CHandler {
136 pub type_name: String,
137 pub args: Vec<Arg>,
138 pub return_type: Arg,
139 pub docs: BTreeSet<String>,
140 pub fn_mut_signature: TokenStream,
141 pub closure_type_name: TokenStream,
142}
143
144#[derive(Debug, Clone)]
145pub struct ReturnType {
146 original: Arg,
147 wrappers: BTreeMap<String, CWrapper>,
148}
149
150impl ReturnType {
151 pub fn new(original_c_type: Arg, wrappers: BTreeMap<String, CWrapper>) -> Self {
152 ReturnType {
153 original: original_c_type,
154 wrappers,
155 }
156 }
157
158 pub fn get_new_return_type(
159 &self,
160 convert_errors: bool,
161 use_ref_for_cwrapper: bool,
162 ) -> TokenStream {
163 if let ArgProcessing::Handler(_) = self.original.processing {
164 if self.original.name.len() > 0 {
165 if !self.original.is_mut_pointer() {
166 let new_type = parse_str::<Type>(&format!(
167 "{}HandlerImpl",
168 snake_to_pascal_case(&self.original.c_type)
169 ))
170 .expect("Invalid class name in wrapper");
171 return quote! { Option<&Handler<#new_type>> };
172 } else {
173 return quote! {};
174 }
175 }
176 } else if let ArgProcessing::StringWithLength(_) = self.original.processing {
177 if self.original.name.len() > 0 {
178 if self.original.is_c_string() {
179 return quote! { &str };
180 } else if self.original.is_mut_c_string() {
181 } else {
183 return quote! {};
184 }
185 }
186 } else if let ArgProcessing::ByteArrayWithLength(_) = self.original.processing {
187 if self.original.name.len() > 0 {
188 if self.original.is_byte_array() {
189 if self.original.is_mut_byte_array() {
190 return quote! { &mut [u8] };
191 } else {
192 return quote! { &[u8] };
193 }
194 } else {
195 return quote! {};
196 }
197 }
198 }
199
200 if self.original.is_single_mut_pointer() {
201 let type_name = self.original.split(" ").last().unwrap();
202 if let Some(wrapper) = self.wrappers.get(type_name) {
203 let new_type =
204 parse_str::<Type>(&wrapper.class_name).expect("Invalid class name in wrapper");
205 if use_ref_for_cwrapper {
206 return quote! { &#new_type };
207 } else {
208 return quote! { #new_type };
209 }
210 }
211 }
212 if let Some(wrapper) = self.wrappers.get(&self.original.c_type) {
213 let new_type =
214 parse_str::<Type>(&wrapper.class_name).expect("Invalid class name in wrapper");
215 return quote! { #new_type };
216 }
217 if convert_errors && self.original.is_c_raw_int() {
218 return quote! { Result<i32, AeronCError> };
219 }
220 if self.original.is_c_string() {
221 if !convert_errors && use_ref_for_cwrapper {
223 return quote! { &std::ffi::CStr };
224 } else {
225 return quote! { &str };
226 }
227 }
228 let return_type: Type = parse_str(&self.original).expect("Invalid return type");
229 if self.original.is_single_mut_pointer() && self.original.is_primitive() {
230 let mut_type: Type = parse_str(
231 &return_type
232 .to_token_stream()
233 .to_string()
234 .replace("* mut ", "&mut "),
235 )
236 .unwrap();
237 return quote! { #mut_type };
238 }
239 quote! { #return_type }
240 }
241
242 pub fn handle_c_to_rs_return(
243 &self,
244 result: TokenStream,
245 convert_errors: bool,
246 use_self: bool,
247 ) -> TokenStream {
248 if let ArgProcessing::StringWithLength(_) = &self.original.processing {
249 if !self.original.is_c_string_any() {
250 return quote! {};
251 }
252 }
253 if let ArgProcessing::ByteArrayWithLength(args) = &self.original.processing {
254 if !self.original.is_byte_array() {
255 return quote! {};
256 } else {
257 let star_const = &args[0].as_ident();
258 let length = &args[1].as_ident();
259 let me = if use_self {
260 quote! {self.}
261 } else {
262 quote! {}
263 };
264 if self.original.is_mut_byte_array() {
265 return quote! {
266 unsafe { if #me #star_const.is_null() { &mut [] as &mut [_] } else {std::slice::from_raw_parts_mut(#me #star_const, #me #length.try_into().unwrap()) } }
267 };
268 } else {
269 return quote! {
270 if #me #star_const.is_null() { &[] as &[_] } else { std::slice::from_raw_parts(#me #star_const, #me #length) }
271 };
272 }
273 }
274 }
275
276 if convert_errors && self.original.is_c_raw_int() {
277 quote! {
278 if result < 0 {
279 return Err(AeronCError::from_code(result));
280 } else {
281 return Ok(result)
282 }
283 }
284 } else if self.original.is_c_string() {
285 if let ArgProcessing::StringWithLength(args) = &self.original.processing {
286 let length = &args[1].as_ident();
287 return quote! { if #result.is_null() { ""} else { std::str::from_utf8_unchecked(std::slice::from_raw_parts(#result as *const u8, #length.try_into().unwrap()))}};
288 } else {
289 return quote! { if #result.is_null() { ""} else { unsafe { std::ffi::CStr::from_ptr(#result).to_str().unwrap() } } };
290 }
291 } else if self.original.is_single_mut_pointer() && self.original.is_primitive() {
292 return quote! {
293 unsafe { &mut *#result }
294 };
295 } else {
296 quote! { #result.into() }
297 }
298 }
299
300 pub fn method_generics_for_where(&self) -> Option<TokenStream> {
301 if let ArgProcessing::Handler(handler_client) = &self.original.processing {
302 if !self.original.is_mut_pointer() {
303 let handler = handler_client.get(0).unwrap();
304 let new_type = parse_str::<Type>(&format!(
305 "{}HandlerImpl",
306 snake_to_pascal_case(&handler.c_type)
307 ))
308 .expect("Invalid class name in wrapper");
309 let new_handler = parse_str::<Type>(&format!(
310 "{}Callback",
311 snake_to_pascal_case(&handler.c_type)
312 ))
313 .expect("Invalid class name in wrapper");
314 return Some(quote! {
315 #new_type: #new_handler
316 });
317 }
318 }
319 None
320 }
321
322 pub fn method_generics_for_method(&self) -> Option<TokenStream> {
323 if let ArgProcessing::Handler(handler_client) = &self.original.processing {
324 if !self.original.is_mut_pointer() {
325 let handler = handler_client.get(0).unwrap();
326 let new_type = parse_str::<Type>(&format!(
327 "{}HandlerImpl",
328 snake_to_pascal_case(&handler.c_type)
329 ))
330 .expect("Invalid class name in wrapper");
331 return Some(quote! {
332 #new_type
333 });
334 }
335 }
336 None
337 }
338
339 pub fn handle_rs_to_c_return(
340 &self,
341 result: TokenStream,
342 include_field_name: bool,
343 ) -> TokenStream {
344 if let ArgProcessing::Handler(handler_client) = &self.original.processing {
345 if !self.original.is_mut_pointer() {
346 let handler = handler_client.get(0).unwrap();
347 let handler_name = handler.as_ident();
348 let handler_type = handler.as_type();
349 let clientd_name = handler_client.get(1).unwrap().as_ident();
350 let method_name = format_ident!("{}_callback", handler.c_type);
351 let new_type = parse_str::<Type>(&format!(
352 "{}HandlerImpl",
353 snake_to_pascal_case(&self.original.c_type)
354 ))
355 .expect("Invalid class name in wrapper");
356 if include_field_name {
357 return quote! {
358 #handler_name: { let callback: #handler_type = if #handler_name.is_none() { None } else { Some(#method_name::<#new_type>) }; callback },
359 #clientd_name: #handler_name.map(|m|m.as_raw()).unwrap_or_else(|| std::ptr::null_mut())
360 };
361 } else {
362 return quote! {
363 { let callback: #handler_type = if #handler_name.is_none() { None } else { Some(#method_name::<#new_type>) }; callback },
364 #handler_name.map(|m|m.as_raw()).unwrap_or_else(|| std::ptr::null_mut())
365 };
366 }
367 } else {
368 return quote! {};
369 }
370 }
371 if let ArgProcessing::StringWithLength(handler_client) = &self.original.processing {
372 if !self.original.is_c_string() {
373 let array = handler_client.get(0).unwrap();
374 let array_name = array.as_ident();
375 let length_name = handler_client.get(1).unwrap().as_ident();
376 if include_field_name {
377 return quote! {
378 #array_name: #array_name.as_ptr() as *const _,
379 #length_name: #array_name.len()
380 };
381 } else {
382 return quote! {
383 #array_name.as_ptr() as *const _,
384 #array_name.len()
385 };
386 }
387 } else {
388 return quote! {};
389 }
390 }
391 if let ArgProcessing::ByteArrayWithLength(handler_client) = &self.original.processing {
392 if !self.original.is_byte_array() {
393 let array = handler_client.get(0).unwrap();
394 let array_name = array.as_ident();
395 let length_name = handler_client.get(1).unwrap().as_ident();
396 if include_field_name {
397 return quote! {
398 #array_name: #array_name.as_ptr() as *mut _,
399 #length_name: #array_name.len()
400 };
401 } else {
402 return quote! {
403 #array_name.as_ptr() as *mut _,
404 #array_name.len()
405 };
406 }
407 } else {
408 return quote! {};
409 }
410 }
411
412 if include_field_name {
413 let arg_name = self.original.as_ident();
414 return if self.original.is_c_string() {
415 quote! {
416 #arg_name: #result.as_ptr()
417 }
418 } else {
419 if self.original.is_single_mut_pointer() && self.original.is_primitive() {
420 return quote! {
421 #arg_name: #result as *mut _
422 };
423 }
424
425 quote! { #arg_name: #result.into() }
426 };
427 }
428
429 if self.original.is_single_mut_pointer() && self.original.is_primitive() {
430 return quote! {
431 #result as *mut _
432 };
433 }
434
435 if self.original.is_c_string() {
436 quote! {
437 #result.as_ptr()
438 }
439 } else {
440 quote! { #result.into() }
441 }
442 }
443}
444
445#[derive(Debug, Clone, Default, Eq, PartialEq)]
446pub struct CWrapper {
447 pub class_name: String,
448 pub type_name: String,
449 pub without_name: String,
450 pub fields: Vec<Arg>,
451 pub methods: Vec<Method>,
452 pub docs: BTreeSet<String>,
453}
454
455impl CWrapper {
456 pub fn find_methods(&self, name: &str) -> Vec<Method> {
457 self.methods
458 .iter()
459 .filter(|m| m.struct_method_name == name)
460 .cloned()
461 .collect_vec()
462 }
463
464 pub fn find_unique_method(&self, name: &str) -> Option<Method> {
465 let results = self.find_methods(name);
466 if results.len() == 1 {
467 results.into_iter().next()
468 } else {
469 None
470 }
471 }
472
473 fn get_close_method(&self) -> Option<Method> {
474 self.find_unique_method("close")
475 }
476
477 fn get_is_closed_method(&self) -> Option<Method> {
478 self.find_unique_method("is_closed")
479 }
480
481 fn get_is_closed_method_quote(&self) -> TokenStream {
482 if let Some(method) = self.get_is_closed_method() {
483 let fn_name = format_ident!("{}", method.fn_name);
484 quote! {
485 Some(|c| unsafe{#fn_name(c)})
486 }
487 } else {
488 quote! {
489 None
490 }
491 }
492 }
493
494 fn generate_methods(
496 &self,
497 wrappers: &BTreeMap<String, CWrapper>,
498 closure_handlers: &Vec<CHandler>,
499 additional_outer_impls: &mut Vec<TokenStream>,
500 ) -> Vec<TokenStream> {
501 self.methods
502 .iter()
503 .filter(|m| !m.arguments.iter().any(|arg| arg.is_double_mut_pointer()))
504 .map(|method| {
505
506 let set_closed = if method.struct_method_name == "close" {
507 quote! {
508 if let Some(inner) = self.inner.as_owned() {
509 inner.close_already_called.set(true);
510 }
511 }
512 } else {
513 quote! {}
514 };
515
516
517
518 let fn_name =
519 Ident::new(&method.struct_method_name, proc_macro2::Span::call_site());
520 let return_type_helper =
521 ReturnType::new(method.return_type.clone(), wrappers.clone());
522 let return_type = return_type_helper.get_new_return_type(true, false);
523 let ffi_call = Ident::new(&method.fn_name, proc_macro2::Span::call_site());
524
525 let generic_types: Vec<TokenStream> = method
527 .arguments
528 .iter()
529 .flat_map(|arg| {
530 ReturnType::new(arg.clone(), wrappers.clone())
531 .method_generics_for_where()
532 .into_iter()
533 })
534 .collect_vec();
535 let where_clause = if generic_types.is_empty() {
536 quote! {}
537 } else {
538 quote! { <#(#generic_types),*> }
539 };
540
541 let fn_arguments: Vec<TokenStream> = method
542 .arguments
543 .iter()
544 .filter_map(|arg| {
545 let ty = &arg.c_type;
546 let t = if arg.is_single_mut_pointer() {
547 ty.split(" ").last().unwrap()
548 } else {
549 "notfound"
550 };
551 if let Some(matching_wrapper) = wrappers.get(t) {
552 if matching_wrapper.type_name == self.type_name {
553 None
554 } else {
555 let arg_name = arg.as_ident();
556 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
557 .get_new_return_type(false, true);
558 if arg_type.is_empty() {
559 None
560 } else {
561 Some(quote! { #arg_name: #arg_type })
562 }
563 }
564 } else {
565 let arg_name = arg.as_ident();
566 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
567 .get_new_return_type(false, true);
568 if arg_type.is_empty() {
569 None
570 } else {
571 Some(quote! { #arg_name: #arg_type })
572 }
573 }
574 })
575 .filter(|t| !t.is_empty())
576 .collect();
577
578 let mut uses_self = false;
579
580 let mut arg_names: Vec<TokenStream> = method
582 .arguments
583 .iter()
584 .filter_map(|arg| {
585 let ty = &arg.c_type;
586 let t = if arg.is_single_mut_pointer() {
587 ty.split(" ").last().unwrap()
588 } else {
589 "notfound"
590 };
591 if let Some(_matching_wrapper) = wrappers.get(t) {
592 let field_name = arg.as_ident();
593 if ty.ends_with(self.type_name.as_str()) {
594 uses_self = true;
595 Some(quote! { self.get_inner() })
596 } else {
597 Some(quote! { #field_name.get_inner() })
598 }
599 } else {
600 let arg_name = arg.as_ident();
601 let arg_name = quote! { #arg_name };
602 let arg_name = ReturnType::new(arg.clone(), wrappers.clone())
603 .handle_rs_to_c_return(arg_name, false);
604 Some(quote! { #arg_name })
605 }
606 })
607 .filter(|t| !t.is_empty())
608 .collect();
609
610 let converter = return_type_helper.handle_c_to_rs_return(quote! { result }, true, false);
611
612 let possible_self = if uses_self || return_type.to_string().eq("& str") {
613 quote! { &self, }
614 } else {
615 quote! {}
616 };
617
618
619 let method_docs: Vec<TokenStream> = get_docs(&method.docs, wrappers, Some(&fn_arguments) );
620
621 let mut additional_methods = vec![];
622
623 Self::add_mut_string_methods_if_applicable(method, &fn_name, uses_self, &method_docs, &mut additional_methods);
624
625 Self::add_getter_instead_of_mut_arg_if_applicable(wrappers, method, &fn_name, &where_clause, &possible_self, &method_docs, &mut additional_methods);
627
628 Self::add_once_methods_for_handlers(closure_handlers, method, &fn_name, &return_type, &ffi_call, &where_clause, &fn_arguments, &mut arg_names, &converter, &possible_self, &method_docs, &mut additional_methods, &set_closed);
629
630 let mut_primitivies = method.arguments.iter()
631 .filter(|a| a.is_mut_pointer() && a.is_primitive())
632 .collect_vec();
633 let single_mut_field = method.return_type.is_c_raw_int() && mut_primitivies.len() == 1;
634
635 if single_mut_field {
638 let mut_field = mut_primitivies.first().unwrap();
639 let rt: Type = parse_str(mut_field.c_type.split_whitespace().last().unwrap()).unwrap();
640 let return_type = quote! { Result<#rt, AeronCError> };
641
642 let fn_arguments= fn_arguments.into_iter().filter(|arg| {!arg.to_string().contains("& mut ")})
643 .collect_vec();
644
645 let idx = arg_names.iter().enumerate()
646 .filter(|(_, arg)| arg.to_string().ends_with("* mut _"))
647 .map(|(i, _)| i)
648 .next().unwrap();
649
650 arg_names[idx] = quote! { &mut mut_result };
651
652 let mut first = true;
653 let mut method_docs = method_docs.iter()
654 .filter(|d| !d.to_string().contains("# Return"))
655 .map(|d| {
656 let mut string = d.to_string();
657 string = string.replace("# Parameters", "");
658 if string.contains("out param") {
659 TokenStream::from_str(&string.replace("- `", "\n# Return\n`")).unwrap()
660 } else {
661 if string.contains("- `") && first {
662 first = false;
663 string = string.replacen("- `","# Parameters\n- `", 1);
664 }
665 TokenStream::from_str(&string).unwrap()
666 }
667 })
668 .collect_vec();
669
670 let filter_param_title = !method_docs.iter().any(|d| d.to_string().contains("- `"));
671
672 if filter_param_title {
673 method_docs = method_docs.into_iter()
674 .map(|s| TokenStream::from_str(s.to_string().replace("# Parameters\n", "").as_str()).unwrap())
675 .collect_vec();
676 }
677
678 quote! {
679 #[inline]
680 #(#method_docs)*
681 pub fn #fn_name #where_clause(#possible_self #(#fn_arguments),*) -> #return_type {
682 #set_closed
683 unsafe {
684 let mut mut_result: #rt = Default::default();
685 let err_code = #ffi_call(#(#arg_names),*);
686
687 if err_code < 0 {
688 return Err(AeronCError::from_code(err_code));
689 } else {
690 return Ok(mut_result);
691 }
692 }
693 }
694
695 #(#additional_methods)*
696 }
697 } else {
698 quote! {
699 #[inline]
700 #(#method_docs)*
701 pub fn #fn_name #where_clause(#possible_self #(#fn_arguments),*) -> #return_type {
702 #set_closed
703 unsafe {
704 let result = #ffi_call(#(#arg_names),*);
705 #converter
706 }
707 }
708
709 #(#additional_methods)*
710 }
711 }
712 })
713 .collect()
714 }
715
716 fn add_once_methods_for_handlers(
717 closure_handlers: &Vec<CHandler>,
718 method: &Method,
719 fn_name: &Ident,
720 return_type: &TokenStream,
721 ffi_call: &Ident,
722 where_clause: &TokenStream,
723 fn_arguments: &Vec<TokenStream>,
724 arg_names: &mut Vec<TokenStream>,
725 converter: &TokenStream,
726 possible_self: &TokenStream,
727 method_docs: &Vec<TokenStream>,
728 additional_methods: &mut Vec<TokenStream>,
729 set_closed: &TokenStream,
730 ) {
731 if method.arguments.iter().any(|arg| {
732 matches!(arg.processing, ArgProcessing::Handler(_))
733 && !method.fn_name.starts_with("set_")
734 && !method.fn_name.starts_with("add_")
735 }) {
736 let fn_name = format_ident!("{}_once", fn_name);
737
738 let mut where_clause = where_clause.to_string();
740
741 for c in closure_handlers.iter() {
742 if !c.closure_type_name.is_empty() {
743 where_clause = where_clause.replace(
744 &c.closure_type_name.to_string(),
745 &c.fn_mut_signature.to_string(),
746 );
747 }
748 }
749 let where_clause = parse_str::<TokenStream>(&where_clause).unwrap();
750
751 let fn_arguments = fn_arguments.iter().map(|arg| {
753 let mut arg = arg.clone();
754 let str = arg.to_string();
755 if str.contains("& Handler ") {
756 let parts = str.split(" ").collect_vec();
758 let variable_name = parse_str::<TokenStream>(parts[0]).unwrap();
759 let closure_type = parse_str::<TokenStream>(parts[parts.len() - 2]).unwrap();
760 arg = quote! { mut #variable_name : #closure_type };
761 }
762
763 arg
764 });
765
766 let arg_names = arg_names.iter().map(|x| {
768 let mut str = x.to_string()
769 .replace("_callback :: <", "_callback_for_once_closure :: <")
770 ;
771
772 if str.contains("_callback_for_once_closure") {
773 let caps = regex::Regex::new(
790 r#"let callback\s*:\s*(?P<type>[\w_]+)\s*=\s*if\s*(?P<handler_var_name>[\w_]+)\s*\.\s*is_none\s*\(\).*Some\s*\(\s*(?P<callback>[\w_]+)\s*::\s*<\s*(?P<handler>[\w_]+)\s*>\s*\).*"#
791 )
792 .unwrap()
793 .captures(&str)
794 .expect(&format!("regex failed for {str}"));
795 let func_type = parse_str::<TokenStream>(&caps["type"]).unwrap();
796 let handler_var_name = parse_str::<TokenStream>(&caps["handler_var_name"]).unwrap();
797 let callback = parse_str::<TokenStream>(&caps["callback"]).unwrap();
798 let handler_type = parse_str::<TokenStream>(&caps["handler"]).unwrap();
799
800 let new_code = quote! {
801 Some(#callback::<#handler_type>),
802 &mut #handler_var_name as *mut _ as *mut std::os::raw::c_void
803 };
804 str = new_code.to_string();
805 }
806
807 parse_str::<TokenStream>(&str).unwrap()
808 }).collect_vec();
809 additional_methods.push(quote! {
810 #[inline]
811 #(#method_docs)*
812 pub fn #fn_name #where_clause(#possible_self #(#fn_arguments),*) -> #return_type {
817 #set_closed
818 unsafe {
819 let result = #ffi_call(#(#arg_names),*);
820 #converter
821 }
822 }
823 })
824 }
825 }
826
827 fn add_getter_instead_of_mut_arg_if_applicable(
828 wrappers: &BTreeMap<String, CWrapper>,
829 method: &Method,
830 fn_name: &Ident,
831 where_clause: &TokenStream,
832 possible_self: &TokenStream,
833 method_docs: &Vec<TokenStream>,
834 additional_methods: &mut Vec<TokenStream>,
835 ) {
836 if ["constants", "buffers", "values"]
837 .iter()
838 .any(|name| method.struct_method_name == *name)
839 && method.arguments.len() == 2
840 {
841 let rt = ReturnType::new(method.arguments[1].clone(), wrappers.clone());
842 let return_type = rt.get_new_return_type(false, false);
843 let getter_method = format_ident!("get_{}", fn_name);
844 let method_docs = method_docs
845 .iter()
846 .cloned()
847 .take_while(|t| !t.to_string().contains(" Parameter"))
848 .collect_vec();
849 additional_methods.push(quote! {
850 #[inline]
851 #(#method_docs)*
852 pub fn #getter_method #where_clause(#possible_self) -> Result<#return_type, AeronCError> {
853 let result = #return_type::new_zeroed_on_stack();
854 self.#fn_name(&result)?;
855 Ok(result)
856 }
857 });
858 }
859 }
860
861 fn add_mut_string_methods_if_applicable(
862 method: &Method,
863 fn_name: &Ident,
864 uses_self: bool,
865 method_docs: &Vec<TokenStream>,
866 additional_methods: &mut Vec<TokenStream>,
867 ) {
868 if method.arguments.len() == 3 && uses_self {
869 let method_docs = method_docs.clone();
870 let into_method = format_ident!("{}_into", fn_name);
871 if method.arguments[1].is_mut_c_string() && method.arguments[2].is_usize() {
872 let string_method = format_ident!("{}_as_string", fn_name);
873 additional_methods.push(quote! {
874 #[inline]
875 #(#method_docs)*
876 pub fn #string_method(
877 &self,
878 max_length: usize,
879 ) -> Result<String, AeronCError> {
880 let mut result = String::with_capacity(max_length);
881 self.#into_method(&mut result)?;
882 Ok(result)
883 }
884
885 #[inline]
886 #(#method_docs)*
887 #[doc = "NOTE: allocation friendly method, the string capacity must be set as it will truncate string to capacity it will never grow the string. So if you pass String::new() it will write 0 chars"]
888 pub fn #into_method(
889 &self,
890 dst_truncate_to_capacity: &mut String,
891 ) -> Result<i32, AeronCError> {
892 unsafe {
893 let capacity = dst_truncate_to_capacity.capacity();
894 let vec = dst_truncate_to_capacity.as_mut_vec();
895 vec.set_len(capacity);
896 let result = self.#fn_name(vec.as_mut_ptr() as *mut _, capacity)?;
897 let mut len = 0;
898 loop {
899 if len == capacity {
900 break;
901 }
902 let val = vec[len];
903 if val == 0 {
904 break;
905 }
906 len += 1;
907 }
908 vec.set_len(len);
909 Ok(result)
910 }
911 }
912 });
913 }
914 }
915 }
916
917 fn generate_fields(
919 &self,
920 cwrappers: &BTreeMap<String, CWrapper>,
921 debug_fields: &mut Vec<TokenStream>,
922 ) -> Vec<TokenStream> {
923 self.fields
924 .iter()
925 .filter(|arg| {
926 !arg.name.starts_with("_")
927 && !self
928 .methods
929 .iter()
930 .any(|m| m.struct_method_name.as_str() == arg.name)
931 })
932 .map(|arg| {
933 let field_name = &arg.name;
934 let fn_name = Ident::new(field_name, proc_macro2::Span::call_site());
935
936 let mut arg = arg.clone();
937 if arg.is_mut_c_string() {
939 arg.c_type = arg.c_type.replace(" mut ", " const ");
940 }
941 let mut rt = ReturnType::new(arg.clone(), cwrappers.clone());
942 let mut return_type = rt.get_new_return_type(false, false);
943 let handler = if let ArgProcessing::Handler(_) = &arg.processing {
944 true
945 } else {
946 false
947 };
948 if return_type.is_empty() || handler {
949 rt = ReturnType::new(
950 Arg {
951 processing: ArgProcessing::Default,
952 ..arg.clone()
953 },
954 cwrappers.clone(),
955 );
956 return_type = rt.get_new_return_type(false, false);
957 }
958 let converter = rt.handle_c_to_rs_return(quote! { self.#fn_name }, false, true);
959
960 if rt.original.is_primitive()
961 || rt.original.is_c_string_any()
962 || rt.original.is_byte_array()
963 || cwrappers.contains_key(&rt.original.c_type)
964 {
965 if !rt.original.is_any_pointer() {
966 debug_fields
967 .push(quote! { .field(stringify!(#fn_name), &self.#fn_name()) });
968 }
969 }
970
971 quote! {
972 #[inline]
973 pub fn #fn_name(&self) -> #return_type {
974 #converter
975 }
976 }
977 })
978 .filter(|t| !t.is_empty())
979 .collect()
980 }
981
982 fn generate_constructor(
984 &self,
985 wrappers: &BTreeMap<String, CWrapper>,
986 constructor_fields: &mut Vec<TokenStream>,
987 new_ref_set_none: &mut Vec<TokenStream>,
988 ) -> Vec<TokenStream> {
989 let constructors = self
990 .methods
991 .iter()
992 .filter(|m| m.arguments.iter().any(|arg| arg.is_double_mut_pointer()))
993 .map(|method| {
994 let init_fn = format_ident!("{}", method.fn_name);
995
996 let close_method = self.find_close_method(method);
997 let found_close = close_method.is_some()
998 && close_method.unwrap().return_type.is_c_raw_int()
999 && close_method.unwrap() != method
1000 && close_method
1001 .unwrap()
1002 .arguments
1003 .iter()
1004 .skip(1)
1005 .all(|a| method.arguments.iter().any(|a2| a.name == a2.name));
1006 if found_close {
1007 let close_fn = format_ident!("{}", close_method.unwrap().fn_name);
1008 let init_args: Vec<TokenStream> = method
1009 .arguments
1010 .iter()
1011 .enumerate()
1012 .map(|(idx, arg)| {
1013 if idx == 0 {
1014 quote! { ctx_field }
1015 } else {
1016 let arg_name = arg.as_ident();
1017 quote! { #arg_name }
1018 }
1019 })
1020 .filter(|t| !t.is_empty())
1021 .collect();
1022 let close_args: Vec<TokenStream> = close_method
1023 .unwrap_or(method)
1024 .arguments
1025 .iter()
1026 .enumerate()
1027 .map(|(idx, arg)| {
1028 if idx == 0 {
1029 if arg.is_double_mut_pointer() {
1030 quote! { ctx_field }
1031 } else {
1032 quote! { *ctx_field }
1033 }
1034 } else {
1035 let arg_name = arg.as_ident();
1036 quote! { #arg_name.into() }
1037 }
1038 })
1039 .filter(|t| !t.is_empty())
1040 .collect();
1041 let lets: Vec<TokenStream> =
1042 Self::lets_for_copying_arguments(wrappers, &method.arguments, true);
1043
1044 constructor_fields.clear();
1045 constructor_fields.extend(Self::constructor_fields(
1046 wrappers,
1047 &method.arguments,
1048 &self.class_name,
1049 ));
1050
1051 let new_ref_args =
1052 Self::new_args(wrappers, &method.arguments, &self.class_name, false);
1053
1054 new_ref_set_none.clear();
1055 new_ref_set_none.extend(Self::new_args(
1056 wrappers,
1057 &method.arguments,
1058 &self.class_name,
1059 true,
1060 ));
1061
1062 let new_args: Vec<TokenStream> = method
1063 .arguments
1064 .iter()
1065 .enumerate()
1066 .filter_map(|(_idx, arg)| {
1067 if arg.is_double_mut_pointer() {
1068 None
1069 } else {
1070 let arg_name = arg.as_ident();
1071 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
1072 .get_new_return_type(false, true);
1073 if arg_type.clone().into_token_stream().is_empty() {
1074 None
1075 } else {
1076 Some(quote! { #arg_name: #arg_type })
1077 }
1078 }
1079 })
1080 .filter(|t| !t.is_empty())
1081 .collect();
1082
1083 let fn_name = format_ident!(
1084 "{}",
1085 method
1086 .struct_method_name
1087 .replace("init", "new")
1088 .replace("create", "new")
1089 );
1090
1091 let generic_types: Vec<TokenStream> = method
1092 .arguments
1093 .iter()
1094 .flat_map(|arg| {
1095 ReturnType::new(arg.clone(), wrappers.clone())
1096 .method_generics_for_where()
1097 .into_iter()
1098 })
1099 .collect_vec();
1100 let where_clause = if generic_types.is_empty() {
1101 quote! {}
1102 } else {
1103 quote! { <#(#generic_types),*> }
1104 };
1105
1106 let method_docs: Vec<TokenStream> =
1107 get_docs(&method.docs, wrappers, Some(&new_args));
1108
1109 let is_closed_method = self.get_is_closed_method_quote();
1110 quote! {
1111 #(#method_docs)*
1112 pub fn #fn_name #where_clause(#(#new_args),*) -> Result<Self, AeronCError> {
1113 #(#lets)*
1114 let resource_constructor = ManagedCResource::new(
1116 move |ctx_field| unsafe { #init_fn(#(#init_args),*) },
1117 Some(Box::new(move |ctx_field| unsafe { #close_fn(#(#close_args),*)} )),
1118 false,
1119 #is_closed_method,
1120 )?;
1121
1122 Ok(Self {
1123 inner: CResource::OwnedOnHeap(std::rc::Rc::new(resource_constructor)),
1124 #(#new_ref_args)*
1125 })
1126 }
1127 }
1128 } else {
1129 quote! {}
1130 }
1131 })
1132 .collect_vec();
1133
1134 let no_constructor = constructors
1135 .iter()
1136 .map(|x| x.to_string())
1137 .join("")
1138 .trim()
1139 .is_empty();
1140 if no_constructor {
1141 let type_name = format_ident!("{}", self.type_name);
1142 let is_closed_method = self.get_is_closed_method_quote();
1143
1144 let zeroed_impl = quote! {
1145 #[inline]
1146 pub fn new_zeroed_on_heap() -> Self {
1148 let resource = ManagedCResource::new(
1149 move |ctx_field| {
1150 #[cfg(feature = "extra-logging")]
1151 log::info!("creating zeroed empty resource on heap {}", stringify!(#type_name));
1152 let inst: #type_name = unsafe { std::mem::zeroed() };
1153 let inner_ptr: *mut #type_name = Box::into_raw(Box::new(inst));
1154 unsafe { *ctx_field = inner_ptr };
1155 0
1156 },
1157 None,
1158 true,
1159 #is_closed_method
1160 ).unwrap();
1161
1162 Self {
1163 inner: CResource::OwnedOnHeap(std::rc::Rc::new(resource)),
1164 }
1165 }
1166
1167 #[inline]
1168 pub fn new_zeroed_on_stack() -> Self {
1171 #[cfg(feature = "extra-logging")]
1172 log::debug!("creating zeroed empty resource on stack {}", stringify!(#type_name));
1173
1174 Self {
1175 inner: CResource::OwnedOnStack(std::mem::MaybeUninit::zeroed()),
1176 }
1177 }
1178 };
1179 if self.has_default_method() {
1180 let type_name = format_ident!("{}", self.type_name);
1181 let new_args: Vec<TokenStream> = self
1182 .fields
1183 .iter()
1184 .filter_map(|arg| {
1185 let arg_name = arg.as_ident();
1186 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
1187 .get_new_return_type(false, true);
1188 if arg_type.is_empty() {
1189 None
1190 } else {
1191 Some(quote! { #arg_name: #arg_type })
1192 }
1193 })
1194 .filter(|t| !t.is_empty())
1195 .collect();
1196 let init_args: Vec<TokenStream> = self
1197 .fields
1198 .iter()
1199 .map(|arg| {
1200 let arg_name = arg.as_ident();
1201 let value = ReturnType::new(arg.clone(), wrappers.clone())
1202 .handle_rs_to_c_return(quote! { #arg_name }, true);
1203 quote! { #value }
1204 })
1205 .filter(|t| !t.is_empty())
1206 .collect();
1207
1208 let generic_types: Vec<TokenStream> = self
1209 .fields
1210 .iter()
1211 .flat_map(|arg| {
1212 ReturnType::new(arg.clone(), wrappers.clone())
1213 .method_generics_for_where()
1214 .into_iter()
1215 })
1216 .collect_vec();
1217 let where_clause = if generic_types.is_empty() {
1218 quote! {}
1219 } else {
1220 quote! { <#(#generic_types),*> }
1221 };
1222
1223 let cloned_fields = self
1224 .fields
1225 .iter()
1226 .filter(|a| a.processing == ArgProcessing::Default)
1227 .cloned()
1228 .collect_vec();
1229 let lets: Vec<TokenStream> =
1230 Self::lets_for_copying_arguments(wrappers, &cloned_fields, false);
1231
1232 let is_closed_method = self.get_is_closed_method_quote();
1233
1234 vec![quote! {
1235 #[inline]
1236 pub fn new #where_clause(#(#new_args),*) -> Result<Self, AeronCError> {
1237 #(#lets)*
1238 let r_constructor = ManagedCResource::new(
1240 move |ctx_field| {
1241 let inst = #type_name { #(#init_args),* };
1242 let inner_ptr: *mut #type_name = Box::into_raw(Box::new(inst));
1243 unsafe { *ctx_field = inner_ptr };
1244 0
1245 },
1246 None,
1247 true,
1248 #is_closed_method
1249 )?;
1250
1251 Ok(Self {
1252 inner: CResource::OwnedOnHeap(std::rc::Rc::new(r_constructor)),
1253 })
1254 }
1255
1256 #zeroed_impl
1257 }]
1258 } else {
1259 vec![zeroed_impl]
1260 }
1261 } else {
1262 constructors
1263 }
1264 }
1265
1266 fn lets_for_copying_arguments(
1267 wrappers: &BTreeMap<String, CWrapper>,
1268 arguments: &Vec<Arg>,
1269 include_let_statements: bool,
1270 ) -> Vec<TokenStream> {
1271 arguments
1272 .iter()
1273 .enumerate()
1274 .filter_map(|(_idx, arg)| {
1275 if arg.is_double_mut_pointer() {
1276 None
1277 } else {
1278 let arg_name = arg.as_ident();
1279 let rtype = arg.as_type();
1280
1281 let fields = if arg.is_single_mut_pointer()
1283 && wrappers.contains_key(arg.c_type.split_whitespace().last().unwrap())
1284 {
1285 let arg_copy = format_ident!("{}_copy", arg.name);
1286 quote! {
1287 let #arg_copy = #arg_name.clone();
1288 }
1289 } else {
1290 quote! {}
1291 };
1292
1293 let return_type = ReturnType::new(arg.clone(), wrappers.clone());
1294
1295 if let ArgProcessing::StringWithLength(_args)
1296 | ArgProcessing::ByteArrayWithLength(_args) =
1297 &return_type.original.processing
1298 {
1299 return None;
1300 }
1301 if let ArgProcessing::Handler(args) = &return_type.original.processing {
1302 let arg1 = args[0].as_ident();
1303 let arg2 = args[1].as_ident();
1304 let value = return_type.handle_rs_to_c_return(quote! { #arg_name }, false);
1305
1306 if value.is_empty() {
1307 return None;
1308 }
1309
1310 if include_let_statements {
1311 return Some(quote! { #fields let (#arg1, #arg2)= (#value); });
1312 } else {
1313 return Some(fields);
1314 }
1315 }
1316
1317 let value = return_type.handle_rs_to_c_return(quote! { #arg_name }, false);
1318 if value.is_empty() {
1319 None
1320 } else {
1321 if include_let_statements {
1322 Some(quote! { #fields let #arg_name: #rtype = #value; })
1323 } else {
1324 return Some(fields);
1325 }
1326 }
1327 }
1328 })
1329 .filter(|t| !t.is_empty())
1330 .collect()
1331 }
1332
1333 fn constructor_fields(
1334 wrappers: &BTreeMap<String, CWrapper>,
1335 arguments: &Vec<Arg>,
1336 class_name: &String,
1337 ) -> Vec<TokenStream> {
1338 if class_name == "AeronAsyncDestination" {
1339 return vec![];
1340 }
1341
1342 arguments
1343 .iter()
1344 .enumerate()
1345 .filter_map(|(_idx, arg)| {
1346 if arg.is_double_mut_pointer() {
1347 None
1348 } else {
1349 let arg_name = arg.as_ident();
1350 let rtype = arg.as_type();
1351 if arg.is_single_mut_pointer()
1352 && wrappers.contains_key(arg.c_type.split_whitespace().last().unwrap())
1353 {
1354 let return_type = ReturnType::new(arg.clone(), wrappers.clone());
1355 let return_type = return_type.get_new_return_type(false, false);
1356
1357 let arg_copy = format_ident!("_{}", arg.name);
1358 Some(quote! {
1359 #arg_copy: Option<#return_type>,
1360 })
1361 } else {
1362 None
1363 }
1364 }
1365 })
1366 .collect()
1367 }
1368
1369 fn new_args(
1370 wrappers: &BTreeMap<String, CWrapper>,
1371 arguments: &Vec<Arg>,
1372 class_name: &String,
1373 set_none: bool,
1374 ) -> Vec<TokenStream> {
1375 if class_name == "AeronAsyncDestination" {
1376 return vec![];
1377 }
1378
1379 arguments
1380 .iter()
1381 .enumerate()
1382 .filter_map(|(_idx, arg)| {
1383 if arg.is_double_mut_pointer() {
1384 None
1385 } else {
1386 let arg_name = arg.as_ident();
1387 let rtype = arg.as_type();
1388 if arg.is_single_mut_pointer()
1389 && wrappers.contains_key(arg.c_type.split_whitespace().last().unwrap())
1390 {
1391 let arg_f = format_ident!("_{}", &arg.name);
1392 let arg_copy = format_ident!("{}_copy", &arg.name);
1393 if set_none {
1394 Some(quote! {
1395 #arg_f: None,
1396 })
1397 } else {
1398 Some(quote! {
1399 #arg_f: Some(#arg_copy),
1400 })
1401 }
1402 } else {
1403 None
1404 }
1405 }
1406 })
1407 .collect()
1408 }
1409
1410 fn find_close_method(&self, method: &Method) -> Option<&Method> {
1411 let mut close_method = None;
1412
1413 if ["_init", "_create", "_add"]
1415 .iter()
1416 .all(|find| !method.fn_name.contains(find))
1417 {
1418 return None;
1419 }
1420
1421 for name in ["_destroy", "_delete"] {
1422 let close_fn = format_ident!(
1423 "{}",
1424 method
1425 .fn_name
1426 .replace("_init", "_close")
1427 .replace("_create", name)
1428 .replace("_add_", "_remove_")
1429 );
1430 let method = self
1431 .methods
1432 .iter()
1433 .find(|m| close_fn.to_string().contains(&m.fn_name));
1434 if method.is_some() {
1435 close_method = method;
1436 break;
1437 }
1438 }
1439 close_method
1440 }
1441
1442 fn has_default_method(&self) -> bool {
1443 let has_init_method = !self
1444 .methods
1445 .iter()
1446 .any(|m| m.arguments.iter().any(|arg| arg.is_double_mut_pointer()));
1447
1448 has_init_method
1449 && !self.fields.iter().any(|arg| arg.name.starts_with("_"))
1450 && !self.fields.is_empty()
1451 }
1452}
1453
1454fn get_docs(
1455 docs: &BTreeSet<String>,
1456 wrappers: &BTreeMap<String, CWrapper>,
1457 arguments: Option<&Vec<TokenStream>>,
1458) -> Vec<TokenStream> {
1459 let mut first_param = true;
1460 docs.iter()
1461 .flat_map(|d| d.lines())
1462 .filter(|s| {
1463 arguments.is_none()
1464 || !s.contains("@param")
1465 || (s.contains("@param")
1466 && arguments.unwrap().iter().any(|a| {
1467 s.contains(
1468 format!(" {}", a.to_string().split_whitespace().next().unwrap())
1469 .as_str(),
1470 )
1471 }))
1472 })
1473 .map(|doc| {
1474 let mut doc = doc.to_string();
1475
1476 if first_param && doc.contains("@param") {
1477 doc = format!("# Parameters\n{}", doc);
1478 first_param = false;
1479 }
1480
1481 if doc.contains("@param") {
1482 doc = regex::Regex::new("@param\\s+([^ ]+)")
1483 .unwrap()
1484 .replace(doc.as_str(), "\n - `$1`")
1485 .to_string();
1486 }
1487
1488 doc = doc
1489 .replace("@return", "\n# Return\n")
1490 .replace("<p>", "\n")
1491 .replace("</p>", "\n");
1492
1493 doc = wrappers.values().fold(doc, |acc, v| {
1494 acc.replace(&v.type_name, &format!("`{}`", v.class_name))
1495 });
1496
1497 if doc.contains("@deprecated") {
1498 quote! {
1499 #[deprecated]
1500 #[doc = #doc]
1501 }
1502 } else {
1503 quote! {
1504 #[doc = #doc]
1505 }
1506 }
1507 })
1508 .collect()
1509}
1510
1511pub fn generate_handlers(handler: &mut CHandler, bindings: &CBinding) -> TokenStream {
1512 if handler
1513 .args
1514 .iter()
1515 .any(|arg| arg.is_primitive() && arg.is_mut_pointer())
1516 {
1517 return quote! {};
1518 }
1519
1520 let fn_name = format_ident!("{}_callback", handler.type_name);
1521 let closure_fn_name = format_ident!("{}_callback_for_once_closure", handler.type_name);
1522 let doc_comments: Vec<TokenStream> = handler
1523 .docs
1524 .iter()
1525 .flat_map(|doc| doc.lines())
1526 .map(|line| quote! { #[doc = #line] })
1527 .collect();
1528
1529 let closure = handler
1530 .args
1531 .iter()
1532 .find(|a| a.is_c_void())
1533 .unwrap()
1534 .name
1535 .clone();
1536 let closure_name = format_ident!("{}", closure);
1537 let closure_type_name = format_ident!("{}Callback", snake_to_pascal_case(&handler.type_name));
1538 let closure_return_type = handler.return_type.as_type();
1539
1540 let logger_type_name = format_ident!("{}Logger", snake_to_pascal_case(&handler.type_name));
1541
1542 let handle_method_name = format_ident!(
1543 "handle_{}",
1544 &handler.type_name[..handler.type_name.len() - 2]
1545 );
1546
1547 let no_method_name = format_ident!(
1548 "no_{}_handler",
1549 &handler.type_name[..handler.type_name.len() - 2]
1550 .replace("_on_", "_")
1551 .replace("aeron_", "")
1552 );
1553
1554 let args: Vec<TokenStream> = handler
1555 .args
1556 .iter()
1557 .map(|arg| {
1558 let arg_name = arg.as_ident();
1559 let arg_type: Type = arg.as_type();
1561 quote! { #arg_name: #arg_type }
1562 })
1563 .filter(|t| !t.is_empty())
1564 .collect();
1565
1566 let converted_args: Vec<TokenStream> = handler
1567 .args
1568 .iter()
1569 .filter_map(|arg| {
1570 let name = &arg.name;
1571 let arg_name = arg.as_ident();
1572 if name != &closure {
1573 let return_type = ReturnType::new(arg.clone(), bindings.wrappers.clone());
1574 Some(return_type.handle_c_to_rs_return(quote! {#arg_name}, false, false))
1575 } else {
1576 None
1577 }
1578 })
1579 .filter(|t| !t.is_empty())
1580 .collect();
1581
1582 let closure_args: Vec<TokenStream> = handler
1583 .args
1584 .iter()
1585 .filter_map(|arg| {
1586 let name = &arg.name;
1587 if name == &closure {
1588 return None;
1589 }
1590
1591 let return_type = ReturnType::new(arg.clone(), bindings.wrappers.clone());
1592 let type_name = return_type.get_new_return_type(false, false);
1593 let field_name = format_ident!("{}", name);
1594 if type_name.is_empty() {
1595 None
1596 } else {
1597 Some(quote! {
1598 #field_name: #type_name
1599 })
1600 }
1601 })
1602 .filter(|t| !t.is_empty())
1603 .collect();
1604
1605 let mut log_field_names = vec![];
1606 let closure_args_in_logger: Vec<TokenStream> = handler
1607 .args
1608 .iter()
1609 .filter_map(|arg| {
1610 let name = &arg.name;
1611 if name == &closure {
1612 return None;
1613 }
1614
1615 let return_type = ReturnType::new(arg.clone(), bindings.wrappers.clone());
1616 let type_name = return_type.get_new_return_type(false, false);
1617 let field_name = format_ident!("{}", name);
1618 if type_name.is_empty() {
1619 None
1620 } else {
1621 log_field_names.push({
1622 Some(quote! { format!("{} : {:?}", stringify!(#field_name), #field_name) })
1623 });
1624
1625 Some(quote! {
1626 #field_name: #type_name
1627 })
1628 }
1629 })
1630 .filter(|t| !t.is_empty())
1631 .collect();
1632
1633 if log_field_names.is_empty() {
1634 log_field_names.push(Some(quote! { "" }));
1635 }
1636
1637 let fn_mut_args: Vec<TokenStream> = handler
1638 .args
1639 .iter()
1640 .filter_map(|arg| {
1641 let name = &arg.name;
1642 if name == &closure {
1643 return None;
1644 }
1645
1646 let return_type = ReturnType::new(arg.clone(), bindings.wrappers.clone());
1647 let type_name = return_type.get_new_return_type(false, false);
1648 if arg.is_single_mut_pointer() && arg.is_primitive() {
1649 let owned_type: Type =
1650 parse_str(arg.c_type.split_whitespace().last().unwrap()).unwrap();
1651 return Some(quote! { #owned_type });
1652 } else {
1653 return Some(quote! {
1654 #type_name
1655 });
1656 }
1657 })
1658 .filter(|t| !t.is_empty())
1659 .collect();
1660
1661 handler.fn_mut_signature = quote! {
1662 FnMut(#(#fn_mut_args),*) -> #closure_return_type
1663 };
1664 handler.closure_type_name = quote! {
1665 #closure_type_name
1666 };
1667
1668 let logger_return_type = if closure_return_type.to_token_stream().to_string().eq("()") {
1669 closure_return_type.clone().to_token_stream()
1670 } else {
1671 quote! {
1672 unimplemented!()
1673 }
1674 };
1675
1676 let wrapper_closure_args: Vec<TokenStream> = handler
1677 .args
1678 .iter()
1679 .filter_map(|arg| {
1680 let name = &arg.name;
1681 if name == &closure {
1682 return None;
1683 }
1684
1685 let field_name = format_ident!("{}", name);
1686 let return_type = ReturnType::new(arg.clone(), bindings.wrappers.clone())
1687 .get_new_return_type(false, false);
1688 if return_type.is_empty() {
1689 None
1690 } else {
1691 Some(quote! { #field_name })
1692 }
1693 })
1694 .filter(|t| !t.is_empty())
1695 .collect();
1696
1697 quote! {
1698 #(#doc_comments)*
1699 pub trait #closure_type_name {
1703 fn #handle_method_name(&mut self, #(#closure_args),*) -> #closure_return_type;
1704 }
1705
1706 pub struct #logger_type_name;
1707 impl #closure_type_name for #logger_type_name {
1708 fn #handle_method_name(&mut self, #(#closure_args_in_logger),*) -> #closure_return_type {
1709 log::info!("{}(\n\t{}\n)",
1710 stringify!(#handle_method_name),
1711 [#(#log_field_names),*].join(",\n\t"),
1712 );
1713 #logger_return_type
1714 }
1715 }
1716
1717 unsafe impl Send for #logger_type_name {}
1718 unsafe impl Sync for #logger_type_name {}
1719
1720 impl Handlers {
1721 pub fn #no_method_name() -> Option<&'static Handler<#logger_type_name>> {
1723 None::<&Handler<#logger_type_name>>
1724 }
1725 }
1726
1727 #[allow(dead_code)]
1729 #(#doc_comments)*
1730 unsafe extern "C" fn #fn_name<F: #closure_type_name>(
1731 #(#args),*
1732 ) -> #closure_return_type
1733 {
1734 #[cfg(debug_assertions)]
1735 if #closure_name.is_null() {
1736 unimplemented!("closure should not be null")
1737 }
1738 #[cfg(feature = "extra-logging")]
1739 {
1740 log::debug!("calling {}", stringify!(#handle_method_name));
1741 }
1742 let closure: &mut F = &mut *(#closure_name as *mut F);
1743 closure.#handle_method_name(#(#converted_args),*)
1744 }
1745
1746 #[allow(dead_code)]
1748 #(#doc_comments)*
1749 unsafe extern "C" fn #closure_fn_name<F: FnMut(#(#fn_mut_args),*) -> #closure_return_type>(
1750 #(#args),*
1751 ) -> #closure_return_type
1752 {
1753 #[cfg(debug_assertions)]
1754 if #closure_name.is_null() {
1755 unimplemented!("closure should not be null")
1756 }
1757 #[cfg(feature = "extra-logging")]
1758 {
1759 log::debug!("calling {}", stringify!(#closure_fn_name));
1760 }
1761 let closure: &mut F = &mut *(#closure_name as *mut F);
1762 closure(#(#converted_args),*)
1763 }
1764
1765 }
1766}
1767
1768pub fn generate_rust_code(
1769 wrapper: &CWrapper,
1770 wrappers: &BTreeMap<String, CWrapper>,
1771 include_common_code: bool,
1772 include_clippy: bool,
1773 include_aeron_client_registering_resource_t: bool,
1774 closure_handlers: &Vec<CHandler>,
1775) -> TokenStream {
1776 let class_name = Ident::new(&wrapper.class_name, proc_macro2::Span::call_site());
1777 let type_name = Ident::new(&wrapper.type_name, proc_macro2::Span::call_site());
1778
1779 let mut additional_outer_impls = vec![];
1780
1781 let methods = wrapper.generate_methods(wrappers, closure_handlers, &mut additional_outer_impls);
1782 let mut constructor_fields = vec![];
1783 let mut new_ref_set_none = vec![];
1784 let constructor =
1785 wrapper.generate_constructor(wrappers, &mut constructor_fields, &mut new_ref_set_none);
1786
1787 let async_impls = if wrapper.type_name.starts_with("aeron_async_")
1788 || wrapper.type_name.starts_with("aeron_archive_async_")
1789 {
1790 let new_method = wrapper
1791 .methods
1792 .iter()
1793 .find(|m| m.fn_name == wrapper.without_name);
1794
1795 if let Some(new_method) = new_method {
1796 let main_type = &wrapper
1797 .type_name
1798 .replace("_async_", "_")
1799 .replace("_add_", "_");
1800 let main = get_possible_wrappers(main_type)
1801 .iter()
1802 .filter_map(|f| wrappers.get(f))
1803 .next()
1804 .expect(&format!("failed to find main type {}", main_type));
1805
1806 let poll_method = main
1807 .methods
1808 .iter()
1809 .find(|m| m.fn_name == format!("{}_poll", wrapper.without_name))
1810 .unwrap();
1811
1812 let main_class_name = format_ident!("{}", main.class_name);
1813 let async_class_name = format_ident!("{}", wrapper.class_name);
1814 let poll_method_name = format_ident!("{}_poll", wrapper.without_name);
1815 let new_method_name = format_ident!("{}", new_method.fn_name);
1816
1817 let client_class = wrappers
1818 .get(
1819 new_method
1820 .arguments
1821 .iter()
1822 .skip(1)
1823 .next()
1824 .unwrap()
1825 .c_type
1826 .split_whitespace()
1827 .last()
1828 .unwrap(),
1829 )
1830 .unwrap();
1831 let client_type = format_ident!("{}", client_class.class_name);
1832 let client_type_method_name = format_ident!(
1833 "{}",
1834 new_method
1835 .fn_name
1836 .replace(&format!("{}_", client_class.without_name), "")
1837 );
1838 let client_type_method_name_without_async = format_ident!(
1839 "{}",
1840 new_method
1841 .fn_name
1842 .replace(&format!("{}_", client_class.without_name), "")
1843 .replace("async_", "")
1844 );
1845
1846 let init_args: Vec<TokenStream> = poll_method
1847 .arguments
1848 .iter()
1849 .enumerate()
1850 .filter_map(|(idx, arg)| {
1851 if idx == 0 {
1852 Some(quote! { ctx_field })
1853 } else {
1854 let arg_name = arg.as_ident();
1855 let arg_name = ReturnType::new(arg.clone(), wrappers.clone())
1856 .handle_rs_to_c_return(quote! { #arg_name }, false);
1857 Some(quote! { #arg_name })
1858 }
1859 })
1860 .filter(|t| !t.is_empty())
1861 .collect();
1862
1863 let new_args: Vec<TokenStream> = poll_method
1864 .arguments
1865 .iter()
1866 .enumerate()
1867 .filter_map(|(idx, arg)| {
1868 if idx == 0 {
1869 None
1870 } else {
1871 let arg_name = arg.as_ident();
1872 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
1873 .get_new_return_type(false, true);
1874 if arg_type.clone().into_token_stream().is_empty() {
1875 None
1876 } else {
1877 Some(quote! { #arg_name: #arg_type })
1878 }
1879 }
1880 })
1881 .filter(|t| !t.is_empty())
1882 .collect();
1883
1884 let async_init_args: Vec<TokenStream> = new_method
1885 .arguments
1886 .iter()
1887 .enumerate()
1888 .filter_map(|(idx, arg)| {
1889 if idx == 0 {
1890 Some(quote! { ctx_field })
1891 } else {
1892 let arg_name = arg.as_ident();
1893 let arg_name = ReturnType::new(arg.clone(), wrappers.clone())
1894 .handle_rs_to_c_return(quote! { #arg_name }, false);
1895 Some(quote! { #arg_name })
1896 }
1897 })
1898 .filter(|t| !t.is_empty())
1899 .collect();
1900
1901 let generic_types: Vec<TokenStream> = new_method
1902 .arguments
1903 .iter()
1904 .flat_map(|arg| {
1905 ReturnType::new(arg.clone(), wrappers.clone())
1906 .method_generics_for_where()
1907 .into_iter()
1908 })
1909 .collect_vec();
1910 let where_clause_async = if generic_types.is_empty() {
1911 quote! {}
1912 } else {
1913 quote! { <#(#generic_types),*> }
1914 };
1915 let generic_types: Vec<TokenStream> = poll_method
1916 .arguments
1917 .iter()
1918 .flat_map(|arg| {
1919 ReturnType::new(arg.clone(), wrappers.clone())
1920 .method_generics_for_where()
1921 .into_iter()
1922 })
1923 .collect_vec();
1924 let where_clause_main = if generic_types.is_empty() {
1925 quote! {}
1926 } else {
1927 quote! { <#(#generic_types),*> }
1928 };
1929 let async_new_args: Vec<TokenStream> = new_method
1930 .arguments
1931 .iter()
1932 .enumerate()
1933 .filter_map(|(idx, arg)| {
1934 if idx == 0 {
1935 None
1936 } else {
1937 let arg_name = arg.as_ident();
1938 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
1939 .get_new_return_type(false, true);
1940 if arg_type.clone().into_token_stream().is_empty() {
1941 None
1942 } else {
1943 Some(quote! { #arg_name: #arg_type })
1944 }
1945 }
1946 })
1947 .filter(|t| !t.is_empty())
1948 .collect();
1949
1950 let async_dependancies = async_new_args
1951 .iter()
1952 .filter(|a| {
1953 a.to_string().contains(" : Aeron") || a.to_string().contains(" : & Aeron")
1954 })
1955 .map(|e| {
1956 let var_name =
1957 format_ident!("{}", e.to_string().split_whitespace().next().unwrap());
1958 quote! {
1959 result.inner.add_dependency(#var_name.clone());
1960 }
1961 })
1962 .collect_vec();
1963
1964 let async_new_args_for_client = async_new_args.iter().skip(1).cloned().collect_vec();
1965
1966 let async_new_args_name_only: Vec<TokenStream> = new_method
1967 .arguments
1968 .iter()
1969 .enumerate()
1970 .filter_map(|(idx, arg)| {
1971 if idx < 2 {
1972 None
1973 } else {
1974 let arg_name = arg.as_ident();
1975 let arg_type = ReturnType::new(arg.clone(), wrappers.clone())
1976 .get_new_return_type(false, false);
1977 if arg_type.clone().into_token_stream().is_empty() {
1978 None
1979 } else {
1980 Some(quote! { #arg_name })
1981 }
1982 }
1983 })
1984 .filter(|t| !t.is_empty())
1985 .collect();
1986
1987 quote! {
1988 impl #main_class_name {
1989 #[inline]
1990 pub fn new #where_clause_main (#(#new_args),*) -> Result<Self, AeronCError> {
1991 let resource = ManagedCResource::new(
1992 move |ctx_field| unsafe {
1993 #poll_method_name(#(#init_args),*)
1994 },
1995 None,
1996 false,
1997 None,
1998 )?;
1999 Ok(Self {
2000 inner: CResource::OwnedOnHeap(std::rc::Rc::new(resource)),
2001 })
2002 }
2003 }
2004
2005 impl #client_type {
2006 #[inline]
2007 pub fn #client_type_method_name #where_clause_async(&self, #(#async_new_args_for_client),*) -> Result<#async_class_name, AeronCError> {
2008 let mut result = #async_class_name::new(self, #(#async_new_args_name_only),*);
2009 if let Ok(result) = &mut result {
2010 result.inner.add_dependency(self.clone());
2011 }
2012
2013 result
2014 }
2015 }
2016
2017 impl #client_type {
2018 #[inline]
2019 pub fn #client_type_method_name_without_async #where_clause_async(&self #(
2020 , #async_new_args_for_client)*, timeout: std::time::Duration) -> Result<#main_class_name, AeronCError> {
2021 let start = std::time::Instant::now();
2022 loop {
2023 if let Ok(poller) = #async_class_name::new(self, #(#async_new_args_name_only),*) {
2024 while start.elapsed() <= timeout {
2025 if let Some(result) = poller.poll()? {
2026 return Ok(result);
2027 }
2028 #[cfg(debug_assertions)]
2029 std::thread::sleep(std::time::Duration::from_millis(10));
2030 }
2031 }
2032 if start.elapsed() > timeout {
2033 log::error!("failed async poll for {:?}", self);
2034 return Err(AeronErrorType::TimedOut.into());
2035 }
2036 #[cfg(debug_assertions)]
2037 std::thread::sleep(std::time::Duration::from_millis(10));
2038 }
2039 }
2040 }
2041
2042 impl #async_class_name {
2043 #[inline]
2044 pub fn new #where_clause_async (#(#async_new_args),*) -> Result<Self, AeronCError> {
2045 let resource_async = ManagedCResource::new(
2046 move |ctx_field| unsafe {
2047 #new_method_name(#(#async_init_args),*)
2048 },
2049 None,
2050 false,
2051 None,
2052 )?;
2053 let result = Self {
2054 inner: CResource::OwnedOnHeap(std::rc::Rc::new(resource_async)),
2055 };
2056 #(#async_dependancies)*
2057 Ok(result)
2058 }
2059
2060 pub fn poll(&self) -> Result<Option<#main_class_name>, AeronCError> {
2061
2062 let mut result = #main_class_name::new(self);
2063 if let Ok(result) = &mut result {
2064 unsafe {
2065 for d in (&mut *self.inner.as_owned().unwrap().dependencies.get()).iter_mut() {
2066 result.inner.add_dependency(d.clone());
2067 }
2068 result.inner.as_owned().unwrap().auto_close.set(true);
2069 }
2070 }
2071
2072 match result {
2073 Ok(result) => Ok(Some(result)),
2074 Err(AeronCError {code }) if code == 0 => {
2075 Ok(None) }
2077 Err(e) => Err(e)
2078 }
2079 }
2080
2081 pub fn poll_blocking(&self, timeout: std::time::Duration) -> Result<#main_class_name, AeronCError> {
2082 if let Some(result) = self.poll()? {
2083 return Ok(result);
2084 }
2085
2086 let time = std::time::Instant::now();
2087 while time.elapsed() < timeout {
2088 if let Some(result) = self.poll()? {
2089 return Ok(result);
2090 }
2091 #[cfg(debug_assertions)]
2092 std::thread::sleep(std::time::Duration::from_millis(10));
2093 }
2094 log::error!("failed async poll for {:?}", self);
2095 Err(AeronErrorType::TimedOut.into())
2096 }
2097 }
2098 }
2099 } else {
2100 quote! {}
2101 }
2102 } else {
2103 quote! {}
2104 };
2105
2106 let mut additional_impls = vec![];
2107
2108 if let Some(close_method) = wrapper.get_close_method() {
2109 if !wrapper.methods.iter().any(|m| m.fn_name.contains("_init")) {
2110 let close_method_call = if close_method.arguments.len() > 1 {
2111 let ident = format_ident!("close_with_no_args");
2112 quote! {#ident}
2113 } else {
2114 let ident = format_ident!("{}", close_method.struct_method_name);
2115 quote! {#ident}
2116 };
2117 let is_closed_method = if wrapper.get_is_closed_method().is_some() {
2118 quote! { self.is_closed() }
2119 } else {
2120 quote! { false }
2121 };
2122
2123 additional_impls.push(quote! {
2124 impl Drop for #class_name {
2125 fn drop(&mut self) {
2126 if let Some(inner) = self.inner.as_owned() {
2127 if (inner.cleanup.is_none() ) && std::rc::Rc::strong_count(inner) == 1 && !inner.is_closed_already_called() {
2128 if inner.auto_close.get() {
2129 log::info!("auto closing {}", stringify!(#class_name));
2130 let result = self.#close_method_call();
2131 log::debug!("result {:?}", result);
2132 } else {
2133 #[cfg(feature = "extra-logging")]
2134 log::warn!("{} not closed", stringify!(#class_name));
2135 }
2136 }
2137 }
2138 }
2139 }
2140 });
2141 }
2142 }
2143
2144 let common_code = if !include_common_code {
2145 quote! {}
2146 } else {
2147 TokenStream::from_str(COMMON_CODE).unwrap()
2148 };
2149 let warning_code = if !include_common_code {
2150 quote! {}
2151 } else {
2152 let mut code = String::new();
2153
2154 if include_clippy {
2155 code.push_str(
2156 " #![allow(non_upper_case_globals)]
2157 #![allow(non_camel_case_types)]
2158 #![allow(non_snake_case)]
2159 #![allow(clippy::all)]
2160 #![allow(unused_variables)]
2161 #![allow(unused_unsafe)]
2162",
2163 );
2164 }
2165
2166 if include_aeron_client_registering_resource_t {
2167 code.push_str(
2168 "
2169 type aeron_client_registering_resource_t = aeron_client_registering_resource_stct;
2170",
2171 );
2172 }
2173
2174 TokenStream::from_str(code.as_str()).unwrap()
2175 };
2176 let class_docs: Vec<TokenStream> = wrapper
2177 .docs
2178 .iter()
2179 .map(|doc| {
2180 quote! {
2181 #[doc = #doc]
2182 }
2183 })
2184 .collect();
2185
2186 let mut debug_fields = vec![];
2187 let fields = wrapper.generate_fields(&wrappers, &mut debug_fields);
2188
2189 let default_impl = if wrapper.has_default_method()
2190 && !constructor
2191 .iter()
2192 .map(|x| x.to_string())
2193 .join("")
2194 .trim()
2195 .is_empty()
2196 {
2197 quote! {
2208 impl Default for #class_name {
2210 fn default() -> Self {
2211 #class_name::new_zeroed_on_heap()
2212 }
2213 }
2214
2215 impl #class_name {
2216 pub fn clone_struct(&self) -> Self {
2225 let copy = Self::default();
2226 copy.get_inner_mut().clone_from(self.deref());
2227 copy
2228 }
2229 }
2230 }
2231 } else {
2232 quote! {}
2233 };
2234
2235 let is_closed_method = wrapper.get_is_closed_method_quote();
2236
2237 quote! {
2238 #warning_code
2239
2240 #(#class_docs)*
2241 #[derive(Clone)]
2242 pub struct #class_name {
2243 inner: CResource<#type_name>,
2244 #(#constructor_fields)*
2245 }
2246
2247 impl core::fmt::Debug for #class_name {
2248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2249 if self.inner.get().is_null() {
2250 f.debug_struct(stringify!(#class_name))
2251 .field("inner", &"null")
2252 .finish()
2253 } else {
2254 f.debug_struct(stringify!(#class_name))
2255 .field("inner", &self.inner)
2256 #(#debug_fields)*
2257 .finish()
2258 }
2259 }
2260 }
2261
2262 impl #class_name {
2263 #(#constructor)*
2264 #(#fields)*
2265 #(#methods)*
2266
2267 #[inline(always)]
2268 pub fn get_inner(&self) -> *mut #type_name {
2269 self.inner.get()
2270 }
2271
2272 #[inline(always)]
2273 pub fn get_inner_mut(&self) -> &mut #type_name {
2274 unsafe { &mut *self.inner.get() }
2275 }
2276
2277 #[inline(always)]
2278 pub fn get_inner_ref(&self) -> & #type_name {
2279 unsafe { &*self.inner.get() }
2280 }
2281 }
2282
2283 impl std::ops::Deref for #class_name {
2284 type Target = #type_name;
2285
2286 fn deref(&self) -> &Self::Target {
2287 self.get_inner_ref()
2288 }
2289 }
2290
2291 impl From<*mut #type_name> for #class_name {
2292 #[inline]
2293 fn from(value: *mut #type_name) -> Self {
2294 #class_name {
2295 inner: CResource::Borrowed(value),
2296 #(#new_ref_set_none)*
2297 }
2298 }
2299 }
2300
2301 impl From<#class_name> for *mut #type_name {
2302 #[inline]
2303 fn from(value: #class_name) -> Self {
2304 value.get_inner()
2305 }
2306 }
2307
2308 impl From<&#class_name> for *mut #type_name {
2309 #[inline]
2310 fn from(value: &#class_name) -> Self {
2311 value.get_inner()
2312 }
2313 }
2314
2315 impl From<#class_name> for #type_name {
2316 #[inline]
2317 fn from(value: #class_name) -> Self {
2318 unsafe { *value.get_inner().clone() }
2319 }
2320 }
2321
2322 impl From<*const #type_name> for #class_name {
2323 #[inline]
2324 fn from(value: *const #type_name) -> Self {
2325 #class_name {
2326 inner: CResource::Borrowed(value as *mut #type_name),
2327 #(#new_ref_set_none)*
2328 }
2329 }
2330 }
2331
2332 impl From<#type_name> for #class_name {
2333 #[inline]
2334 fn from(mut value: #type_name) -> Self {
2335 #class_name {
2336 inner: CResource::Borrowed(&mut value as *mut #type_name),
2337 #(#new_ref_set_none)*
2338 }
2339 }
2340 }
2341
2342 #(#additional_impls)*
2343
2344 #async_impls
2345 #default_impl
2346 #common_code
2347 }
2348}