1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4#[derive(Clone)]
6pub enum Letter {
7 Single(String),
8 Multiple(Vec<String>),
9}
10
11impl Letter {
12 pub fn new<S: ToString>(symbol: S) -> Self {
14 Letter::Single(symbol.to_string())
15 }
16
17 pub fn from_symbols(symbols: Vec<String>) -> Self {
19 if symbols.len() == 1 {
20 Letter::Single(symbols.into_iter().next().unwrap())
21 } else {
22 let mut sorted = symbols;
23 sorted.sort();
24 sorted.dedup();
25 Letter::Multiple(sorted)
26 }
27 }
28
29 pub fn symbols(&self) -> String {
31 match self {
32 Letter::Single(s) => s.clone(),
33 Letter::Multiple(v) => v.join(","),
34 }
35 }
36
37 pub fn name(&self) -> String {
39 match self {
40 Letter::Single(s) => format!("Letter('{}')", s),
41 Letter::Multiple(v) => {
42 format!(
43 "Letter({})",
44 v.iter()
45 .map(|s| format!("'{}'", s))
46 .collect::<Vec<_>>()
47 .join(",")
48 )
49 }
50 }
51 }
52
53 pub fn is_empty(&self) -> bool {
55 false
56 }
57
58 pub fn deserialize(str_letters: &str, possible_letters: &[Letter]) -> Result<Letter, String> {
60 let mut letters = Vec::new();
61 for str_letter in str_letters.split(',') {
62 let found = possible_letters
63 .iter()
64 .find(|l| l.name() == str_letter)
65 .ok_or_else(|| format!("Cannot find any letter that fit with '{}'", str_letter))?;
66 letters.push(found.clone());
67 }
68
69 if letters.len() == 1 {
70 Ok(letters[0].clone())
71 } else {
72 let symbols: Vec<String> = letters
73 .iter()
74 .flat_map(|l| match l {
75 Letter::Single(s) => vec![s.clone()],
76 Letter::Multiple(v) => v.clone(),
77 })
78 .collect();
79 Ok(Letter::from_symbols(symbols))
80 }
81 }
82}
83
84impl PartialEq for Letter {
85 fn eq(&self, other: &Self) -> bool {
86 match (self, other) {
87 (Letter::Single(a), Letter::Single(b)) => a == b,
88 (Letter::Multiple(a), Letter::Multiple(b)) => a == b,
89 _ => false,
90 }
91 }
92}
93
94impl Eq for Letter {}
95
96impl Hash for Letter {
97 fn hash<H: Hasher>(&self, state: &mut H) {
98 match self {
99 Letter::Single(s) => {
100 0u8.hash(state);
101 s.hash(state);
102 }
103 Letter::Multiple(v) => {
104 1u8.hash(state);
105 v.hash(state);
106 }
107 }
108 }
109}
110
111impl fmt::Display for Letter {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 write!(f, "{}", self.name())
114 }
115}
116
117impl fmt::Debug for Letter {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 write!(f, "{}", self.name())
120 }
121}
122
123#[derive(Clone, PartialEq, Eq)]
125pub struct EmptyLetter;
126
127impl EmptyLetter {
128 pub fn new() -> Self {
129 EmptyLetter
130 }
131}
132
133impl Default for EmptyLetter {
134 fn default() -> Self {
135 EmptyLetter::new()
136 }
137}
138
139impl Hash for EmptyLetter {
140 fn hash<H: Hasher>(&self, state: &mut H) {
141 "EmptyLetter".hash(state);
142 }
143}
144
145impl fmt::Display for EmptyLetter {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 write!(f, "EmptyLetter")
148 }
149}
150
151impl fmt::Debug for EmptyLetter {
152 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153 write!(f, "EmptyLetter")
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn test_letter_creation() {
163 let letter = Letter::new("a");
164 assert_eq!(letter.name(), "Letter('a')");
165 }
166
167 #[test]
168 fn test_letter_equality() {
169 let l1 = Letter::new("a");
170 let l2 = Letter::new("a");
171 let l3 = Letter::new("b");
172
173 assert_eq!(l1, l2);
174 assert_ne!(l1, l3);
175 }
176
177 #[test]
178 fn test_empty_letter() {
179 let empty = EmptyLetter::new();
180 assert_eq!(empty.to_string(), "EmptyLetter");
181 }
182}