1#[macro_export]
142macro_rules! action {
143 ($plugin_name:ident : $name:expr; $($tokens:tt)*) => {
144 $crate::__leaf_plugin_parse! {
145 ctx: {
146 plugin_name: $plugin_name,
147 node_name: $name,
148 factory_type: $crate::node::ActionFactory,
149 plugin_constructor: $crate::node::ActionPluginConstructor,
150 reconstruction_data: $crate::__macro_support::ActionReconstructionData,
151 behavior_box_type: $crate::__macro_support::BoxActionBehavior,
152 node_kind: $crate::__macro_support::NodeKind::action(),
153 },
154 receivers: [],
155 senders: [],
156 params: none,
157 params_binding: _parameters,
158 tokens: $($tokens)*
159 }
160 };
161}
162
163#[macro_export]
172macro_rules! condition {
173 ($plugin_name:ident : $name:expr; $($tokens:tt)*) => {
174 $crate::__leaf_plugin_parse! {
175 ctx: {
176 plugin_name: $plugin_name,
177 node_name: $name,
178 factory_type: $crate::node::ConditionFactory,
179 plugin_constructor: $crate::node::ConditionPluginConstructor,
180 reconstruction_data: $crate::__macro_support::ConditionReconstructionData,
181 behavior_box_type: $crate::__macro_support::BoxConditionBehavior,
182 node_kind: $crate::__macro_support::NodeKind::condition(),
183 },
184 receivers: [],
185 senders: [],
186 params: none,
187 params_binding: _parameters,
188 tokens: $($tokens)*
189 }
190 };
191}
192
193#[macro_export]
241macro_rules! decorator {
242 ($plugin_name:ident : $name:expr; child($child_binding:ident),create: $create:expr,) => {
243 $crate::__decorator_plugin_impl! {
244 $plugin_name,
245 $name,
246 $child_binding,
247 none,
248 _parameters,
249 $create
250 }
251 };
252 (
253 $plugin_name:ident :
254 $name:expr; child($child_binding:ident),params($params_binding:ident):
255 $params_ty:path,create:
256 $create:expr,
257 ) => {
258 $crate::__decorator_plugin_impl! {
259 $plugin_name,
260 $name,
261 $child_binding,
262 (typed $params_ty),
263 $params_binding,
264 $create
265 }
266 };
267}
268
269#[macro_export]
314macro_rules! control {
315 ($plugin_name:ident : $name:expr; children($children_binding:ident),create: $create:expr,) => {
316 $crate::__control_plugin_impl! {
317 $plugin_name,
318 $name,
319 $children_binding,
320 none,
321 _parameters,
322 $create
323 }
324 };
325 (
326 $plugin_name:ident :
327 $name:expr; children($children_binding:ident),params($params_binding:ident):
328 $params_ty:path,create:
329 $create:expr,
330 ) => {
331 $crate::__control_plugin_impl! {
332 $plugin_name,
333 $name,
334 $children_binding,
335 (typed $params_ty),
336 $params_binding,
337 $create
338 }
339 };
340}
341
342#[doc(hidden)]
346#[macro_export]
347macro_rules! __leaf_plugin_parse {
348 (
349 ctx: $ctx:tt,
350 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
351 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
352 params: $params:tt,
353 params_binding: $params_binding:ident,
354 tokens: receivers: [$($new_receiver_name:ident : $new_receiver_ty:ty => $new_receiver_desc:literal),* $(,)?]; $($rest:tt)*
355 ) => {
356 $crate::__leaf_plugin_parse! {
357 ctx: $ctx,
358 receivers: [$($new_receiver_name : $new_receiver_ty => $new_receiver_desc),*],
359 senders: [$($sender_name : $sender_ty => $sender_desc),*],
360 params: $params,
361 params_binding: $params_binding,
362 tokens: $($rest)*
363 }
364 };
365 (
366 ctx: $ctx:tt,
367 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
368 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
369 params: $params:tt,
370 params_binding: $params_binding:ident,
371 tokens: senders: [$($new_sender_name:ident : $new_sender_ty:ty => $new_sender_desc:literal),* $(,)?]; $($rest:tt)*
372 ) => {
373 $crate::__leaf_plugin_parse! {
374 ctx: $ctx,
375 receivers: [$($receiver_name : $receiver_ty => $receiver_desc),*],
376 senders: [$($new_sender_name : $new_sender_ty => $new_sender_desc),*],
377 params: $params,
378 params_binding: $params_binding,
379 tokens: $($rest)*
380 }
381 };
382 (
383 ctx: $ctx:tt,
384 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
385 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
386 params: $params:tt,
387 params_binding: $params_binding:ident,
388 tokens: params($new_params_binding:ident): $new_params_ty:path; $($rest:tt)*
389 ) => {
390 $crate::__leaf_plugin_parse! {
391 ctx: $ctx,
392 receivers: [$($receiver_name : $receiver_ty => $receiver_desc),*],
393 senders: [$($sender_name : $sender_ty => $sender_desc),*],
394 params: (typed $new_params_ty),
395 params_binding: $new_params_binding,
396 tokens: $($rest)*
397 }
398 };
399 (
400 ctx: $ctx:tt,
401 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
402 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
403 params: $params:tt,
404 params_binding: $params_binding:ident,
405 tokens: create: $create:expr $(;)?
406 ) => {
407 $crate::__leaf_plugin_impl! {
408 ctx: $ctx,
409 receivers: [$($receiver_name : $receiver_ty => $receiver_desc),*],
410 senders: [$($sender_name : $sender_ty => $sender_desc),*],
411 params: $params,
412 params_binding: $params_binding,
413 create: $create
414 }
415 };
416 (
417 ctx: $ctx:tt,
418 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
419 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
420 params: $params:tt,
421 params_binding: $params_binding:ident,
422 tokens: $($unexpected:tt)+
423 ) => {
424 compile_error!(
425 "invalid plugin DSL. Expected fields separated by ';': \
426 receivers: [...]; senders: [...]; params(<ident>): <type-path>; create: <expr>;"
427 );
428 };
429}
430
431#[doc(hidden)]
432#[macro_export]
433macro_rules! __leaf_plugin_extract_receivers {
434 ([], $data:ident) => {};
435 ([$($port_name:ident : $port_ty:ty => $port_desc:literal),+], $data:ident) => {
436 $(
437 let $port_name = $data
438 .context
439 .take_receiver(&$crate::__macro_support::PortKey::new(stringify!($port_name)))?
440 .into_receiver_of::<$port_ty>()
441 .map_err(|_| {
442 $crate::__macro_support::anyhow::anyhow!(
443 concat!(
444 "failed to obtain typed receiver for port '",
445 stringify!($port_name),
446 "'"
447 )
448 )
449 })?;
450 )+
451 };
452}
453
454#[doc(hidden)]
455#[macro_export]
456macro_rules! __leaf_plugin_extract_senders {
457 ([], $data:ident) => {};
458 ([$($port_name:ident : $port_ty:ty => $port_desc:literal),+], $data:ident) => {
459 $(
460 let $port_name = $data
461 .context
462 .take_sender(&$crate::__macro_support::PortKey::new(stringify!($port_name)))?
463 .into_sender_of::<$port_ty>()
464 .map_err(|_| {
465 $crate::__macro_support::anyhow::anyhow!(
466 concat!(
467 "failed to obtain typed sender for port '",
468 stringify!($port_name),
469 "'"
470 )
471 )
472 })?;
473 )+
474 };
475}
476
477#[doc(hidden)]
478#[macro_export]
479macro_rules! __leaf_plugin_build_ports {
480 ([], []) => {
481 None
482 };
483 ([$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),+], []) => {
484 Some(
485 <$crate::__macro_support::PortsSpec as $crate::__macro_support::FromIterator1<
486 $crate::__macro_support::NodePortSpec,
487 >>::from_iter1([
488 $(
489 $crate::__macro_support::NodePortSpec {
490 key: $crate::__macro_support::PortKey::new(stringify!($receiver_name)),
491 kind: $crate::__macro_support::NodePortKind::Receiver,
492 msg_spec: $crate::__macro_support::MessageSpec::new::<$receiver_ty>($receiver_desc),
493 }
494 ),+
495 ]),
496 )
497 };
498 ([], [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),+]) => {
499 Some(
500 <$crate::__macro_support::PortsSpec as $crate::__macro_support::FromIterator1<
501 $crate::__macro_support::NodePortSpec,
502 >>::from_iter1([
503 $(
504 $crate::__macro_support::NodePortSpec {
505 key: $crate::__macro_support::PortKey::new(stringify!($sender_name)),
506 kind: $crate::__macro_support::NodePortKind::Sender,
507 msg_spec: $crate::__macro_support::MessageSpec::new::<$sender_ty>($sender_desc),
508 }
509 ),+
510 ]),
511 )
512 };
513 ([$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),+], [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),+]) => {
514 Some(
515 <$crate::__macro_support::PortsSpec as $crate::__macro_support::FromIterator1<
516 $crate::__macro_support::NodePortSpec,
517 >>::from_iter1([
518 $(
519 $crate::__macro_support::NodePortSpec {
520 key: $crate::__macro_support::PortKey::new(stringify!($receiver_name)),
521 kind: $crate::__macro_support::NodePortKind::Receiver,
522 msg_spec: $crate::__macro_support::MessageSpec::new::<$receiver_ty>($receiver_desc),
523 }
524 ),+,
525 $(
526 $crate::__macro_support::NodePortSpec {
527 key: $crate::__macro_support::PortKey::new(stringify!($sender_name)),
528 kind: $crate::__macro_support::NodePortKind::Sender,
529 msg_spec: $crate::__macro_support::MessageSpec::new::<$sender_ty>($sender_desc),
530 }
531 ),+
532 ]),
533 )
534 };
535}
536
537#[doc(hidden)]
538#[macro_export]
539macro_rules! __optional_params_spec {
540 (none) => {
541 None
542 };
543 ((typed $params_ty:path)) => {
544 Some(<$params_ty as $crate::ProvideParamSpec>::provide())
545 };
546}
547
548#[doc(hidden)]
549#[macro_export]
550macro_rules! __deserialize_params {
551 (none, $params_binding:ident, $parameters:expr) => {};
552 ((typed $params_ty:path), $params_binding:ident, $parameters:expr) => {
553 let $params_binding = $crate::ParamsDeserializer::deserialize::<$params_ty>($parameters)?;
554 };
555}
556
557#[doc(hidden)]
558#[macro_export]
559macro_rules! __leaf_plugin_impl {
560 (
561 ctx: {
562 plugin_name: $plugin_name:ident,
563 node_name: $name:expr,
564 factory_type: $factory_type:ty,
565 plugin_constructor: $plugin_constructor:ty,
566 reconstruction_data: $reconstruction_data:ty,
567 behavior_box_type: $behavior_box_type:ty,
568 node_kind: $node_kind:expr,
569 },
570 receivers: [$($receiver_name:ident : $receiver_ty:ty => $receiver_desc:literal),* $(,)?],
571 senders: [$($sender_name:ident : $sender_ty:ty => $sender_desc:literal),* $(,)?],
572 params: $params:tt,
573 params_binding: $params_binding:ident,
574 create: $create:expr $(,)?
575 ) => {
576 pub struct $plugin_name {
577 spec: $crate::__macro_support::NodeSpec,
578 factory: $factory_type,
579 }
580
581 impl $crate::Plugin for $plugin_name {
582 type Spec = $crate::__macro_support::NodeSpec;
583 type Factory = $factory_type;
584
585 fn new() -> Self
586 where
587 Self: Sized,
588 {
589 let factory_fn = |mut data: $reconstruction_data| {
590 $crate::__leaf_plugin_extract_receivers!([$($receiver_name : $receiver_ty => $receiver_desc),*], data);
591 $crate::__leaf_plugin_extract_senders!([$($sender_name : $sender_ty => $sender_desc),*], data);
592 $crate::__deserialize_params!($params, $params_binding, data.parameters);
593 Ok(Box::new($create) as $behavior_box_type)
594 };
595
596 let spec = $crate::__macro_support::NodeSpec::builder()
597 .key($crate::__macro_support::NodeSpecKey::new(
598 $crate::__macro_support::NodeName::new($name),
599 $node_kind,
600 ))
601 .maybe_ports($crate::__leaf_plugin_build_ports!(
602 [$($receiver_name : $receiver_ty => $receiver_desc),*],
603 [$($sender_name : $sender_ty => $sender_desc),*]
604 ))
605 .maybe_params($crate::__optional_params_spec!($params))
606 .build();
607
608 Self {
609 spec,
610 factory: Self::Factory::new(Box::new(factory_fn)),
611 }
612 }
613
614 fn spec(&self) -> &Self::Spec {
615 &self.spec
616 }
617
618 fn factory(&self) -> &Self::Factory {
619 &self.factory
620 }
621
622 fn into_parts(self: Box<Self>) -> (Self::Spec, Self::Factory) {
623 (self.spec, self.factory)
624 }
625 }
626
627 $crate::submit!(<$plugin_constructor>::new::<$plugin_name>());
628 };
629}
630
631#[doc(hidden)]
632#[macro_export]
633macro_rules! __control_plugin_impl {
634 (
635 $plugin_name:ident,
636 $name:expr,
637 $children_binding:ident,
638 $params:tt,
639 $params_binding:ident,
640 $create:expr $(,)?
641 ) => {
642 struct $plugin_name {
643 spec: NodeSpec,
644 factory: ControlFactory,
645 }
646
647 impl Plugin for $plugin_name {
648 type Spec = NodeSpec;
649 type Factory = ControlFactory;
650
651 fn new() -> Self
652 where
653 Self: Sized,
654 {
655 Self {
656 spec: NodeSpec::builder()
657 .key(NodeSpecKey::new(NodeName::new($name), NodeKind::Control))
658 .maybe_params($crate::__optional_params_spec!($params))
659 .build(),
660
661 factory: ControlFactory::new(Box::new(|data: ControlReconstructionData| {
662 $crate::__deserialize_params!($params, $params_binding, data.parameters);
663 let $children_binding = data.context.children;
664
665 Ok(Box::new($create) as BoxNode)
666 })),
667 }
668 }
669
670 fn spec(&self) -> &Self::Spec {
671 &self.spec
672 }
673
674 fn factory(&self) -> &Self::Factory {
675 &self.factory
676 }
677
678 fn into_parts(self: Box<Self>) -> (Self::Spec, Self::Factory) {
679 (self.spec, self.factory)
680 }
681 }
682
683 $crate::submit!(ControlPluginConstructor::new::<$plugin_name>());
684 };
685}
686
687#[doc(hidden)]
688#[macro_export]
689macro_rules! __decorator_plugin_impl {
690 (
691 $plugin_name:ident,
692 $name:expr,
693 $child_binding:ident,
694 $params:tt,
695 $params_binding:ident,
696 $create:expr $(,)?
697 ) => {
698 struct $plugin_name {
699 spec: NodeSpec,
700 factory: DecoratorFactory,
701 }
702
703 impl Plugin for $plugin_name {
704 type Spec = NodeSpec;
705 type Factory = DecoratorFactory;
706
707 fn new() -> Self
708 where
709 Self: Sized,
710 {
711 Self {
712 spec: NodeSpec::builder()
713 .key(NodeSpecKey::new(NodeName::new($name), NodeKind::Decorator))
714 .maybe_params($crate::__optional_params_spec!($params))
715 .build(),
716
717 factory: DecoratorFactory::new(Box::new(
718 |data: DecoratorReconstructionData| {
719 $crate::__deserialize_params!(
720 $params,
721 $params_binding,
722 data.parameters
723 );
724 let $child_binding = data.context.child;
725
726 Ok(Box::new($create) as BoxNode)
727 },
728 )),
729 }
730 }
731
732 fn spec(&self) -> &Self::Spec {
733 &self.spec
734 }
735
736 fn factory(&self) -> &Self::Factory {
737 &self.factory
738 }
739
740 fn into_parts(self: Box<Self>) -> (Self::Spec, Self::Factory) {
741 (self.spec, self.factory)
742 }
743 }
744
745 $crate::submit!(DecoratorPluginConstructor::new::<$plugin_name>());
746 };
747}