1use crate::{
2 MayTransition, SMapRuntime, SMove, SMut, SPinMut, SPinRef, SRef, State, StateInference,
3 StateMachineImpl, StateMarker, StateStorage, StateTrait, Transition, TransitionCallsite,
4 TransitionProof, UnionStateKind, state_trait,
5};
6use core::{any::TypeId, marker::PhantomData, pin::Pin};
7
8#[doc(hidden)]
10pub struct StateUnionState<Marker>(PhantomData<fn() -> Marker>);
11
12impl<Marker> StateUnionState<Marker> {
13 #[doc(hidden)]
14 #[must_use]
15 pub const fn new() -> Self {
16 Self(PhantomData)
17 }
18}
19
20#[doc(hidden)]
22pub auto trait StateUnionConcreteState {}
23
24impl<Marker> !StateUnionConcreteState for StateUnionState<Marker> {}
25
26#[doc(hidden)]
28pub trait StateUnionMember<State> {}
29
30pub trait StateUnionDiscriminant: Sized + StateMarker<Kind = UnionStateKind> {
44 type Enum<Storage, T>
49 where
50 Storage: StateStorage,
51 T: StateMachineImpl;
52
53 #[doc(hidden)]
54 fn discriminate<Storage, T>(
55 state: DiscriminatedState<Storage, T, Self>,
56 ) -> Self::Enum<Storage, T>
57 where
58 Storage: StateStorage,
59 T: StateMachineImpl;
60}
61
62pub trait In<Marker>: StateTrait + StateMarker
100where
101 Marker: StateMarker,
102{
103 #[must_use]
108 fn into_discriminated<Storage, T>(
109 state: State<Storage, T, Self>,
110 ) -> DiscriminatedState<Storage, T, Marker>
111 where
112 Self: Sized,
113 Storage: StateStorage,
114 T: StateMachineImpl,
115 Marker: StateUnionDiscriminant;
116
117 #[doc(hidden)]
118 #[must_use]
119 fn prove<Storage, T, To>()
120 -> TransitionProof<Storage, T, Self, Marker, To, <Marker as StateMarker>::Kind>
121 where
122 Self: Sized,
123 Storage: StateStorage,
124 T: StateMachineImpl,
125 To: StateTrait + StateMarker,
126 {
127 TransitionProof::new()
128 }
129}
130
131impl<StateMarkerType> In<StateMarkerType> for StateMarkerType
132where
133 StateMarkerType: StateTrait + StateMarker,
134{
135 fn into_discriminated<Storage, T>(
136 _state: State<Storage, T, Self>,
137 ) -> DiscriminatedState<Storage, T, StateMarkerType>
138 where
139 Self: Sized,
140 Storage: StateStorage,
141 T: StateMachineImpl,
142 StateMarkerType: StateUnionDiscriminant,
143 {
144 unreachable!("concrete identity states are not generated state unions")
145 }
146}
147
148pub type DiscriminatedState<Storage, T, Marker> =
174 State<SDiscriminated<Storage>, T, StateUnionState<Marker>>;
175
176impl<Storage, T, Marker> State<SDiscriminated<Storage>, T, StateUnionState<Marker>>
177where
178 Storage: StateStorage,
179 T: StateMachineImpl,
180 Marker: StateUnionDiscriminant,
181{
182 #[must_use]
198 pub fn discriminate(self) -> <Marker as StateUnionDiscriminant>::Enum<Storage, T> {
199 Marker::discriminate(self)
200 }
201}
202
203#[doc(hidden)]
204#[must_use]
205pub fn discriminate_state<Storage, T, From, Marker>(
206 state: State<Storage, T, From>,
207) -> DiscriminatedState<Storage, T, Marker>
208where
209 Storage: StateStorage,
210 T: StateMachineImpl,
211 From: crate::ConcreteStateTrait,
212 Marker: StateUnionDiscriminant,
213{
214 let inference =
215 <<Storage::Inference as crate::InferenceKind>::Inference as crate::StateInference>::new::<
216 Storage,
217 T,
218 From,
219 >(&state.inner);
220 State::from_inner(DiscriminatedInner {
221 inner: Storage::retag(state.inner),
222 inference,
223 })
224}
225
226#[doc(hidden)]
227#[must_use]
228pub fn rediscriminate_union_state<Storage, T, FromMarker, ToMarker>(
229 state: State<Storage, T, StateUnionState<FromMarker>>,
230) -> DiscriminatedState<Storage, T, ToMarker>
231where
232 Storage: StateStorage,
233 T: StateMachineImpl,
234 FromMarker: StateUnionDiscriminant,
235 StateUnionState<FromMarker>: StateTrait,
236 ToMarker: StateUnionDiscriminant,
237{
238 let inferred_state = Storage::inferred_state(&state.inner);
239 let inference =
240 <<Storage::Inference as crate::InferenceKind>::Inference as crate::StateInference>::from_erased(
241 inferred_state,
242 );
243 State::from_inner(DiscriminatedInner {
244 inner: Storage::retag(state.inner),
245 inference,
246 })
247}
248
249#[doc(hidden)]
250#[must_use]
251pub fn undiscriminate_state<Storage, T, S>(
252 state: State<SDiscriminated<Storage>, T, S>,
253) -> State<Storage, T, S>
254where
255 Storage: StateStorage,
256 T: StateMachineImpl,
257{
258 State::from_inner(state.inner.inner)
259}
260
261#[doc(hidden)]
262#[must_use]
263pub fn concretize_discriminated_state<Storage, T, Marker, Concrete>(
264 state: DiscriminatedState<Storage, T, Marker>,
265) -> State<Storage, T, Concrete>
266where
267 Storage: StateStorage,
268 T: StateMachineImpl,
269 Marker: StateUnionDiscriminant,
270{
271 State::from_inner(Storage::retag(state.inner.inner))
272}
273
274#[doc(hidden)]
275#[must_use]
276pub fn discriminated_state_marker<Storage, T, S>(
277 state: &State<SDiscriminated<Storage>, T, S>,
278) -> state_trait::ErasedState
279where
280 Storage: StateStorage,
281 T: StateMachineImpl,
282 S: StateTrait,
283{
284 state
285 .inner
286 .inference
287 .state::<Storage, T, S>(&state.inner.inner)
288}
289
290#[doc(hidden)]
291#[must_use]
292pub fn state_union_marker<Storage, T, S>(state: &State<Storage, T, S>) -> state_trait::ErasedState
293where
294 Storage: StateStorage,
295 T: StateMachineImpl,
296 S: StateTrait,
297{
298 Storage::inferred_state(&state.inner)
299}
300
301#[doc(hidden)]
302#[must_use]
303pub fn erased_state_type_id(state: &state_trait::ErasedState) -> TypeId {
304 state.type_id()
305}
306
307#[doc(hidden)]
309pub struct SDiscriminated<Storage>(PhantomData<fn() -> Storage>);
310
311#[doc(hidden)]
312pub struct DiscriminatedInner<Inner, Inference> {
313 pub(crate) inner: Inner,
314 pub(crate) inference: Inference,
315}
316
317impl<Storage> StateStorage for SDiscriminated<Storage>
318where
319 Storage: StateStorage,
320{
321 type Inference = Storage::Inference;
322
323 type Inner<T, S>
324 = DiscriminatedInner<
325 Storage::Inner<T, S>,
326 <Storage::Inference as crate::InferenceKind>::Inference,
327 >
328 where
329 T: StateMachineImpl;
330 type Machine<T>
331 = Storage::Machine<T>
332 where
333 T: StateMachineImpl;
334
335 fn retag<T, From, To>(inner: Self::Inner<T, From>) -> Self::Inner<T, To>
336 where
337 T: StateMachineImpl,
338 {
339 DiscriminatedInner {
340 inner: Storage::retag(inner.inner),
341 inference: inner.inference,
342 }
343 }
344
345 fn inferred_state<T, State>(inner: &Self::Inner<T, State>) -> state_trait::ErasedState
346 where
347 T: StateMachineImpl,
348 State: StateTrait,
349 {
350 inner.inference.state::<Storage, T, State>(&inner.inner)
351 }
352}
353
354impl<Storage> MayTransition for SDiscriminated<Storage>
355where
356 Storage: MayTransition,
357{
358 fn complete_transition<T, From, To, Args>(
359 state: State<Self, T, From>,
360 args: Args,
361 callsite: TransitionCallsite,
362 ) -> State<Self, T, To>
363 where
364 T: StateMachineImpl,
365 From: StateTrait,
366 To: crate::ConcreteStateTrait,
367 T::Standin: Transition<From, To>,
368 <T::Standin as Transition<From, To>>::F: crate::TransitionSignature<Args>,
369 {
370 let state = State::<Storage, T, From>::from_inner(state.inner.inner);
371 let state = Storage::complete_transition(state, args, callsite);
372 let inference =
373 <<Storage::Inference as crate::InferenceKind>::Inference as crate::StateInference>::new::<
374 Storage,
375 T,
376 To,
377 >(&state.inner);
378 State::from_inner(DiscriminatedInner {
379 inner: state.inner,
380 inference,
381 })
382 }
383
384 fn complete_transition_after_effect<T, From, To>(
385 state: State<Self, T, From>,
386 callsite: TransitionCallsite,
387 ) -> State<Self, T, To>
388 where
389 T: StateMachineImpl,
390 From: StateTrait,
391 To: crate::ConcreteStateTrait,
392 {
393 let state = State::<Storage, T, From>::from_inner(state.inner.inner);
394 let state = Storage::complete_transition_after_effect(state, callsite);
395 let inference =
396 <<Storage::Inference as crate::InferenceKind>::Inference as crate::StateInference>::new::<
397 Storage,
398 T,
399 To,
400 >(&state.inner);
401 State::from_inner(DiscriminatedInner {
402 inner: state.inner,
403 inference,
404 })
405 }
406}
407
408impl<Storage> SRef for SDiscriminated<Storage>
409where
410 Storage: SRef,
411{
412 fn s_ref<T, S>(inner: &Self::Inner<T, S>) -> &T
413 where
414 T: StateMachineImpl,
415 {
416 Storage::s_ref(&inner.inner)
417 }
418}
419
420impl<Storage> SMut for SDiscriminated<Storage>
421where
422 Storage: SMut,
423{
424 fn s_mut<T, S>(inner: &mut Self::Inner<T, S>) -> &mut T
425 where
426 T: StateMachineImpl,
427 {
428 Storage::s_mut(&mut inner.inner)
429 }
430}
431
432impl<Storage> SPinRef for SDiscriminated<Storage>
433where
434 Storage: SPinRef,
435{
436 fn s_pin_ref<T, S>(inner: &Self::Inner<T, S>) -> core::pin::Pin<&T>
437 where
438 T: StateMachineImpl,
439 {
440 Storage::s_pin_ref(&inner.inner)
441 }
442}
443
444impl<Storage> SPinMut for SDiscriminated<Storage>
445where
446 Storage: SPinMut,
447{
448 fn s_pin_mut<T, S>(inner: &mut Self::Inner<T, S>) -> core::pin::Pin<&mut T>
449 where
450 T: StateMachineImpl,
451 {
452 Storage::s_pin_mut(&mut inner.inner)
453 }
454}
455
456impl<Storage> SMove for SDiscriminated<Storage> where Storage: SMove {}
457
458impl<Storage, FromRuntime, ToRuntime> SMapRuntime<FromRuntime, ToRuntime>
459 for SDiscriminated<Storage>
460where
461 Storage: SMapRuntime<FromRuntime, ToRuntime>,
462 FromRuntime: StateMachineImpl,
463 ToRuntime: StateMachineImpl,
464{
465 fn map_runtime<S, F>(state: State<Self, FromRuntime, S>, f: F) -> State<Self, ToRuntime, S>
466 where
467 F: FnOnce(FromRuntime) -> ToRuntime,
468 {
469 let inference = state.inner.inference;
470 let state = State::<Storage, FromRuntime, S>::from_inner(state.inner.inner);
471 let state = Storage::map_runtime(state, f);
472 State::from_inner(DiscriminatedInner {
473 inner: state.inner,
474 inference,
475 })
476 }
477}
478
479#[doc(hidden)]
481pub trait StateUnionErased<Marker>: StateTrait {
482 fn into_union_erased<Storage, T>(
483 state: State<Storage, T, Self>,
484 ) -> DiscriminatedState<Storage, T, Marker>
485 where
486 Self: Sized,
487 Storage: StateStorage,
488 T: StateMachineImpl,
489 Marker: StateUnionDiscriminant;
490}
491
492#[doc(hidden)]
494pub trait StateUnionRuntime {
495 fn contains(state: &dyn StateTrait) -> bool;
496 fn expected_type_name() -> &'static str;
497}
498
499#[doc(hidden)]
501pub trait StateUnionTransition<Standin, To> {
502 type F;
503}
504
505#[doc(hidden)]
507pub trait StateUnionProofMembership<Marker>: StateUnionErased<Marker>
508where
509 Marker: StateUnionDiscriminant,
510{
511}
512
513#[doc(hidden)]
515pub trait StateUnionProofTarget<T, From>: crate::ConcreteStateTrait + Sized
516where
517 T: StateMachineImpl,
518 From: StateTrait,
519{
520 type Marker: StateUnionDiscriminant + StateUnionSharedEffect<T, Self>;
521}
522
523#[doc(hidden)]
525pub trait StateUnionSharedEffect<T, To>: StateUnionDiscriminant
526where
527 T: StateMachineImpl,
528 To: crate::ConcreteStateTrait,
529{
530 type Effect;
531}
532
533#[doc(hidden)]
535pub trait StateUnionSharedTransitionEffect<T, To, Args>: StateUnionSharedEffect<T, To>
536where
537 T: StateMachineImpl,
538 To: crate::ConcreteStateTrait,
539{
540 fn apply(value: &mut T, args: Args);
541}
542
543#[doc(hidden)]
545pub trait StateUnionSharedPinnedEffect<T, To>: StateUnionDiscriminant
546where
547 T: StateMachineImpl,
548 To: crate::ConcreteStateTrait,
549{
550 type Effect;
551}
552
553#[doc(hidden)]
555pub trait StateUnionSharedPinnedTransitionEffect<T, To, Args>:
556 StateUnionSharedPinnedEffect<T, To>
557where
558 T: StateMachineImpl,
559 To: crate::ConcreteStateTrait,
560{
561 fn apply_pinned(value: Pin<&mut T>, args: Args);
562}
563
564#[doc(hidden)]
566pub trait StateUnionDiscriminatedTransition<T, To, Args>: StateUnionDiscriminant
567where
568 T: StateMachineImpl,
569{
570 fn transition<Storage>(
571 state: DiscriminatedState<Storage, T, Self>,
572 args: Args,
573 callsite: TransitionCallsite,
574 ) -> State<Storage, T, To>
575 where
576 Storage: SMut,
577 To: crate::ConcreteStateTrait;
578}
579
580#[doc(hidden)]
582pub trait StateUnionDiscriminatedPinnedTransition<T, To, Args>: StateUnionDiscriminant
583where
584 T: StateMachineImpl,
585{
586 fn pinned_transition<Storage>(
587 state: DiscriminatedState<Storage, T, Self>,
588 args: Args,
589 callsite: TransitionCallsite,
590 ) -> State<Storage, T, To>
591 where
592 Storage: SPinMut,
593 To: crate::ConcreteStateTrait;
594}
595
596impl<Standin, Marker, To> Transition<StateUnionState<Marker>, To> for Standin
597where
598 Marker: StateUnionTransition<Standin, To>,
599{
600 type F = Marker::F;
601}