behaviortree_derive/lib.rs
1// Copyright © 2025 Stephan Kunz
2
3//! Derive macros for [`Behavior`](crate)s.
4//! There are 4 derive macros avialable:
5//! - Action
6//! - Condition
7//! - Control
8//! - Decorator
9//!
10//! On struct level there are the attributes
11//! - `#[behavior(no_create)]`: will suppress the derive of create_fn(...)
12//! - `#[behavior(no_register)]`: will suppress the derive of register()
13//! - `#[behavior(no_register_with)]`: will suppress the derive of register_with(...)
14//!
15//! On field level there are the attributes
16//! - `#[behavior(parameter)]`: defines a field as a parameter for `create_fn(...)` and `register_with(...)`
17//! The values must be given when using the `register_with(...)` method.
18//! A parameter must implement `Clone`.
19//! - `#[behavior(default = <Expression>)]`: defines a default value for a field.
20//! 'Expression' can be any Rust expression that creates an appropriate value out of nothing.
21//!
22//! # Usage
23//! Using the derive macro `Action`, the others work respectively.
24//! ```no_test
25//! #[derive(Action)]
26//! struct MyAction {
27//! // specific elements
28//! ...
29//! }
30//!
31//! impl MyAction {
32//! // specific implementations
33//! ...
34//! }
35//! ```
36//!
37//! # Result
38//! Expands the above example to
39//! ```no_test
40//! struct MyAction {
41//! // specific elements
42//! ...
43//! }
44//!
45//! impl MyAction {
46//! // specific implementations
47//! ...
48//! }
49//!
50//! #[automatically_derived]
51//! #[diagnostic::do_not_recommend]
52//! impl behaviortree::behavior::Behavior for MyAction {
53//! fn creation_fn() -> alloc::boxed::Box<behaviortree::behavior::BehaviorCreationFn> {
54//! ...
55//! }
56//!
57//! fn kind() -> behaviortree::behavior::BehaviorKind {
58//! ...
59//! }
60//! }
61//!
62//! #[automatically_derived]
63//! #[diagnostic::do_not_recommend]
64//! impl behaviortree::behavior::BehaviorExecution for MyAction {
65//! fn as_any(&self) -> &dyn core::any::Any { self }
66//! fn as_any_mut(&mut self) -> &mut dyn core::any::Any { self }
67//! fn static_provided_ports(&self) -> behaviortree::port::PortList { Self::provided_ports() }
68//! }
69//! ```
70//! The macros also creates a function to create the behaviorCreationFunction,
71//! a default registration function and if parameters are given a register_with function.
72//! The creation of the all three functions can be controlled by attributes
73//! `no_create`, `no_register` and `no_register_with` independently.
74//! ```no_test
75//! pub struct MyActionWithParameters {
76//! #[behavior(parameter)]
77//! arg1: i32,
78//! #[behavior(parameter)]
79//! arg2: String,
80//! }
81//!
82//! #[automatically_derived]
83//! #[diagnostic::do_not_recommend]
84//! impl MyActionWithParameters {
85//! /// Behavior creation function
86//! fn create_fn() -> alloc::boxed::Box<behaviortree::behavior::BehaviorCreationFn> {
87//! ...
88//! }
89//! /// Registers the behavior.
90//! pub fn register(
91//! factory: &mut behaviortree::factory::BehaviorTreeFactory,
92//! name: &str,
93//! ) -> Result<(), behaviortree::factory::error::Error> {
94//! ...
95//! }
96//! /// Registers the behavior with parameter.
97//! pub fn register_with(
98//! factory: &mut behaviortree::factory::BehaviorTreeFactory,
99//! name: &str,
100//! arg1: i32,
101//! arg2: String,
102//! ) -> Result<(), behaviortree::factory::error::Error> {
103//! ...
104//! }
105//! }
106//! ```
107//!
108//! # Errors
109//! - if attributes are used in a wrong way
110//!
111//! # Panics
112//! - if used on enums or unions or functions
113
114#[doc(hidden)]
115extern crate proc_macro;
116
117#[doc(hidden)]
118extern crate alloc;
119
120mod behavior;
121
122use behavior::derive_behavior_struct;
123use proc_macro::TokenStream;
124
125/// internal differantiation of the different kinds of [`Behavior`](behaviortree::BehaviorKind)s.
126enum Kind {
127 Action,
128 Condition,
129 Control,
130 Decorator,
131}
132
133/// Derive macro for an [`Action`] type `Behavior`, [`usage`](https://docs.rs/behaviortree-derive).
134#[proc_macro_derive(Action, attributes(behavior))]
135pub fn derive_action(input: TokenStream) -> TokenStream {
136 derive_behavior_struct(input.into(), Kind::Action)
137 .expect("derive `Action` failed")
138 .into()
139}
140
141/// Derive macro for an [`Condition`] type `Behavior`, [`usage`](https://docs.rs/behaviortree-derive).
142#[proc_macro_derive(Condition, attributes(behavior))]
143pub fn derive_condition(input: TokenStream) -> TokenStream {
144 derive_behavior_struct(input.into(), Kind::Condition)
145 .expect("derive `Condition` failed")
146 .into()
147}
148
149/// Derive macro for an [`Control`] type `Behavior`, [`usage`](https://docs.rs/behaviortree-derive).
150#[proc_macro_derive(Control, attributes(behavior))]
151pub fn derive_control(input: TokenStream) -> TokenStream {
152 derive_behavior_struct(input.into(), Kind::Control)
153 .expect("derive `Control` failed")
154 .into()
155}
156
157/// Derive macro for an [`Decorator`] type `Behavior`, [`usage`](https://docs.rs/behaviortree-derive).
158#[proc_macro_derive(Decorator, attributes(behavior))]
159pub fn derive_decorator(input: TokenStream) -> TokenStream {
160 derive_behavior_struct(input.into(), Kind::Decorator)
161 .expect("derive `Decorator` failed")
162 .into()
163}