solverforge_derive/lib.rs
1//! Derive macros for SolverForge domain types.
2//!
3//! This crate provides derive macros for implementing `PlanningEntity` and
4//! `PlanningSolution` traits from `solverforge-core`.
5//!
6//! # Example
7//!
8//! ```ignore
9//! use solverforge_derive::{PlanningEntity, PlanningSolution};
10//!
11//! #[derive(PlanningEntity, Clone)]
12//! pub struct Lesson {
13//! #[planning_id]
14//! pub id: String,
15//! pub subject: String,
16//! #[planning_variable(value_range_provider = "rooms")]
17//! pub room: Option<Room>,
18//! }
19//!
20//! #[derive(PlanningSolution, Clone)]
21//! #[constraint_provider = "define_constraints"]
22//! pub struct Timetable {
23//! #[problem_fact_collection]
24//! #[value_range_provider(id = "rooms")]
25//! pub rooms: Vec<Room>,
26//! #[planning_entity_collection]
27//! pub lessons: Vec<Lesson>,
28//! #[planning_score]
29//! pub score: Option<HardSoftScore>,
30//! }
31//! ```
32
33use proc_macro::TokenStream;
34
35mod entity;
36mod solution;
37
38/// Derive macro for implementing the `PlanningEntity` trait.
39///
40/// # Attributes
41///
42/// ## Field Attributes
43///
44/// - `#[planning_id]` - Marks the field as the unique identifier for this entity.
45/// Required for every planning entity.
46///
47/// - `#[planning_variable(value_range_provider = "...")]` - Marks the field as a
48/// planning variable. The solver will assign values from the specified value
49/// range provider.
50///
51/// - `#[planning_variable(value_range_provider = "...", allows_unassigned = true)]` -
52/// Allows the variable to remain unassigned (null/None).
53///
54/// # Example
55///
56/// ```ignore
57/// #[derive(PlanningEntity, Clone)]
58/// pub struct Lesson {
59/// #[planning_id]
60/// pub id: String,
61///
62/// pub subject: String,
63/// pub teacher: String,
64///
65/// #[planning_variable(value_range_provider = "timeslots")]
66/// pub timeslot: Option<Timeslot>,
67///
68/// #[planning_variable(value_range_provider = "rooms", allows_unassigned = true)]
69/// pub room: Option<Room>,
70/// }
71/// ```
72#[proc_macro_derive(
73 PlanningEntity,
74 attributes(planning_id, planning_variable, planning_list_variable)
75)]
76pub fn derive_planning_entity(input: TokenStream) -> TokenStream {
77 entity::derive_planning_entity_impl(input)
78}
79
80/// Derive macro for implementing the `PlanningSolution` trait.
81///
82/// # Attributes
83///
84/// ## Struct Attributes
85///
86/// - `#[constraint_provider = "function_name"]` - Specifies the function that
87/// provides constraints for this solution. The function must have signature
88/// `fn(ConstraintFactory) -> Vec<Constraint>`.
89///
90/// ## Field Attributes
91///
92/// - `#[problem_fact_collection]` - Marks a collection field as containing
93/// immutable problem facts.
94///
95/// - `#[problem_fact]` - Marks a single field as a problem fact.
96///
97/// - `#[planning_entity_collection]` - Marks a collection field as containing
98/// planning entities that will be modified during solving.
99///
100/// - `#[planning_entity]` - Marks a single field as a planning entity.
101///
102/// - `#[value_range_provider(id = "...")]` - Marks a field as providing values
103/// for planning variables with the matching `value_range_provider` reference.
104///
105/// - `#[planning_score]` - Marks the field that will hold the solution's score.
106///
107/// # Example
108///
109/// ```ignore
110/// #[derive(PlanningSolution, Clone)]
111/// #[constraint_provider = "define_constraints"]
112/// pub struct Timetable {
113/// #[problem_fact_collection]
114/// #[value_range_provider(id = "timeslots")]
115/// pub timeslots: Vec<Timeslot>,
116///
117/// #[problem_fact_collection]
118/// #[value_range_provider(id = "rooms")]
119/// pub rooms: Vec<Room>,
120///
121/// #[planning_entity_collection]
122/// pub lessons: Vec<Lesson>,
123///
124/// #[planning_score]
125/// pub score: Option<HardSoftScore>,
126/// }
127/// ```
128#[proc_macro_derive(
129 PlanningSolution,
130 attributes(
131 constraint_provider,
132 problem_fact_collection,
133 problem_fact,
134 planning_entity_collection,
135 planning_entity,
136 value_range_provider,
137 planning_score
138 )
139)]
140pub fn derive_planning_solution(input: TokenStream) -> TokenStream {
141 solution::derive_planning_solution_impl(input)
142}