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}