Skip to main content

aura_anim_iced/state/
matcher.rs

1use std::{hash::Hash, sync::Arc};
2
3use rustc_hash::FxHashMap;
4
5use crate::{StateTransition, Timeline};
6
7/// Reusable collection that matches state pairs to transition timelines.
8#[derive(Debug, Clone, PartialEq)]
9pub struct StateTransitionSet<S>
10where
11    S: Copy + Eq + Hash,
12{
13    transitions: Vec<StateTransition<S>>,
14    index: FxHashMap<(S, S), usize>,
15    fallback: Option<Arc<Timeline>>,
16}
17
18impl<S> StateTransitionSet<S>
19where
20    S: Copy + Eq + Hash,
21{
22    /// Creates an empty transition set.
23    #[must_use]
24    pub fn new() -> Self {
25        Self {
26            transitions: Vec::new(),
27            index: FxHashMap::default(),
28            fallback: None,
29        }
30    }
31
32    /// Creates a transition set from an iterator of transitions.
33    #[must_use]
34    pub fn from_transitions(transitions: impl IntoIterator<Item = StateTransition<S>>) -> Self {
35        let mut set = Self::new();
36
37        for transition in transitions {
38            set.push(transition);
39        }
40
41        set
42    }
43
44    /// Sets the fallback timeline used when no state-pair transition matches.
45    #[must_use]
46    pub fn with_fallback(mut self, fallback: Timeline) -> Self {
47        self.fallback = Some(Arc::new(fallback));
48        self
49    }
50
51    /// Adds a transition to the set.
52    pub fn push(&mut self, transition: StateTransition<S>) {
53        let key = (transition.from(), transition.to());
54        let index = self.transitions.len();
55
56        self.transitions.push(transition);
57        self.index.entry(key).or_insert(index);
58    }
59
60    /// Returns all transitions in insertion order.
61    #[must_use]
62    pub fn transitions(&self) -> &[StateTransition<S>] {
63        &self.transitions
64    }
65
66    /// Returns the fallback timeline, if one is configured.
67    #[must_use]
68    pub fn fallback(&self) -> Option<&Timeline> {
69        self.fallback.as_deref()
70    }
71
72    pub(crate) fn fallback_arc(&self) -> Option<Arc<Timeline>> {
73        self.fallback.as_ref().map(Arc::clone)
74    }
75
76    /// Returns the first transition matching `from` and `to`.
77    #[must_use]
78    pub fn find(&self, from: S, to: S) -> Option<&StateTransition<S>> {
79        self.index
80            .get(&(from, to))
81            .and_then(|index| self.transitions.get(*index))
82    }
83}
84
85impl<S> Default for StateTransitionSet<S>
86where
87    S: Copy + Eq + Hash,
88{
89    fn default() -> Self {
90        Self::new()
91    }
92}
93
94impl<S> From<Vec<StateTransition<S>>> for StateTransitionSet<S>
95where
96    S: Copy + Eq + Hash,
97{
98    fn from(value: Vec<StateTransition<S>>) -> Self {
99        Self::from_transitions(value)
100    }
101}