1use state_validation::{CollectedInputs, StateFilter};
2
3use crate::{
4 actions::ActionSource,
5 priority::{Priority, PriorityMut, PriorityStack},
6};
7
8pub trait ActionRequirement<State, Input> {
9 type Filter: StateFilter<State, Input>;
11 fn collect_inputs(state: &State) -> CollectedInputs<State, impl Iterator<Item = Input>>;
13}
14struct NoIter<Item>(std::marker::PhantomData<Item>);
15impl<Item> Iterator for NoIter<Item> {
16 type Item = Item;
17 fn next(&mut self) -> Option<Self::Item> {
18 None
19 }
20}
21impl<State> ActionRequirement<State, ()> for () {
22 type Filter = ();
23 fn collect_inputs(_state: &State) -> CollectedInputs<State, impl Iterator<Item = ()>> {
24 CollectedInputs::new(NoIter(std::marker::PhantomData::default()))
25 }
26}
27
28pub struct FulfilledAction<Action: crate::actions::ActionSource, Value> {
29 action: Action,
30 source: Action::Source,
31 value: Value,
32}
33
34impl<Action: crate::actions::ActionSource, Value> FulfilledAction<Action, Value> {
35 pub const fn new(action: Action, source: Action::Source, value: Value) -> Self {
36 FulfilledAction {
37 action,
38 source,
39 value,
40 }
41 }
42 pub fn take_action(self) -> Action {
43 self.action
44 }
45 pub fn source(&self) -> &Action::Source {
46 &self.source
47 }
48 pub fn value(&self) -> &Value {
49 &self.value
50 }
51}
52
53impl<Action: crate::actions::ActionSource, Value: Send + Sync> ActionSource
54 for FulfilledAction<Action, Value>
55{
56 type Source = Action::Source;
57 fn source(&self) -> &Self::Source {
58 self.action.source()
59 }
60}
61
62pub struct RequirementAction<Priority, Input, Action> {
63 priority: Priority,
64 action: Action,
65 _m: std::marker::PhantomData<Input>,
66}
67
68impl<Priority, Input, Action> RequirementAction<Priority, Input, Action> {
69 pub fn priority(&self) -> &Priority {
70 &self.priority
71 }
72 pub fn action(&self) -> &Action {
73 &self.action
74 }
75}
76impl<State, Input, Action: crate::actions::IncitingAction<State, Input>>
77 RequirementAction<Priority<State>, Input, Action>
78where
79 Action::Requirement: ActionRequirement<Priority<State>, Input>,
80{
81 pub fn try_new(
84 priority: Priority<State>,
85 action: Action,
86 ) -> Result<
87 RequirementAction<Priority<State>, Input, Action>,
88 TryNewRequirementActionError<Priority<State>, Action>,
89 > {
90 let collected_inputs =
91 <Action::Requirement as ActionRequirement<Priority<State>, Input>>::collect_inputs(
92 &priority,
93 );
94 if collected_inputs
95 .fits_any::<<Action::Requirement as ActionRequirement<Priority<State>, Input>>::Filter>(
96 &priority,
97 ) {
98 Ok(RequirementAction {
99 priority,
100 action,
101 _m: std::marker::PhantomData::default(),
102 })
103 } else {
104 Err(TryNewRequirementActionError { priority, action })
105 }
106 }
107 pub fn select(
108 self,
109 value: Input,
110 ) -> Result<
111 Action::Resolved,
112 RequirementActionSelectionError<
113 Self,
114 <<Action::Requirement as ActionRequirement<Priority<State>, Input>>::Filter as StateFilter<Priority<State>, Input>>::Error,
115 >,
116 >{
117 let result = <<Action::Requirement as ActionRequirement<Priority<State>, Input>>::Filter as StateFilter<Priority<State>, Input>>::filter(
118 &self.priority,
119 value,
120 );
121 match result {
122 Ok(input) => Ok(self
123 .action
124 .resolve(PriorityMut::<Priority<State>>::new(self.priority), input)),
125 Err(error) => Err(RequirementActionSelectionError {
126 action: self,
127 error,
128 }),
129 }
130 }
131}
132#[derive(thiserror::Error)]
133#[error("requirement for action is impossible to fulfill")]
134pub struct TryNewRequirementActionError<Priority, Action> {
135 pub priority: Priority,
136 pub action: Action,
137}
138impl<Priority, Action> std::fmt::Debug for TryNewRequirementActionError<Priority, Action> {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 write!(f, "requirement for action is impossible to fulfill")
141 }
142}
143impl<
144 State,
145 Input,
146 IncitingAction: crate::actions::IncitingActionInfo<State>,
147 Action: crate::actions::StackAction<State, Input, IncitingAction>,
148> RequirementAction<PriorityStack<State, IncitingAction>, Input, Action>
149where
150 Action::Requirement: ActionRequirement<PriorityStack<State, IncitingAction>, Input>,
151{
152 pub fn try_new(
155 priority: PriorityStack<State, IncitingAction>,
156 action: Action,
157 ) -> Result<
158 RequirementAction<PriorityStack<State, IncitingAction>, Input, Action>,
159 TryNewRequirementActionError<PriorityStack<State, IncitingAction>, Action>,
160 > {
161 let collected_inputs = <Action::Requirement as ActionRequirement<
162 PriorityStack<State, IncitingAction>,
163 Input,
164 >>::collect_inputs(&priority);
165 if collected_inputs.fits_any::<<Action::Requirement as ActionRequirement<
166 PriorityStack<State, IncitingAction>,
167 Input,
168 >>::Filter>(&priority)
169 {
170 Ok(RequirementAction {
171 priority,
172 action,
173 _m: std::marker::PhantomData::default(),
174 })
175 } else {
176 Err(TryNewRequirementActionError { priority, action })
177 }
178 }
179 pub fn select(
180 self,
181 value: Input,
182 ) -> Result<
183 Action::Resolved,
184 RequirementActionSelectionError<
185 Self,
186 <<Action::Requirement as ActionRequirement<
187 PriorityStack<State, IncitingAction>,
188 Input,
189 >>::Filter as StateFilter<PriorityStack<State, IncitingAction>, Input>>::Error,
190 >,
191 > {
192 let result = <<Action::Requirement as ActionRequirement<
193 PriorityStack<State, IncitingAction>,
194 Input,
195 >>::Filter as StateFilter<PriorityStack<State, IncitingAction>, Input>>::filter(
196 &self.priority,
197 value,
198 );
199 match result {
200 Ok(input) => Ok(self.action.resolve(
201 PriorityMut::<PriorityStack<State, IncitingAction>>::new(self.priority),
202 input,
203 )),
204 Err(error) => Err(RequirementActionSelectionError {
205 action: self,
206 error,
207 }),
208 }
209 }
210}
211pub struct RequirementActionSelectionError<Action, E: std::error::Error> {
212 action: Action,
213 error: E,
214}
215impl<Action, E: std::error::Error> std::fmt::Debug for RequirementActionSelectionError<Action, E> {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 std::fmt::Debug::fmt(&self.error, f)
218 }
219}
220impl<Action, E: std::error::Error> std::fmt::Display
221 for RequirementActionSelectionError<Action, E>
222{
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 std::fmt::Display::fmt(&self.error, f)
225 }
226}
227impl<Action, E: std::error::Error> RequirementActionSelectionError<Action, E> {
228 pub fn take_requirement_action(self) -> Action {
229 self.action
230 }
231 pub fn take_all(self) -> (Action, E) {
232 (self.action, self.error)
233 }
234 pub fn error(&self) -> &E {
235 &self.error
236 }
237}