rusty_systems/
strings.rs

1//! Provides tools for handling strings of  [`Symbol`] objects which are rewritten using [`crate::productions::Production`]
2//! rules of a [`System`].
3//!
4//! The main struct is [`ProductionString`]. These can be parsed from a text string using
5//! [`parser::parse_prod_string`](crate::parser::parse_prod_string). See [`ProductionString`]
6//! for more details.
7
8use std::fmt::{Display, Formatter, Write};
9use std::iter::Cloned;
10use std::ops::Index;
11use std::slice::Iter;
12use crate::prelude::*;
13
14/// Represents strings in our L-system. Strings
15/// are made up of a list of [`Symbol`] objects.
16///
17/// If you would like to parse an instance of this struct
18/// from a string, you can use
19/// [`parser::parse_prod_string`](crate::parser::parse_prod_string), like so:
20///
21/// ```
22/// use rusty_systems::parser;
23/// let axiom = parser::parse_prod_string("Forward Forward Forward").unwrap();
24/// ```
25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct ProductionString {
27    symbols: Vec<Symbol>
28}
29
30impl ProductionString {
31    /// Create an empty string
32    pub fn new() -> Self {
33        ProductionString {
34            symbols: Vec::new()
35        }
36    }
37
38    /// Creates an / the _empty_ production string. This is a
39    /// synonym for [`ProductionString::new`].
40    #[inline]
41    pub fn empty() -> Self {
42        ProductionString::new()
43    }
44
45    /// Whether the production string is empty or not. i.e., whether this is
46    /// the _empty_ string.
47    #[inline]
48    pub fn is_empty(&self) -> bool {
49        self.symbols.is_empty()
50    }
51
52    /// Returns the length of the production string.
53    #[inline]
54    pub fn len(&self) -> usize {
55        self.symbols.len()
56    }
57
58    /// Access the symbols of this production string.
59    #[inline]
60    pub fn symbols(&self) -> &Vec<Symbol> {
61        &self.symbols
62    }
63
64    /// Add another symbol to the end of the string.
65    #[inline]
66    pub fn push_symbol(&mut self, symbol: Symbol) {
67        self.symbols.push(symbol);
68    }
69
70    /// Iterate over the symbols.
71    #[inline]
72    pub fn iter(&self) -> Iter<'_, Symbol> {
73        self.symbols.iter()
74    }
75}
76
77impl Default for ProductionString {
78    fn default() -> Self {
79        ProductionString::new()
80    }
81}
82
83impl From<Vec<Symbol>> for ProductionString {
84    fn from(value: Vec<Symbol>) -> Self {
85        ProductionString {
86            symbols: value
87        }
88    }
89}
90
91impl Index<usize> for ProductionString {
92    type Output = Symbol;
93
94    fn index(&self, index: usize) -> &Self::Output {
95        &self.symbols[index]
96    }
97}
98
99
100impl From<Symbol> for ProductionString {
101    fn from(value: Symbol) -> Self {
102        ProductionString {
103            symbols: vec![value]
104        }
105    }
106}
107
108impl IntoIterator for ProductionString {
109    type Item = Symbol;
110    type IntoIter = std::vec::IntoIter<Self::Item>;
111
112    fn into_iter(self) -> Self::IntoIter {
113        self.symbols.into_iter()
114    }
115}
116
117impl<'a> IntoIterator for &'a ProductionString {
118    type Item = Symbol;
119    type IntoIter = Cloned<Iter<'a, Self::Item>>;
120
121    fn into_iter(self) -> Self::IntoIter {
122        self.symbols.iter().cloned()
123    }
124}
125
126impl Display for ProductionString {
127    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
128        let mut first = true;
129        for symbol in self.symbols() {
130            if !first {
131                f.write_char(' ')?;
132            } else {
133                first = false;
134            }
135            f.write_str(symbol.to_string().as_str())?;
136        }
137        
138        Ok(())
139        
140    }
141}
142
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn empty_string_is_empty() {
150        let empty = ProductionString::empty();
151
152        assert!(empty.is_empty());
153        assert_eq!(empty.len(), 0);
154    }
155}