letter_sequence/sequence/
renderer.rs1use super::*;
2use crate::sequence::helper::*;
3use std::convert::TryFrom;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum RenderDisplay {
8 Upper,
9 Lower,
10 Numeric,
11}
12
13impl Default for RenderDisplay {
14 fn default() -> Self { RenderDisplay::Numeric }
15}
16
17
18impl TryFrom<char> for RenderDisplay {
31 type Error = SequenceError;
32 fn try_from(c: char) -> Result<Self, Self::Error> {
33 if c.is_ascii_digit() {
34 Ok(RenderDisplay::Numeric)
35 }
36 else if c.is_ascii_lowercase() {
37 Ok(RenderDisplay::Lower)
38 }
39 else if c.is_ascii_uppercase() {
40 Ok(RenderDisplay::Upper)
41 }
42 else {
43 Err(SequenceError::InvalidCharacter(c))
44 }
45 }
46}
47
48impl TryFrom<&str> for RenderDisplay {
49 type Error = SequenceError;
50 fn try_from(str: &str) -> Result<Self, Self::Error> {
52 let char = str.chars().next();
53 match char {
54 Some(char) => Ok(RenderDisplay::try_from(char)?),
55 None => Err(SequenceError::EmptyString)
56 }
57 }
58}
59
60#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
61pub struct SeqRenderer {
62 display: RenderDisplay,
64 capacity: Option<u8>,
66 length: Option<u8>,
68}
69
70impl SeqRenderer {
71 pub fn display(self) -> RenderDisplay { self.display }
72
73 pub fn render(&self, x: u64) -> Result<String, SequenceError> {
89 let result = match self.display {
90 RenderDisplay::Upper => int_to_string(x)?,
91 RenderDisplay::Lower => {
92 let mut display = int_to_string(x)?;
93 display.make_ascii_lowercase();
94 display.to_string()
95 }
96 RenderDisplay::Numeric => x.to_string()
97 };
98
99 if let Some(capacity) = self.capacity {
100 if result.len() > capacity as usize {
101 return Err(SequenceError::OutOfRange)
102 }
103 }
104
105 match (self.length, self.display) {
106 (None, _) => Ok(result),
107 (Some(length), RenderDisplay::Numeric) => Ok(format!("{:0>len$}", result, len=length as usize)),
108 (_, RenderDisplay::Upper | RenderDisplay::Lower) => Err(SequenceError::PaddingAlpha),
109 }
110 }
111 pub fn max(&self) -> Option<u64> {
112 if let Some(char_limit) = self.capacity {
113 match self.display {
114 RenderDisplay::Upper | RenderDisplay::Lower => Some(max_alpha(char_limit)),
115 RenderDisplay::Numeric => Some(max_numeric(char_limit)),
116 }
117 }
118 else {
119 None
120 }
121 }
122}
123
124#[derive(Default, Debug)]
125pub struct SeqRendererBuilder {
126 display: RenderDisplay,
127 capacity: Option<u8>,
128 length: Option<u8>,
129}
130
131impl SeqRendererBuilder {
132 pub fn upper() -> Self { Self::new_with_display( RenderDisplay::Upper) }
133 pub fn lower() -> Self { Self::new_with_display( RenderDisplay::Lower) }
134 pub fn numeric() -> Self { Self::new_with_display( RenderDisplay::Numeric) }
135 pub fn set_upper(self) -> Self { self.set_display(RenderDisplay::Upper) }
136 pub fn set_lower(self) -> Self { self.set_display(RenderDisplay::Lower) }
137 pub fn set_numeric(self) -> Self { self.set_display(RenderDisplay::Numeric) }
138 pub fn set_display(mut self, display: RenderDisplay) -> Self {
139 self.display = display;
140 self
141 }
142 fn new_with_display(display: RenderDisplay) -> Self { Self { display, ..Default::default() } }
143 pub fn capacity(mut self, val: u8) -> Self { self.capacity = Some(val); self }
145 pub fn length(mut self, val: u8) -> Self { self.length = Some(val); self }
147 pub fn build(self) -> Result<SeqRenderer,SequenceError> {
150 let sr = SeqRenderer {
151 capacity: self.capacity,
152 display: self.display,
153 length: self.length,
154 .. Default::default()
155 };
156 Ok(sr)
157 }
158}
159
160
161pub fn max_alpha(chars: u8) -> u64 {
170 const BASE : u64 = 26;
171 const Z: u32 = 25;
172
173 let mut max: u64 = 0;
174 for x in 0..chars {
175 max += (1 + Z) as u64 * BASE.pow(x as u32)
176 }
177 max -= 1;
178 max
179}
180
181pub fn max_numeric(chars: u8) -> u64 {
191 10u64.pow(chars as u32) - 1
192}