letter_sequence/sequence/
builder.rs1use crate::sequence::helper::*;
2use std::convert::From;
3use std::convert::TryFrom;
4use super::*;
5
6#[derive(Debug)]
91pub struct SequenceBuilder {
92 start: u64,
93 step: u32,
94 inclusive: bool,
95 renderer: SeqRendererBuilder,
96 min_render_length: Option<u8>,
97 end: Option<u64>
98}
99
100impl Default for SequenceBuilder {
101 fn default() -> Self {
102 Self {
103 start: 0,
104 step: 1,
105 end: None,
106 inclusive: false,
107 renderer: Default::default(),
108 min_render_length: Default::default(),
109 }
110 }
111}
112
113impl SequenceBuilder {
114 pub fn new() -> Self {
115 Self { ..Default::default() }
116 }
117
118
119 pub fn end(mut self, end: u64) -> Self {
121 self.end = Some(end);
122 self
123 }
124
125 pub fn start(mut self, start: u64) -> Self {
127 self.start = start;
128 self
129 }
130
131 pub fn step(mut self, step: u32) -> Self {
133 self.step = step;
134 self
135 }
136
137
138 pub fn max_render_capacity(mut self, chars: u8) -> Self {
153 self.renderer = self.renderer.capacity(chars);
154 self
155 }
156
157 pub fn min_render_length(mut self, chars: u8) -> Self {
160 self.min_render_length = Some(chars);
161 self
162 }
163
164 pub fn exclusive(mut self) -> Self {
166 self.inclusive = false;
167 self
168 }
169
170 pub fn inclusive(mut self) -> Self {
172 self.inclusive = true;
173 self
174 }
175
176 pub fn lower(mut self) -> Self {
178 self.renderer = SeqRendererBuilder::lower();
179 self
180 }
181 pub fn upper(mut self) -> Self {
183 self.renderer = SeqRendererBuilder::upper();
184 self
185 }
186 pub fn numeric(mut self) -> Self {
188 self.renderer = SeqRendererBuilder::numeric();
189 self
190 }
191
192 pub fn build(self) -> Result<Sequence, SequenceError> {
193 let renderer = self.renderer.build()?;
194
195 match (renderer.display(), self.min_render_length) {
197 (RenderDisplay::Upper | RenderDisplay::Lower, Some(_)) => return Err(SequenceError::PaddingAlpha),
198 _ => ()
199 };
200
201 let end = match (self.end, self.inclusive) {
202 (Some(end), true) => Some(end + 1),
203 (Some(end), false) => Some(end),
204 _ => None
205 };
206 let seq = Sequence {
207 end,
208 step: self.step,
209 start: self.start,
210 renderer,
211 .. Default::default()
212 };
213 Ok(seq)
214 }
215}
216
217impl From<u64> for SequenceBuilder {
218 fn from(start: u64) -> Self {
219 Self::new().start(start)
220 }
221}
222
223impl TryFrom<&str> for SequenceBuilder {
245 type Error = SequenceError;
246 fn try_from(value: &str) -> Result<Self, Self::Error> {
247 let first_char = value
248 .chars()
249 .next()
250 .ok_or_else( || SequenceError::EmptyString )?
251 ;
252
253 match renderer::RenderDisplay::try_from(first_char)? {
254 renderer::RenderDisplay::Numeric => Ok(
255 Self::new().start(value.parse::<u64>()?).numeric()
256 ),
257 renderer::RenderDisplay::Upper => Ok(
258 Self::new().start(string_to_int(&value)?).upper()
259 ),
260 renderer::RenderDisplay::Lower => Ok(
261 Self::new().start(string_to_int(&value)?).lower()
262 )
263 }
264 }
265}
266
267impl TryFrom<(&str, &str)> for SequenceBuilder {
268 type Error = SequenceError;
269 fn try_from((start, end): (&str, &str)) -> Result<Self, Self::Error> {
270 let first_char = start
271 .chars()
272 .next()
273 .ok_or_else( || SequenceError::EmptyString )?
274 ;
275
276 let builder = match renderer::RenderDisplay::try_from(first_char)? {
277 renderer::RenderDisplay::Numeric => {
278 Self::new()
279 .start(start.parse::<u64>()?)
280 .end(end.parse::<u64>()?)
281 .numeric()
282 },
283 renderer::RenderDisplay::Upper => {
284 Self::new()
285 .start(string_to_int(&start)?)
286 .end(string_to_int(&end)?)
287 .upper()
288 },
289 renderer::RenderDisplay::Lower => {
290 Self::new()
291 .start(string_to_int(&start)?)
292 .end(string_to_int(&end)?)
293 .lower()
294 }
295 };
296
297 Ok(builder)
298 }
299}
300
301impl TryFrom<char> for SequenceBuilder {
302 type Error = SequenceError;
303 fn try_from(value: char) -> Result<Self, Self::Error> {
304 Ok(Self::new().start(char_to_int(value)? as u64))
305 }
306}
307
308#[cfg(test)]
309mod test {
310 use super::*;
311
312 fn max_render_capacity() {
314 for limit in 1..10 {
316 let max = crate::sequence::renderer::max_alpha(limit);
317 let mut seq = SequenceBuilder::new().start(max)
318 .upper()
319 .max_render_capacity(limit)
320 .build()
321 .unwrap();
322 let render_as = "Z".repeat(limit as usize);
323 let elem = seq.next().unwrap();
324 assert_eq!( elem.to_string(), render_as );
325 let elem = seq.next();
326 assert_eq!( elem, None );
327 assert_eq!( seq.next(), None )
328 }
329
330 for limit in 1..10 {
332 let max = crate::sequence::renderer::max_numeric(limit);
333 let mut seq = SequenceBuilder::new().start(max).numeric().max_render_capacity(limit).build().unwrap();
334 let render_as = "9".repeat(limit as usize);
335 assert_eq!( seq.to_string(), render_as, "Render {} as {}", max, render_as );
336 assert_eq!(
337 seq.next(),
338 None,
339 "Throw error with numeric char limit of {} which can only represent {}",
340 limit,
341 max
342 );
343 assert_eq!( seq.next(), None )
344 }
345 }
346
347 #[test]
349 fn simple() {
350 for c in 'A'..'Z' {
351 let mut seq = SequenceBuilder::new().start(c as u64 - 'A' as u64).upper().build().unwrap();
353 let elem = seq.next().unwrap();
354 assert_eq!(
355 elem.to_string(),
356 c.to_string(),
357 );
358
359 let mut seq = SequenceBuilder::new().start(c as u64 - 'A' as u64).lower().build().unwrap();
361 let elem = seq.next().unwrap();
362 assert_eq!(
363 elem.to_string(),
364 c.to_string().to_lowercase(),
365 );
366 }
367
368 for i in 1..123_456 {
370 let mut seq = SequenceBuilder::new().start(i).numeric().build().unwrap();
371 let elem = seq.next().unwrap();
372 assert_eq!(
373 elem.to_string(),
374 i.to_string()
375 );
376 }
377 }
378
379 fn rollover() {
380 const A: u32 = 0;
381 const Z: u32 = 25;
382 for i in A..Z {
383
384 let seq = SequenceBuilder::new().start(Z as u64).upper().build().unwrap();
386 let result = format!("A{}", std::char::from_u32('A' as u32 + i).unwrap());
387 assert_eq!(
388 seq.skip(i as usize + 1).next().unwrap().to_string(),
389 result
390 );
391
392 let mut seq = SequenceBuilder::new().start(Z as u64).upper().build().unwrap();
393 assert_eq!(
394 seq.nth(i as usize + 1).unwrap().to_string(),
395 result,
396 ".nth({})", i
397 );
398
399 let seq = SequenceBuilder::new().start(Z as u64 + 1 + i as u64).lower().build().unwrap();
400 assert_eq!(
401 seq.to_string(),
402 result.to_lowercase()
403 );
404
405 let mut seq = SequenceBuilder::new().start(A as u64).upper().build().unwrap();
406 for len in 1..5 {
407 assert_eq!(
408 seq.nth(26usize.pow(len as u32) - 1).unwrap().to_string(),
409 "A".repeat(len + 1),
410 );
411 }
412
413 let mut seq = SequenceBuilder::new().start(Z as u64).upper().build().unwrap();
414 for len in 2..5 {
415 assert_eq!(
416 seq.nth(26usize.pow(len as u32) - 1).unwrap().to_string(),
417 "Z".repeat(len),
418 );
419 }
420 }
421 }
422
423}