rstm_programs/program/
impl_program.rs

1/*
2    Appellation: impl_program <module>
3    Created At: 2025.09.04:19:04:56
4    Contrib: @FL03
5*/
6use crate::program::Program;
7
8use crate::types::RuleVec;
9use rstm_core::{Head, Rule, Tail};
10use rstm_state::{RawState, State};
11
12use alloc::vec::{self, Vec};
13
14impl<Q, A> Program<Q, A>
15where
16    Q: RawState,
17{
18    /// returns an immutable reference to the tail for a given head; returns [`None`](Option::None)
19    /// if no match is found.
20    pub fn get(&self, head: &Head<Q, A>) -> Option<&Tail<Q, A>>
21    where
22        Q: PartialEq,
23        A: PartialEq,
24    {
25        self.iter().find_map(|i| {
26            if i.head() == head {
27                Some(i.tail())
28            } else {
29                None
30            }
31        })
32    }
33    /// returns a mutable reference to the tail for a given head; returns [`None`](Option::None)
34    /// if no match is found.
35    pub fn get_mut(&mut self, head: &Head<Q, A>) -> Option<&mut Tail<Q, A>>
36    where
37        Q: PartialEq,
38        A: PartialEq,
39    {
40        self.iter_mut().find_map(|i| {
41            if i.head() == head {
42                Some(i.tail_mut())
43            } else {
44                None
45            }
46        })
47    }
48    /// returns an immutable reference to the tail of a rule whose state and symbol match the
49    /// givens
50    pub fn find_tail(&self, state: State<&Q>, symbol: &A) -> Option<&Tail<Q, A>>
51    where
52        Q: PartialEq,
53        A: PartialEq,
54    {
55        self.iter().find_map(|i| {
56            if i.head().view() == (Head { state, symbol }) {
57                Some(i.tail())
58            } else {
59                None
60            }
61        })
62    }
63    /// returns a mutable reference to the tail for a given head; returns [`None`](Option::None)
64    /// if no match is found.
65    pub fn find_mut_tail(&mut self, state: State<&Q>, symbol: &A) -> Option<&mut Tail<Q, A>>
66    where
67        Q: PartialEq,
68        A: PartialEq,
69    {
70        self.iter_mut().find_map(|i| {
71            if i.head().view() == (Head { state, symbol }) {
72                Some(i.tail_mut())
73            } else {
74                None
75            }
76        })
77    }
78    /// Returns a collection of rules whose head contains a match for the given state.
79    pub fn filter_by_state(&self, state: State<&Q>) -> Vec<&Rule<Q, A>>
80    where
81        Q: PartialEq,
82    {
83        self.iter().filter(|i| *i.head() == state).collect()
84    }
85    #[cfg(all(feature = "json", feature = "std"))]
86    /// saves the current program as a `.json` file at the given path
87    pub fn export_json<P: AsRef<std::path::Path>>(&self, path: P) -> std::io::Result<()>
88    where
89        Q: serde::Serialize,
90        A: serde::Serialize,
91    {
92        let serialized = serde_json::to_string_pretty(self).unwrap();
93        std::fs::write(path, serialized)?;
94        #[cfg(feature = "tracing")]
95        tracing::info!("Program exported as JSON");
96        Ok(())
97    }
98}
99
100impl<Q, A> AsRef<[Rule<Q, A>]> for Program<Q, A>
101where
102    Q: RawState,
103{
104    fn as_ref(&self) -> &[Rule<Q, A>] {
105        self.rules()
106    }
107}
108
109impl<Q, A> AsMut<[Rule<Q, A>]> for Program<Q, A>
110where
111    Q: RawState,
112{
113    fn as_mut(&mut self) -> &mut [Rule<Q, A>] {
114        self.rules_mut()
115    }
116}
117
118impl<Q, A> core::ops::Deref for Program<Q, A>
119where
120    Q: RawState,
121{
122    type Target = [Rule<Q, A>];
123
124    fn deref(&self) -> &Self::Target {
125        &self.rules
126    }
127}
128
129impl<Q, A> core::ops::DerefMut for Program<Q, A>
130where
131    Q: RawState,
132{
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        &mut self.rules
135    }
136}
137
138impl<Q, A> core::ops::Index<Head<Q, A>> for Program<Q, A>
139where
140    Q: RawState + PartialEq,
141    A: PartialEq,
142{
143    type Output = Tail<Q, A>;
144
145    fn index(&self, index: Head<Q, A>) -> &Self::Output {
146        self.get(&index).unwrap()
147    }
148}
149
150impl<Q, A> From<Vec<Rule<Q, A>>> for Program<Q, A>
151where
152    Q: RawState + Default,
153{
154    fn from(rules: Vec<Rule<Q, A>>) -> Self {
155        Self::from_rules(rules)
156    }
157}
158
159impl<Q, A> Extend<Rule<Q, A>> for Program<Q, A>
160where
161    Q: RawState,
162{
163    fn extend<I: IntoIterator<Item = Rule<Q, A>>>(&mut self, iter: I) {
164        self.rules_mut().extend(iter)
165    }
166}
167
168impl<Q, A> Extend<(Head<Q, A>, Tail<Q, A>)> for Program<Q, A>
169where
170    Q: RawState,
171{
172    fn extend<I: IntoIterator<Item = (Head<Q, A>, Tail<Q, A>)>>(&mut self, iter: I) {
173        self.rules_mut()
174            .extend(iter.into_iter().map(|(head, tail)| Rule { head, tail }))
175    }
176}
177
178impl<Q, A> FromIterator<Rule<Q, A>> for Program<Q, A>
179where
180    Q: RawState,
181{
182    fn from_iter<I: IntoIterator<Item = Rule<Q, A>>>(iter: I) -> Self {
183        Self {
184            initial_state: None,
185            rules: iter.into_iter().collect::<RuleVec<Q, A>>(),
186        }
187    }
188}
189
190impl<Q, A> FromIterator<(Head<Q, A>, Tail<Q, A>)> for Program<Q, A>
191where
192    Q: RawState,
193{
194    fn from_iter<I: IntoIterator<Item = (Head<Q, A>, Tail<Q, A>)>>(iter: I) -> Self {
195        Self::from_rules(iter.into_iter().map(|(head, tail)| Rule { head, tail }))
196    }
197}
198
199impl<Q, A> IntoIterator for Program<Q, A>
200where
201    Q: RawState,
202{
203    type Item = Rule<Q, A>;
204    type IntoIter = vec::IntoIter<Self::Item>;
205
206    fn into_iter(self) -> Self::IntoIter {
207        self.rules.into_iter()
208    }
209}