letter_sequence/
sequence.rs

1pub mod builder;
2pub mod combined;
3pub mod helper;
4pub mod renderer;
5
6pub use element::Element;
7
8use std::convert::Into;
9
10use super::*;
11use crate::sequence::renderer::*;
12use std::fmt;
13
14use std::ops::{AddAssign, SubAssign};
15
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct Sequence {
18	// start is needed a sequence of 9 will rollover to 0, but the starting
19	// state will be 9.
20	start: u64,
21	end: Option<u64>,
22	inner: Option<u64>,
23	step: u32,
24	// If you hard .set() something, next call to .next() returns that element
25	initialized: bool,
26	// Forces .next() to return None
27	done: bool,
28	renderer: SeqRenderer,
29}
30
31impl Default for Sequence {
32	fn default() -> Self {
33		Self {
34			initialized: false,
35			start: 0,
36			end: None,
37			inner: None,
38			done: false,
39			renderer: Default::default(),
40			step: 1,
41		}
42	}
43}
44
45impl Iterator for Sequence {
46	type Item = Element;
47
48	fn next(&mut self) -> Option<Self::Item> {
49		match (self.done, self.initialized, self.inner) {
50			(true, _, _) => None,
51			(false, false, Some(_)) => {
52				self.initialized = true;
53				Some(self.generate_element())
54			}
55			(false, _, None) => {
56				self.initialized = true;
57				match self.inner(self.start) {
58					Ok(_) => Some(self.generate_element()),
59					_ => None
60				}
61			},
62			(false, true, Some(_)) => {
63				match self.add(self.step as u64) {
64					Ok(_) => Some(self.generate_element()),
65					Err(_) => { self.done = true; None }
66				}
67			}
68		}
69	}
70}
71
72impl fmt::Display for Sequence {
73	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
74		write!(f, "{}", 42 ) // self.renderer.render(self.inner).unwrap())
75	}
76}
77
78/// ```rust
79/// ```
80impl Sequence {
81	/// Create a new instance, as above, but do not check for violations of
82	/// display
83	fn new_unchecked(inner: u64) -> Self {
84		Self {
85			start: inner,
86			..Self::default()
87		}
88	}
89
90	/// Reset the sequence to 0
91	pub fn reset(&mut self) {
92		self.inner = None;
93		self.done = false;
94	}
95	
96	pub fn zero(&mut self) {
97		self.initialized = false;
98		self.inner = Some(0);
99		self.done = false;
100	}
101	
102	pub fn rollover(&mut self) {
103		self.initialized = true;
104		self.inner = Some(0);
105		self.done = false;
106	}
107
108	/// Add rhs to sequence
109	pub fn add(&mut self, rhs: u64) -> Result<(), SequenceError> {
110		match (self.done, self.inner) {
111			(true, _) => Err(SequenceError::Done),
112			(false, None) => Err(SequenceError::Uninitialized),
113			(false, Some(inner)) => match inner.checked_add(rhs) {
114				None => return Err(SequenceError::OutOfRange),
115				Some(new_inner) => self.inner(new_inner)
116			}
117		}
118	}
119
120	/// This should probably check that the result is > 0
121	pub fn sub(&mut self, rhs: u64) -> Result<(), SequenceError> {
122		match (self.done, self.inner) {
123			(true, _) => Err(SequenceError::Done),
124			(false, None) => Err(SequenceError::Uninitialized),
125			(false, Some(inner)) => match inner.checked_sub(rhs) {
126				None => return Err(SequenceError::OutOfRange),
127				Some(new_inner) => self.inner(new_inner)
128			}
129		}
130	}
131
132	pub fn set(&mut self, inner: u64) -> Option<Element> {
133		self.initialized = false;
134		self.inner(inner).map( |_| self.generate_element()).ok()
135	}
136
137	fn inner(&mut self, new_inner: u64) -> Result<(), SequenceError> {
138		// Calculated max render exhausted
139		if let Some(renderlimit) = self.renderer.max() {
140			if renderlimit < new_inner {
141				return Err(SequenceError::OutOfRangeRender);
142			}
143		}
144		// User imposed end of sequence
145		if let Some(end) = self.end {
146			if end <= new_inner {
147				return Err(SequenceError::OutOfRange);
148			}
149		}
150		self.inner = Some(new_inner);
151		Ok(())
152	}
153
154	fn generate_element(&self) -> Element {
155		element::ElementBuilder::default()
156			.inner(self.inner.unwrap())
157			.renderer(self.renderer.clone())
158			.build()
159			.unwrap()
160	}
161}
162
163impl<T: Into<u64>> AddAssign<T> for Sequence {
164	fn add_assign(&mut self, rhs: T) {
165		self.initialized = false;
166		self.add(rhs.into()).expect("Failed to call add_assisgn on sequence");
167	}
168}
169
170impl<T: Into<u64>> SubAssign<T> for Sequence {
171	fn sub_assign(&mut self, rhs: T) {
172		self.initialized = false;
173		self.sub(rhs.into()).expect("Failed to call sub_assign on sequence");
174	}
175}
176
177#[cfg(test)]
178mod test {
179	use super::*;
180
181	#[test]
182	fn default() {
183		let mut seq = Sequence::default();
184		let elem = seq.next().unwrap();
185		assert_eq!(elem.to_string(), "0");
186	}
187
188	#[test]
189	fn new_unchecked() {
190		let mut seq = Sequence::new_unchecked(u64::MAX);
191		let elem = seq.next().unwrap();
192		assert_eq!(
193			elem.to_string(),
194			u64::MAX.to_string()
195		);
196	}
197
198	#[test]
199	fn num() {
200		for i in 0..123_456 {
201			let mut seq = SequenceBuilder::new().start(i).build().unwrap();
202			let elem = seq.next().unwrap();
203			assert_eq!(elem.to_string(), i.to_string());
204		}
205	}
206
207	#[test]
208	fn lower() {
209		for i in 0..100 {
210			let mut seq = SequenceBuilder::new().start(i).lower().build().unwrap();
211			let elem = seq.next().unwrap();
212			assert_eq!(
213				elem.to_string().matches(|c: char| !c.is_lowercase()).count(),
214				0
215			);
216			assert_eq!(seq.to_string(), seq.to_string().to_ascii_lowercase(),)
217		}
218	}
219
220	#[test]
221	fn upper() {
222		for i in 0..100 {
223			let mut seq = SequenceBuilder::new().start(i).upper().build().unwrap();
224			let elem = seq.next().unwrap();
225			assert_eq!(
226				elem.to_string().matches(|c: char| !c.is_uppercase()).count(),
227				0
228			);
229			assert_eq!(seq.to_string(), seq.to_string().to_ascii_uppercase(),)
230		}
231	}
232
233	//inner: 1 * 26u64.pow(2) + 1 * 26u64.pow(1)  + 0 * 26u64.pow(0),
234	#[test]
235	fn rollover() {
236		use std::convert::TryFrom;
237		let mut seq = SequenceBuilder::try_from("Z").unwrap().build().unwrap();
238		let elem = seq.next().unwrap();
239		assert_eq!(elem.to_string(), "Z");
240		let elem = seq.next().unwrap();
241		assert_eq!(elem.to_string(), "AA");
242		let elem = seq.next().unwrap();
243		assert_eq!(elem.to_string(), "AB");
244
245		let mut seq = SequenceBuilder::try_from("z").unwrap().build().unwrap();
246		let elem = seq.next().unwrap();
247		assert_eq!(elem.to_string(), "z");
248		let elem = seq.next().unwrap();
249		assert_eq!(elem.to_string(), "aa");
250		let elem = seq.next().unwrap();
251		assert_eq!(elem.to_string(), "ab");
252
253		let mut seq = SequenceBuilder::try_from("9").unwrap().build().unwrap();
254		let elem = seq.next().unwrap();
255		assert_eq!(elem.to_string(), (9).to_string());
256		let elem = seq.next().unwrap();
257		assert_eq!(elem.to_string(), (10).to_string());
258		let elem = seq.next().unwrap();
259		assert_eq!(elem.to_string(), (11).to_string());
260	}
261
262	#[test]
263	fn zero() {
264		use std::convert::TryFrom;
265		let mut seq = SequenceBuilder::try_from(0).unwrap().build().unwrap();
266		let elem = seq.next().unwrap();
267		assert_eq!(elem.to_string(), "0");
268		let elem = seq.next().unwrap();
269		assert_eq!(elem.to_string(), "1");
270		seq.zero();
271		let elem = seq.next().unwrap();
272		assert_eq!(elem.to_string(), "0");
273	}
274
275	#[test]
276	fn assignmod() {
277		let mut seq = SequenceBuilder::new().start(42).build().unwrap();
278
279		let elem = seq.next().unwrap();
280		assert_eq!( elem.to_string(), "42" );
281
282		// += and -= for unsigned int
283		seq += 0u32;
284		let elem = seq.next().unwrap();
285		assert_eq!( elem.to_string(), "42" );
286
287		seq += 5u32;
288		let elem = seq.next().unwrap();
289		assert_eq!( elem.to_string(), "47" );
290
291		seq -= 5u32;
292		let elem = seq.next().unwrap();
293		assert_eq!( elem.to_string(), "42" );
294	}
295}