letter_sequence/sequence/
combined.rs1use super::*;
4use crate::sequence::renderer::RenderDisplay;
5use std::convert::From;
6use std::convert::TryFrom;
7use std::fmt::Display;
8use std::iter::Iterator;
9
10#[derive(Default, Debug, Clone)]
39pub struct CombinedSequence {
40 inner: Vec<Sequence>,
41 done: bool,
42 initialized: bool,
43}
44
45
46impl CombinedSequence {
47 fn new() -> Self {
48 Self::default()
49 }
50 pub fn push(&mut self, seq: Sequence) {
51 self.inner.push(seq)
52 }
53
54 pub fn sequences(&self) -> std::slice::Iter<Sequence> {
56 self.inner.iter()
57 }
58 pub fn sequences_mut(&mut self) -> std::slice::IterMut<Sequence> {
60 self.inner.iter_mut()
61 }
62
63 pub fn reset(&mut self) {
77 self.initialized = false;
78 for seq in &mut self.sequences_mut() {
79 seq.reset()
80 }
81 }
82
83 pub fn zero(&mut self) {
93 self.initialized = false;
94 for seq in &mut self.sequences_mut() {
95 seq.zero()
96 }
97 }
98
99 fn generate_element(&self) -> CombinedElement {
100 let mut ce = CombinedElement::new();
101 for s in self.sequences() {
102 ce.push(s.generate_element())
103 }
104 ce
105 }
106
107}
108
109impl Iterator for CombinedSequence {
110 type Item = CombinedElement;
111
112 fn next(&mut self) -> Option<Self::Item> {
123 match (self.done, self.initialized) {
124 (_, false) => {
125 for s in &mut self.sequences_mut() {
126 s.next();
127 }
128 self.initialized = true;
129 Some(self.generate_element())
130 }
131 (true, _) => { dbg!("done = true"); None },
132 (false, true) => {
133 for s in &mut self.sequences_mut() {
134 match s.next() {
135 None => s.rollover(),
136 Some(_) => break
137 };
138 }
139 Some(self.generate_element())
140 },
141 }
142 }
143}
144
145impl From<Vec<Sequence>> for CombinedSequence {
146 fn from(vec: Vec<Sequence>) -> Self {
147 Self { inner: vec, .. Default::default() }
148 }
149}
150
151impl TryFrom<&str> for CombinedSequence {
152 type Error = SequenceError;
153
154 fn try_from(input: &str) -> Result<CombinedSequence, Self::Error> {
155 let mut input : &mut str = &mut input.to_owned();
156 if ! input.is_ascii() {
157 return Err(SequenceError::InvalidString);
158 }
159
160 let mut splits: Vec<(usize, RenderDisplay)> = Vec::new();
161 let mut iter = input.char_indices();
162 while let Some((i, val)) = iter.next() {
163 let val = RenderDisplay::try_from(val)?;
164 match splits.last() {
165 Some((_, lastval)) if *lastval != val => splits.push( (i,val) ),
167 None => splits.push( (i,val) ),
169 _ => ()
170 }
171 }
172
173 let mut cs = CombinedSequence::new();
174 while let Some((idx, _)) = splits.pop() {
175 let (init, last) = input.split_at_mut(idx);
176 input = &mut(*init);
177 let mut seq = SequenceBuilder::try_from(&*last).unwrap();
178 if ! splits.is_empty() {
179 let length = last.len();
180 seq = seq.max_render_capacity(length as u8);
181 }
182 cs.push( seq.build()? );
183 }
184 Ok(cs)
185 }
186}
187
188#[derive(Debug, Default, Clone)]
189pub struct CombinedElement {
190 inner: Vec<Element>
191}
192
193impl CombinedElement {
194 fn new() -> Self {
195 Self::default()
196 }
197 pub fn push(&mut self, elem: Element) {
198 self.inner.push(elem)
199 }
200 pub fn elements(&self) -> std::slice::Iter<Element> {
202 self.inner.iter()
203 }
204}
205
206impl Display for CombinedElement {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 for i in self.elements().rev() {
209 write!(f, "{}", i )?
210 }
211 Ok(())
212 }
213}
214
215
216#[cfg(test)]
217mod test {
218 use super::*;
219
220
221 #[test]
223 fn one_char() {
224 let mut seq = SequenceBuilder::try_from("A").unwrap().build().unwrap();
225 let mut cs = CombinedSequence::try_from("A").unwrap();
226 let elem = seq.next().unwrap();
227 let celem = cs.next().unwrap();
228 assert_eq!( elem.to_string(), "A" );
229 assert_eq!( celem.to_string(), "A" );
230
231 let elem = seq.next().unwrap();
232 let celem = cs.next().unwrap();
233 assert_eq!( elem.to_string(), "B" );
234 assert_eq!( celem.to_string(), "B" );
235 }
236
237 #[test]
238 fn two_char() {
239 let mut seq = CombinedSequence::try_from("A0").unwrap();
240 let elem = seq.next().unwrap();
241 assert_eq!( elem.to_string(), "A0" );
242 let elem = seq.next().unwrap();
243 assert_eq!( elem.to_string(), "A1" );
244 }
245
246 #[test]
247 fn segment_access() {
248 let mut seq = CombinedSequence::try_from("A9").unwrap();
249 let segment1 = seq.inner[0].next().unwrap();
250 assert_eq!( segment1.to_string(), "9" );
251 let segment1 = seq.inner[0].next();
252 assert_eq!( segment1, None );
253 }
254
255
256 #[test]
257 fn one_char_with_rollover() {
258 let mut seq = CombinedSequence::try_from("9").unwrap();
259 let elem = seq.next().unwrap();
260 assert_eq!( elem.to_string(), "9" );
261 let elem = seq.next().unwrap();
262 assert_eq!( elem.to_string(), "10" );
263
264 let mut seq = CombinedSequence::try_from("Z").unwrap();
265 let elem = seq.next().unwrap();
266 assert_eq!( elem.to_string(), "Z" );
267 let elem = seq.next().unwrap();
268 assert_eq!( elem.to_string(), "AA" );
269 }
270
271 #[test]
272 fn two_char_with_rollover1() {
273 let mut seq = CombinedSequence::try_from("A9").unwrap();
274 let elem = seq.next().unwrap();
275 assert_eq!( elem.to_string(), "A9" );
276 let elem = seq.next().unwrap();
277 assert_eq!( elem.to_string(), "B0" );
278 let elem = seq.next().unwrap();
279 assert_eq!( elem.to_string(), "B1" );
280
281 let mut seq = CombinedSequence::try_from("9A").unwrap();
282 let elem = seq.next().unwrap();
283 assert_eq!( elem.to_string(), "9A" );
284 let elem = seq.next().unwrap();
285 assert_eq!( elem.to_string(), "9B" );
286 let elem = seq.next().unwrap();
287 assert_eq!( elem.to_string(), "9C" );
288
289 let mut seq = CombinedSequence::try_from("Z9ZZ").unwrap();
290 let elem = seq.next().unwrap();
291 assert_eq!( elem.to_string(), "Z9ZZ" );
292 let elem = seq.next().unwrap();
293 assert_eq!( elem.to_string(), "AA0A" );
294 }
295}