rstm_rules/
rule_map.rs

1/*
2    Appellation: workload <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5
6mod impl_rule_map;
7
8use super::Rule;
9
10use core::hash::Hash;
11use rstm_core::{Head, Tail};
12use rstm_state::{RawState, State};
13use std::collections::hash_map::{self, HashMap};
14
15#[derive(Clone, Debug, Default)]
16#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
17pub struct RuleMap<Q, S>
18where
19    Q: RawState + Eq + Hash,
20    S: Eq + Hash,
21{
22    pub(crate) initial_state: Option<State<Q>>,
23    pub(crate) rules: HashMap<Head<Q, S>, Tail<Q, S>>,
24}
25
26impl<Q, S> RuleMap<Q, S>
27where
28    Q: RawState + Eq + Hash,
29    S: Eq + Hash,
30{
31    pub fn new() -> Self {
32        Self {
33            initial_state: None,
34            rules: HashMap::new(),
35        }
36    }
37    /// returns a new instance of the [`RuleMap`] with the given initial state.
38    pub fn from_state(initial_state: State<Q>) -> Self {
39        Self {
40            initial_state: Some(initial_state),
41            rules: HashMap::new(),
42        }
43    }
44    #[allow(clippy::should_implement_trait)]
45    /// returns a new instance of the [`RuleMap`] composed from an iterator of head/tail pairs
46    pub fn from_iter<I>(iter: I) -> Self
47    where
48        I: IntoIterator<Item = (Head<Q, S>, Tail<Q, S>)>,
49    {
50        Self {
51            initial_state: None,
52            rules: HashMap::from_iter(iter),
53        }
54    }
55
56    pub fn from_rules<I>(iter: I) -> Self
57    where
58        I: IntoIterator<Item = super::Rule<Q, S>>,
59    {
60        Self::from_iter(iter.into_iter().map(|Rule { head, tail }| (head, tail)))
61    }
62    /// consumes the current instance to create another with the given initial state.
63    pub fn with_initial_state(self, state: State<Q>) -> Self {
64        Self {
65            initial_state: Some(state),
66            ..self
67        }
68    }
69    /// consumes the current instance to create another with the given instructions
70    pub fn with_instructions(
71        self,
72        instructions: impl IntoIterator<Item = (Head<Q, S>, Tail<Q, S>)>,
73    ) -> Self {
74        Self {
75            rules: HashMap::from_iter(instructions),
76            ..self
77        }
78    }
79    /// returns an instance of [State] which owns a reference to the interval value.
80    pub fn initial_state(&self) -> Option<State<&'_ Q>> {
81        self.initial_state.as_ref().map(|state| state.view())
82    }
83    /// returns an immutable reference to the set of rules.
84    pub const fn rules(&self) -> &HashMap<Head<Q, S>, Tail<Q, S>> {
85        &self.rules
86    }
87    /// returns a mutable reference to the set of rules.
88    pub const fn rules_mut(&mut self) -> &mut HashMap<Head<Q, S>, Tail<Q, S>> {
89        &mut self.rules
90    }
91    /// Clears the set of rules.
92    pub fn clear(&mut self) {
93        self.rules_mut().clear();
94    }
95    /// returns an the entry for the given head within the set of rules.
96    pub fn rule(&mut self, head: Head<Q, S>) -> hash_map::Entry<'_, Head<Q, S>, Tail<Q, S>> {
97        self.rules_mut().entry(head)
98    }
99    /// returns an immutable reference to the tail of the rule for the given head; returns none
100    /// if the head is not found.
101    pub fn get<K>(&self, head: &K) -> Option<&Tail<Q, S>>
102    where
103        K: Eq + Hash,
104        Head<Q, S>: core::borrow::Borrow<K>,
105    {
106        self.rules().get(head)
107    }
108    /// returns a mutable reference to the tail of the rule for the given head; returns none if
109    /// the head is not found.
110    pub fn get_mut<K>(&mut self, head: &K) -> Option<&mut Tail<Q, S>>
111    where
112        K: Eq + Hash,
113        Head<Q, S>: core::borrow::Borrow<K>,
114    {
115        self.rules_mut().get_mut(head)
116    }
117    /// returns the tail of the rule for the given head; returns none if the head is not found
118    /// within the set of rules.
119    pub fn get_tail_view<K>(&self, head: &K) -> Option<Tail<&Q, &S>>
120    where
121        K: Eq + Hash,
122        Head<Q, S>: core::borrow::Borrow<K>,
123    {
124        self.get(head).map(|tail| tail.view())
125    }
126    /// insert a new rule into the set of rules.
127    pub fn insert(&mut self, head: Head<Q, S>, tail: Tail<Q, S>)
128    where
129        Q: RawState + Eq + Hash,
130        S: Eq + Hash,
131    {
132        self.rules_mut().insert(head, tail);
133    }
134    /// insert a new rule into the set of rules.
135    pub fn insert_rule(&mut self, rule: Rule<Q, S>)
136    where
137        Q: RawState + Eq + Hash,
138        S: Eq + Hash,
139    {
140        self.insert(rule.head, rule.tail);
141    }
142    /// returns true if the set of rules is empty.
143    pub fn is_empty(&self) -> bool {
144        self.rules().is_empty()
145    }
146    /// returns the number of rules in the set.
147    pub fn len(&self) -> usize {
148        self.rules().len()
149    }
150    /// returns a mutable reference to the tail of the rule for the given head; inserts the
151    /// tail if the head is not found.
152    pub fn or_insert(&mut self, head: Head<Q, S>, tail: Tail<Q, S>) -> &mut Tail<Q, S> {
153        self.rule(head).or_insert(tail)
154    }
155    /// returns a mutable reference to the tail of the rule for the given head; inserts the
156    /// tail if the head is not found.
157    pub fn or_insert_with<F>(&mut self, head: Head<Q, S>, f: F) -> &mut Tail<Q, S>
158    where
159        F: FnOnce() -> Tail<Q, S>,
160    {
161        self.rule(head).or_insert_with(f)
162    }
163    /// returns a mutable reference to the tail of the rule for the given head; inserts the
164    /// default tail if the head is not found.
165    pub fn or_insert_default(&mut self, head: Head<Q, S>) -> &mut Tail<Q, S>
166    where
167        Q: Default,
168        S: Default,
169    {
170        self.or_insert(head, Tail::default())
171    }
172    /// Removes a rule from the set of rules.
173    pub fn remove(&mut self, head: &Head<Q, S>) -> Option<Tail<Q, S>> {
174        self.rules_mut().remove(head)
175    }
176}
177
178#[allow(deprecated)]
179impl<Q, S> RuleMap<Q, S>
180where
181    Q: RawState + Eq + Hash,
182    S: Eq + Hash,
183{
184    #[deprecated(since = "0.1.0", note = "use `get` instead, which is more concise.")]
185    pub fn get_head<K>(&self, head: &K) -> Option<&Tail<Q, S>>
186    where
187        K: Eq + Hash,
188        Head<Q, S>: core::borrow::Borrow<K>,
189    {
190        self.rules().get(head)
191    }
192}