1use genco::prelude::*;
2
3use mproto_codegen::codegen::{
4 name_util::{camel_to_snake_case, snake_to_upper_camel_case},
5 rust::{rust_type_default_value, rust_type_param_list},
6};
7
8use crate::{
9 Database,
10 ast::{Interface, InterfaceObject},
11};
12
13pub use project::{rust_project_gen, rust_proto_package_gen, rust_role_impl_gen};
14
15mod project;
16
17fn import_qualified(module: Option<impl AsRef<str>>, name: impl AsRef<str>) -> rust::Tokens {
18 if let Some(module) = module {
19 quote! { $(rust::import(format!("{}_modrpc", module.as_ref()), name.as_ref())) }
20 } else {
21 quote! { $(name.as_ref()) }
22 }
23}
24
25pub fn rust_interface(db: &Database, interface: &Interface) -> rust::Tokens {
26 let interface_builder = &rust::import("modrpc", "InterfaceBuilder");
27 let interface_event = &rust::import("modrpc", "InterfaceEvent");
28 let interface_schema = &rust::import("modrpc", "InterfaceSchema");
29
30 let mproto_cx = &mproto_codegen::codegen::CodegenCx::new_with_type_params(
31 db.mproto_db(),
32 Some("crate::proto"),
33 true,
34 &interface.type_params,
35 );
36
37 let mut events_field_tokens = rust::Tokens::new();
38 let mut events_constr_tokens = rust::Tokens::new();
39 for events_list in &interface.events {
40 for event in &events_list.events {
41 let event_type_tokens =
42 mproto_codegen::codegen::rust::rust_type_tokens(mproto_cx, &event.ty);
43 events_field_tokens = quote! {
44 $events_field_tokens
45 pub $(&event.name): $interface_event<$event_type_tokens>,
46 };
47
48 let event_name_tokens = quote! { $("\"")$(&event.name)$("\"") };
49 events_constr_tokens = quote! {
50 $events_constr_tokens
51 $(&event.name): ib.event($event_name_tokens),
52 };
53 }
54 }
55
56 let mut objects_field_tokens = rust::Tokens::new();
57 let mut objects_constr_tokens = rust::Tokens::new();
58 for object in &interface.objects {
59 if db.lookup_interface(&object.construct).is_none() {
60 panic!("failed to lookup interface '{}'", object.construct.name);
61 };
62
63 let object_type_args =
64 &mproto_codegen::codegen::rust::rust_type_arg_list(mproto_cx, &object.type_args, None);
65
66 let object_interface_import = import_qualified(
67 object.construct.module.as_ref(),
68 format!("{}Interface", object.construct.name),
69 );
70 objects_field_tokens = quote! {
71 $objects_field_tokens
72 pub $(&object.name): $(object_interface_import)$(object_type_args),
73 };
74
75 objects_constr_tokens = quote! {
76 $objects_constr_tokens
77 $(&object.name): $(&object.construct.name)Interface::new(ib),
78 };
79 }
80
81 let type_params = &rust_type_param_list(&interface.type_params, None, None);
82
83 let tokens: rust::Tokens = quote! {
84 pub struct $(&interface.name)Interface$(type_params) {
85 $events_field_tokens
86 $objects_field_tokens
87 }
88
89 impl$(type_params) $interface_schema for $(&interface.name)Interface$(type_params) {
90 fn new(ib: &mut $interface_builder) -> Self {
91 Self {
92 $events_constr_tokens
93 $objects_constr_tokens
94 }
95 }
96 }
97 };
98
99 tokens
100}
101
102pub fn rust_interface_role(db: &Database, interface: &Interface, role_name: &str) -> rust::Tokens {
103 let role_setup = &rust::import("modrpc", "RoleSetup");
104 let event_tx = &rust::import("modrpc", "EventTx");
105 let event_rx_builder = &rust::import("modrpc", "EventRxBuilder");
106 let interface_role = &rust::import("modrpc", "InterfaceRole");
107 let proto_interface = &rust::import("crate::interface", format!("{}Interface", interface.name));
108 let init_state = &rust::import("crate::proto", format!("{}InitState", interface.name));
109 let role_config = &rust::import(
110 "crate::proto",
111 format!("{}{}Config", interface.name, role_name),
112 );
113
114 let interface_role_name = &format!("{}{}", interface.name, role_name);
115 let interface_role_name_snake = &camel_to_snake_case(interface_role_name);
116
117 let mproto_cx = &mproto_codegen::codegen::CodegenCx::new_with_type_params(
118 db.mproto_db(),
119 Some("crate::proto"),
120 true,
121 &interface.type_params,
122 );
123
124 let mut events_hook_field_tokens = rust::Tokens::new();
125 let mut events_hook_constr_field_tokens = rust::Tokens::new();
126 let mut events_stubs_field_tokens = rust::Tokens::new();
127 let mut events_stubs_constr_field_tokens = rust::Tokens::new();
128 let mut events_clone_tokens = rust::Tokens::new();
129 for events_list in &interface.events {
130 let role_needs_event_tx = events_list
131 .from_roles
132 .iter()
133 .find(|x| x == &role_name)
134 .is_some();
135 let role_needs_event_rx = events_list
136 .to_roles
137 .iter()
138 .find(|x| x == &role_name)
139 .is_some();
140
141 for event in &events_list.events {
142 let payload_ty = mproto_codegen::codegen::rust::rust_type_tokens(&mproto_cx, &event.ty);
143
144 let hook_field_tokens: rust::Tokens = if role_needs_event_tx {
145 quote! {
146 pub $(&event.name): $event_tx<$(&payload_ty)>,
147 }
148 } else {
149 quote! {}
150 };
151 let hook_constr_tokens: rust::Tokens = if role_needs_event_tx {
152 quote! {
153 $(&event.name): setup.event_tx(i.$(&event.name)),
154 }
155 } else {
156 quote! {}
157 };
158 let stubs_field_tokens: rust::Tokens = if role_needs_event_rx {
159 quote! {
160 pub $(&event.name): $event_rx_builder<$(&payload_ty)>,
161 }
162 } else {
163 quote! {}
164 };
165 let stubs_constr_tokens: rust::Tokens = if role_needs_event_rx {
166 quote! {
167 $(&event.name): setup.event_rx(i.$(&event.name)),
168 }
169 } else {
170 quote! {}
171 };
172 let clone_tokens: rust::Tokens = if role_needs_event_tx {
173 quote! {
174 $(&event.name): self.$(&event.name).clone(),
175 }
176 } else {
177 quote! {}
178 };
179
180 events_hook_field_tokens = quote! {
181 $events_hook_field_tokens
182 $hook_field_tokens
183 };
184 events_hook_constr_field_tokens = quote! {
185 $events_hook_constr_field_tokens
186 $hook_constr_tokens
187 };
188 events_stubs_field_tokens = quote! {
189 $events_stubs_field_tokens
190 $stubs_field_tokens
191 };
192 events_stubs_constr_field_tokens = quote! {
193 $events_stubs_constr_field_tokens
194 $stubs_constr_tokens
195 };
196 events_clone_tokens = quote! {
197 $events_clone_tokens
198 $clone_tokens
199 };
200 }
201 }
202
203 let mut objects_hook_field_tokens = rust::Tokens::new();
204 let mut objects_hook_constr_tokens = rust::Tokens::new();
205 let mut objects_hook_constr_stubs_tokens = rust::Tokens::new();
206 let mut objects_hook_constr_field_tokens = rust::Tokens::new();
207 let mut objects_stubs_field_tokens = rust::Tokens::new();
208 let mut objects_clone_tokens = rust::Tokens::new();
209 let mut i = 0;
210 for object in &interface.objects {
211 let Some(object_interface) = db.lookup_interface(&object.construct) else {
212 panic!("failed to lookup interface '{}'", object.construct.name);
213 };
214
215 let object_role_names = object.get_roles_for_parent_role(object_interface, role_name);
216 if object_role_names.is_empty() {
217 panic!(
218 "object '{}' failed to find roles '{}'",
219 object.name, role_name
220 );
221 };
222
223 for object_role_name in &object_role_names {
224 let construct_module = object.construct.module.as_ref();
225 let object_interface_role_name =
226 &format!("{}{}", object.construct.name, object_role_name);
227
228 let object_field_name = if object_role_names.len() > 1 {
229 &format!("{}_{}", object.name, camel_to_snake_case(object_role_name))
230 } else {
231 &object.name
232 };
233
234 let object_type_args = &mproto_codegen::codegen::rust::rust_type_arg_list(
235 mproto_cx,
236 &object.type_args,
237 None,
238 );
239
240 let hook_field_tokens = quote! {
241 pub $(object_field_name): $(import_qualified(construct_module, object_interface_role_name))$(object_type_args),
242 };
243
244 let object_config: &rust::Tokens = &if object_interface
245 .has_config_for_role(object_role_name)
246 {
247 quote! { config.$(object_field_name) }
248 } else {
249 quote! { $(import_qualified(construct_module, format!("{}Config", object_interface_role_name))) { } }
250 };
251
252 let object_init: &rust::Tokens = &if object_interface.has_state(db) {
253 quote! { init.$(object_field_name) }
254 } else {
255 quote! { $(import_qualified(construct_module, format!("{}InitState", object.construct.name))) { } }
256 };
257
258 let mut hook_constr_tokens = quote! {
259 let ($(object_field_name)_stubs, $(object_field_name)_hooks) =
260 $(import_qualified(construct_module, format!("{}Role", object_interface_role_name)))::setup_worker(
261 &i.$(&object.name), setup, &$(object_config), &$(object_init),
262 );
263 let $(object_field_name)_builder = $(import_qualified(construct_module, format!("{}Builder", object_interface_role_name)))::new(
264 $("\"")$(interface_role_name_snake).$(&object.name)$("\""),
265 $(object_field_name)_hooks,
266 $(object_field_name)_stubs,
267 &$(object_config),
268 $(object_init).clone(),
269 );
270 let $(object_field_name) = $(object_field_name)_builder.create_handle(setup);
271 };
272 let hook_constr_field_tokens = quote! {
273 $(object_field_name),
274 };
275
276 let clone_tokens = quote! {
277 $(object_field_name): self.$(object_field_name).clone(),
278 };
279
280 let stubs_field_tokens: rust::Tokens;
285 let hook_constr_stubs_tokens: rust::Tokens;
286 if object_interface.requires_impls_for_role(object_role_name) {
287 stubs_field_tokens = quote! {
290 pub $(object_field_name): $(import_qualified(construct_module, format!("{}Builder", object_interface_role_name)))$(object_type_args),
291 };
292
293 hook_constr_stubs_tokens = quote! {
294 $(object_field_name): $(object_field_name)_builder,
295 };
296 } else {
297 hook_constr_tokens = quote! {
300 $hook_constr_tokens
301 $(object_field_name)_builder.build(setup);
302 };
303
304 stubs_field_tokens = quote! {};
305
306 hook_constr_stubs_tokens = quote! {};
307 }
308
309 hook_constr_tokens = quote! {
310 setup.push_object_path($("\"")$(&object.name)$("\""));
311 $hook_constr_tokens
312 setup.pop_object_path();
313 };
314
315 if i > 0 {
316 objects_hook_field_tokens = quote! {
317 $objects_hook_field_tokens
318 $hook_field_tokens
319 };
320 objects_hook_constr_tokens = quote! {
321 $objects_hook_constr_tokens
322 $hook_constr_tokens
323 };
324 objects_hook_constr_stubs_tokens = quote! {
325 $objects_hook_constr_stubs_tokens
326 $hook_constr_stubs_tokens
327 };
328 objects_hook_constr_field_tokens = quote! {
329 $objects_hook_constr_field_tokens
330 $hook_constr_field_tokens
331 };
332 objects_stubs_field_tokens = quote! {
333 $objects_stubs_field_tokens
334 $stubs_field_tokens
335 };
336 objects_clone_tokens = quote! {
337 $objects_clone_tokens
338 $clone_tokens
339 };
340 } else {
341 objects_hook_field_tokens = hook_field_tokens;
342 objects_stubs_field_tokens = stubs_field_tokens;
343 objects_hook_constr_tokens = hook_constr_tokens;
344 objects_hook_constr_stubs_tokens = hook_constr_stubs_tokens;
345 objects_hook_constr_field_tokens = hook_constr_field_tokens;
346 objects_clone_tokens = clone_tokens;
347 }
348
349 i += 1;
350 }
351 }
352
353 let type_params = &rust_type_param_list(&interface.type_params, None, None);
356 let type_params_no_lifetime = &rust_type_param_list(&interface.type_params, None, None);
357 let type_params_no_lifetime_bounded =
358 &rust_type_param_list(&interface.type_params, None, Some(quote! { mproto::Owned }));
359
360 let mut interface_type_params_tokens = rust::Tokens::new();
361 if interface.type_params.len() > 0 {
362 interface_type_params_tokens = quote! { $(&interface.type_params[0]) };
363 for type_param in &interface.type_params[1..] {
364 interface_type_params_tokens = quote! { $interface_type_params_tokens, $(type_param) };
365 }
366 }
367 let interface_type_params_tokens = &interface_type_params_tokens;
368
369 let phantom_data: &rust::Tokens = if interface.type_params.len() > 1 {
372 "e! { _phantom: std::marker::PhantomData<($interface_type_params_tokens)>, }
373 } else if interface.type_params.len() == 1 {
374 "e! { _phantom: std::marker::PhantomData<$interface_type_params_tokens>, }
375 } else {
376 "e! {}
377 };
378
379 let role_config_def = db
380 .mproto_db()
381 .lookup_type_def(&mproto_codegen::ast::QualifiedIdentifier::local(format!(
382 "{}{}Config",
383 interface.name, role_name
384 )))
385 .expect("role config struct def");
386
387 let init_state_with_args: rust::Tokens = if interface.has_state(db) {
388 quote! { $(init_state)$(type_params_no_lifetime) }
389 } else {
390 quote! { $(init_state) }
391 };
392
393 quote! {
394 pub struct $(interface_role_name)Hooks$(type_params) {
395 $events_hook_field_tokens
396 $objects_hook_field_tokens
397 $phantom_data
398 }
399
400 pub struct $(interface_role_name)Stubs$(type_params) {
401 $events_stubs_field_tokens
402 $objects_stubs_field_tokens
403 $phantom_data
404 }
405
406 pub struct $(interface_role_name)Role$(type_params_no_lifetime) {
407 $phantom_data
408 }
409
410 impl$(type_params_no_lifetime_bounded) $interface_role for $(&interface.name)$(role_name)Role$(type_params_no_lifetime) {
411 type Interface = $(proto_interface)$(type_params_no_lifetime);
412 type Config = $(role_config)$(rust_type_param_list(&role_config_def.params, None, None));
413 type Init = $init_state_with_args;
414 type Stubs = $(interface_role_name)Stubs$(type_params);
415 type Hooks = $(interface_role_name)Hooks$(type_params);
416
417 fn setup_worker(
418 i: &Self::Interface,
419 setup: &mut $role_setup,
420 config: &Self::Config,
421 init: &Self::Init,
422 ) -> (Self::Stubs, Self::Hooks) {
423 $objects_hook_constr_tokens
424
425 (
426 Self::Stubs {
427 $events_stubs_constr_field_tokens
428 $objects_hook_constr_stubs_tokens
429 $(if !interface.type_params.is_empty() { _phantom: std::marker::PhantomData, })
430 },
431 Self::Hooks {
432 $events_hook_constr_field_tokens
433 $objects_hook_constr_field_tokens
434 $(if !interface.type_params.is_empty() { _phantom: std::marker::PhantomData, })
435 },
436 )
437 }
438 }
439
440 impl$(type_params) Clone for $(interface_role_name)Hooks$(type_params) {
441 fn clone(&self) -> Self {
442 Self {
443 $events_clone_tokens
444 $objects_clone_tokens
445 $(if !interface.type_params.is_empty() { _phantom: std::marker::PhantomData, })
446 }
447 }
448 }
449 }
450}
451
452pub fn rust_interface_role_impl(
453 db: &Database,
454 interface: &Interface,
455 role_name: &str,
456) -> rust::Tokens {
457 if !interface.has_private_event_impls_for_role(role_name)
458 && !interface.has_methods_for_role(role_name)
459 && !interface.has_config_for_role(role_name)
460 && !interface.has_impls_for_role(role_name)
461 {
462 return quote! {};
463 }
464
465 let role_config = &rust::import(
466 "crate::proto",
467 format!("{}{}Config", interface.name, role_name),
468 );
469 let init_state = &rust::import("crate::proto", format!("{}InitState", interface.name));
470 let role_setup = &rust::import("modrpc", "RoleSetup");
471
472 let interface_role_name = &format!("{}{}", interface.name, role_name);
473
474 let mproto_cx = &mproto_codegen::codegen::CodegenCx::new_with_type_params(
475 db.mproto_db(),
476 Some("crate::proto"),
477 true,
478 &interface.type_params,
479 );
480
481 let type_params = &rust_type_param_list(&interface.type_params, None, None);
482 let type_params_bounded =
483 &rust_type_param_list(&interface.type_params, None, Some(quote! { mproto::Owned }));
484 let type_params_no_lifetime = &rust_type_param_list(&interface.type_params, None, None);
485
486 let mut event_handler_stubs = rust::Tokens::new();
487 for events_list in &interface.events {
488 if !events_list
489 .to_roles
490 .iter()
491 .find(|x| x.as_str() == role_name)
492 .is_some()
493 {
494 continue;
495 }
496
497 for event in &events_list.events {
498 if !event.is_private {
499 continue;
500 }
501
502 let payload_ty = mproto_codegen::codegen::rust::rust_type_tokens(mproto_cx, &event.ty);
503
504 event_handler_stubs = quote! {
505 $event_handler_stubs
506 let $(&event.name) = self.stubs.$(&event.name)
507 .queued(setup, async move |_source, _event: $(payload_ty)| {
508 })
509 .load_balance();
510 };
511 }
512 }
513
514 let mut methods = rust::Tokens::new();
515 for methods_list in &interface.methods {
516 if !methods_list
517 .roles
518 .iter()
519 .find(|x| x.as_str() == role_name)
520 .is_some()
521 {
522 continue;
523 }
524
525 for method in &methods_list.methods {
526 let input_ty =
527 &mproto_codegen::codegen::rust::rust_type_tokens(mproto_cx, &method.input_ty);
528 let output_ty =
529 &mproto_codegen::codegen::rust::rust_type_tokens(mproto_cx, &method.output_ty);
530
531 methods = quote! {
532 $methods
533 pub $(
534 if method.is_async { async } else { }
535 ) fn $(&method.name)(
536 &self,
537 input: impl mproto::Encode + for<'a> mproto::Decode<'a> + mproto::Compatible<$input_ty>,
538 ) -> $output_ty {
539 $(rust_type_default_value(
540 mproto_cx,
541 &method.output_ty,
542 ))
543 }
544 };
545 }
546 }
547
548 if !methods.is_empty() {
549 methods = quote! {
550 impl$(type_params_bounded) $(interface_role_name)$(type_params) {
551 $methods
552 }
553 };
554 }
555
556 let role_config_def = db
557 .mproto_db()
558 .lookup_type_def(&mproto_codegen::ast::QualifiedIdentifier::local(format!(
559 "{}{}Config",
560 interface.name, role_name
561 )))
562 .expect("role config struct def");
563
564 let init_state_with_args: &rust::Tokens = &if interface.has_state(db) {
565 quote! { $(init_state)$(type_params_no_lifetime) }
566 } else {
567 quote! { $(init_state) }
568 };
569
570 quote! {
571 #[derive(Clone)]
572 pub struct $(interface_role_name)$(type_params) {
573 hooks: crate::$(interface_role_name)Hooks$(type_params),
574 }
575
576 pub struct $(interface_role_name)Builder$(type_params) {
577 pub name: &'static str,
578 pub hooks: crate::$(interface_role_name)Hooks$(type_params),
579 pub stubs: crate::$(interface_role_name)Stubs$(type_params),
580 pub init: $init_state_with_args,
581 }
582
583 impl$(type_params_bounded) $(interface_role_name)Builder$(type_params) {
584 pub fn new(
585 name: &'static str,
586 hooks: crate::$(interface_role_name)Hooks$(type_params),
587 stubs: crate::$(interface_role_name)Stubs$(type_params),
588 config: &$(role_config)$(rust_type_param_list(&role_config_def.params, None, None)),
589 init: $init_state_with_args,
590 ) -> Self {
591 Self { name, hooks, stubs, init }
592 }
593
594 pub fn create_handle(
595 &self,
596 setup: &$role_setup,
597 ) -> crate::$(interface_role_name)$(type_params) {
598 crate::$(interface_role_name) {
599 hooks: self.hooks.clone(),
600 }
601 }
602
603 pub fn build(
604 self,
605 setup: &$role_setup,
606 ) {
607 $event_handler_stubs
608 }
609 }
610
611 $methods
612 }
613}
614
615pub fn request_impl_stub(
616 mproto_cx: &mproto_codegen::codegen::CodegenCx,
617 object: &InterfaceObject,
618) -> rust::Tokens {
619 let object_name_upper_camel = &snake_to_upper_camel_case(&object.name);
620
621 let request_ty =
622 mproto_codegen::codegen::rust::rust_type_lazy_tokens(mproto_cx, &object.type_args[0]);
623 let response_ty =
624 mproto_codegen::codegen::rust::rust_type_tokens(mproto_cx, &object.type_args[1]);
625
626 quote! {
627 pub struct $(object_name_upper_camel)Handler {
628 }
629
630 impl std_modrpc::RequestHandlerReply for $(object_name_upper_camel)Handler {
631 type Input<'a> = $(request_ty);
632 type Output = $(response_ty);
633
634 async fn call<'a>(
635 &'a mut self,
636 mut cx: std_modrpc::RequestContext<'a, Self::Output>,
637 request: Self::Input<'a>,
638 ) -> Option<()> {
639 None
640 }
641 }
642 }
643}
644
645pub struct RustInterfaceImpl {
646 pub main_rs: rust::Tokens,
647 pub handlers: Vec<(String, rust::Tokens)>,
648}
649
650impl RustInterfaceImpl {
651 pub fn generate(
652 mproto_db: &mproto_codegen::Database,
653 package_name: &str,
654 interface: &Interface,
655 role_name: &str,
656 ) -> Self {
657 let interface_name = &interface.name;
658 let interface_role_name = &format!("{}{}", interface.name, role_name);
659 let package_name = &package_name.replace("-", "_");
660
661 let def_crate = format!("{}_modrpc", package_name);
662 let def_crate = def_crate.as_str();
663 let def_source = Some(def_crate);
664
665 let mproto_cx = &mproto_codegen::codegen::CodegenCx::new_with_type_params(
666 mproto_db,
667 def_source,
668 true,
669 &interface.type_params,
670 );
671
672 let rc = &rust::import("std::rc", "Rc");
673 let ref_cell = &rust::import("std::cell", "RefCell");
674 let block_on = &rust::import("futures_lite::future", "block_on");
675 let modmesh_session = &rust::import("modmesh_endpoint", "ModmeshSession");
676
677 let mut register_handlers = rust::Tokens::new();
678 let mut handlers = Vec::new();
679 for object in &interface.objects {
680 if object.construct.name == "Request"
681 && object.construct.module.as_ref().map(|s| s.as_ref()) == Some("std")
682 {
683 let object_name_upper_camel = &snake_to_upper_camel_case(&object.name);
686 register_handlers = quote! {
687 $register_handlers
688 cx.stubs.$(&object.name).build_replier(s, $(object_name_upper_camel)Handler {});
689 };
690
691 handlers.push((object.name.clone(), request_impl_stub(mproto_cx, object)));
692 }
693 }
694
695 let main_rs = quote! {
696 struct $(interface_role_name)State {
697 }
698
699 fn main() {
700 let state = Rc::new(RefCell::new($(interface_role_name)State {
701 }));
702
703 loop {
704 $block_on(async move {
705 if let Ok(mut modmesh) = $modmesh_session::connect(("127.0.0.1", 13016)).await {
706 modmesh.host_service::<$def_crate::$interface_role_name>(
707 "untitled-service".into(),
708 $(def_crate)::$(interface_name)InitState { },
709 |cx| start_$(package_name)(cx, state.clone())
710 ).await;
711
712 modmesh.run().await;
713 }
714
715 std::thread::sleep(std::time::Duration::from_secs(5));
717 println!("Retrying modmesh connection...");
718 });
719 }
720 }
721
722 fn start_$(package_name)(
723 cx: modrpc::RoleWorkerContext<$def_crate::$(interface_role_name)Role>,
724 state: $rc<$ref_cell<$(interface_role_name)State>>,
725 ) {
726 $register_handlers
727 }
728 };
729
730 Self { main_rs, handlers }
731 }
732}
733
734pub fn rust_interface_init_state_tokens(db: &mut Database, interface: &Interface) -> rust::Tokens {
735 let init_state_struct = crate::codegen::interface_init_state(db, interface);
736 let init_state_struct_id = db
737 .mproto_db_mut()
738 .local_mut()
739 .new_type_def(init_state_struct);
740
741 let mproto_cx = &mproto_codegen::codegen::CodegenCx::new_with_type_params(
742 db.mproto_db(),
743 Some("crate::proto"),
744 true,
745 &interface.type_params,
746 );
747
748 quote! {
749 $(mproto_codegen::codegen::rust::rust_type_def(
750 &mproto_cx,
751 db.mproto_db().local().type_def(init_state_struct_id)
752 ))
753 }
754}
755
756pub fn rust_interface_role_config_tokens(
757 db: &mut Database,
758 interface: &Interface,
759 role_name: &str,
760) -> rust::Tokens {
761 let config_struct = crate::codegen::interface_role_config(
762 db,
763 &mproto_codegen::codegen::CodegenCx::new_with_type_params(
764 db.mproto_db(),
765 Some("crate::proto"),
766 true,
767 &interface.type_params,
768 ),
769 interface,
770 role_name,
771 );
772 let config_struct_id = db.mproto_db_mut().local_mut().new_type_def(config_struct);
773
774 quote! {
775 $(mproto_codegen::codegen::rust::rust_type_def(
776 &mproto_codegen::codegen::CodegenCx::new_with_type_params(
777 db.mproto_db(), Some("crate::proto"), true, &interface.type_params,
778 ),
779 db.mproto_db().local().type_def(config_struct_id)
780 ))
781 }
782}