@@ -97,6 +97,34 @@ impl Struct {
9797 }
9898
9999 fn to_tokens ( & self , output : & mut Output ) {
100+ match self . attrs . c_definition {
101+ true => self . to_tokens_c_definition ( output) ,
102+ false => self . to_tokens_rust_definition ( output) ,
103+ }
104+ }
105+
106+ fn to_tokens_c_definition ( & self , output : & mut Output ) {
107+ assert ! (
108+ self . attrs. event_name. is_none( ) ,
109+ "C struct definitions cannot be directly used as events."
110+ ) ;
111+
112+ let ident = & self . ident ;
113+ let extra_attrs = & self . attrs . extra ;
114+ let c_definition_attrs = & self . attrs . c_definition_attrs ;
115+ let builder_fields = self . fields . iter ( ) . map ( Field :: builder) ;
116+
117+ output. c_ffi . extend ( quote ! (
118+ #c_definition_attrs
119+ #[ derive( Clone , Debug ) ]
120+ #extra_attrs
121+ pub struct #ident {
122+ #( #builder_fields) *
123+ }
124+ ) ) ;
125+ }
126+
127+ fn to_tokens_rust_definition ( & self , output : & mut Output ) {
100128 let Self {
101129 attrs,
102130 ident,
@@ -173,6 +201,12 @@ impl Struct {
173201 }
174202 ) ) ;
175203
204+ if ident_str == "ConnectionMeta" {
205+ output. connection_meta_c_type = attrs. associated_c_type . clone ( ) ;
206+ } else if ident_str == "ConnectionInfo" {
207+ output. connection_info_c_type = attrs. associated_c_type . clone ( ) ;
208+ }
209+
176210 if let Some ( event_name) = attrs. event_name . as_ref ( ) {
177211 output. api . extend ( quote ! (
178212 #allow_deprecated
@@ -296,6 +330,12 @@ impl Struct {
296330 self . output #lock. push( out) ;
297331 }
298332 ) ) ;
333+
334+ assert ! (
335+ attrs. associated_c_type. is_empty( ) ,
336+ "C types cannot be associated with endpoint events. Publishing endpoint \
337+ events from the C API is not yet supported."
338+ ) ;
299339 }
300340 Subject :: Connection => {
301341 output. subscriber . extend ( quote ! (
@@ -405,6 +445,15 @@ impl Struct {
405445 }
406446 }
407447 ) ) ;
448+
449+ if output. config . c_api {
450+ let c_type = & attrs. associated_c_type ;
451+ assert ! (
452+ !c_type. is_empty( ) ,
453+ "Events must specify an associated C type with the #[c_type()] \
454+ attribute.",
455+ ) ;
456+ }
408457 }
409458 }
410459 }
@@ -432,18 +481,41 @@ impl Enum {
432481 }
433482
434483 fn to_tokens ( & self , output : & mut Output ) {
484+ assert ! (
485+ self . attrs. event_name. is_none( ) ,
486+ "enum events are not currently supported"
487+ ) ;
488+
489+ match self . attrs . c_definition {
490+ true => self . to_tokens_c_definition ( output) ,
491+ false => self . to_tokens_rust_definition ( output) ,
492+ }
493+ }
494+
495+ fn to_tokens_c_definition ( & self , output : & mut Output ) {
496+ let ident = & self . ident ;
497+ let extra_attrs = & self . attrs . extra ;
498+ let c_definition_attrs = & self . attrs . c_definition_attrs ;
499+ let builder_fields = self . variants . iter ( ) . map ( Variant :: builder) ;
500+
501+ output. c_ffi . extend ( quote ! (
502+ #c_definition_attrs
503+ #[ derive( Clone , Debug ) ]
504+ #extra_attrs
505+ pub enum #ident {
506+ #( #builder_fields) *
507+ }
508+ ) ) ;
509+ }
510+
511+ fn to_tokens_rust_definition ( & self , output : & mut Output ) {
435512 let Self {
436513 attrs,
437514 ident,
438515 generics,
439516 variants,
440517 } = self ;
441518
442- assert ! (
443- attrs. event_name. is_none( ) ,
444- "enum events are not currently supported"
445- ) ;
446-
447519 let derive_attrs = & attrs. derive_attrs ;
448520 let builder_derive_attrs = & attrs. builder_derive_attrs ;
449521 let extra_attrs = & attrs. extra ;
@@ -543,6 +615,9 @@ pub struct ContainerAttrs {
543615 pub checkpoint : Vec < Checkpoint > ,
544616 pub measure_counter : Vec < Metric > ,
545617 pub extra : TokenStream ,
618+ pub associated_c_type : TokenStream ,
619+ pub c_definition : bool ,
620+ pub c_definition_attrs : TokenStream ,
546621}
547622
548623impl ContainerAttrs {
@@ -563,6 +638,9 @@ impl ContainerAttrs {
563638 checkpoint : vec ! [ ] ,
564639 measure_counter : vec ! [ ] ,
565640 extra : quote ! ( ) ,
641+ associated_c_type : quote ! ( ) ,
642+ c_definition : false ,
643+ c_definition_attrs : TokenStream :: default ( ) ,
566644 } ;
567645
568646 for attr in attrs {
@@ -591,6 +669,13 @@ impl ContainerAttrs {
591669 v. checkpoint . push ( attr. parse_args ( ) . unwrap ( ) ) ;
592670 } else if path. is_ident ( "measure_counter" ) {
593671 v. measure_counter . push ( attr. parse_args ( ) . unwrap ( ) ) ;
672+ } else if path. is_ident ( "c_type" ) {
673+ v. associated_c_type = attr. parse_args ( ) . unwrap ( ) ;
674+ } else if path. is_ident ( "repr" ) {
675+ // Structs/enums with the #[repr(...)] attribute are assumed to be defined for the
676+ // C API.
677+ v. c_definition = true ;
678+ attr. to_tokens ( & mut v. c_definition_attrs ) ;
594679 } else {
595680 attr. to_tokens ( & mut v. extra )
596681 }
0 commit comments