1use crate::{MorseCode, MorseSequence};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct MorseWord {
11 code: u8,
12}
13
14macro_rules! from_word {
15 ($num:literal) => {
16 impl From<[MorseCode; $num]> for MorseWord {
17 fn from(codes: [MorseCode; $num]) -> Self {
19 MorseWord::new(codes)
20 }
21 }
22 };
23}
24
25from_word!(1);
26from_word!(2);
27from_word!(3);
28from_word!(4);
29from_word!(5);
30
31impl MorseWord {
32 const fn new<const N: usize>(codes: [MorseCode; N]) -> Self {
33 debug_assert!(N <= 5);
34
35 let mut code: u8 = (N as u8) & 0b0000_0111;
37
38 if N >= 1 {
39 code |= codes[0].to_bit() << 3;
40 }
41
42 if N >= 2 {
43 code |= codes[1].to_bit() << 4;
44 }
45
46 if N >= 3 {
47 code |= codes[2].to_bit() << 5;
48 }
49
50 if N >= 4 {
51 code |= codes[3].to_bit() << 6;
52 }
53
54 if N == 5 {
55 code |= codes[4].to_bit() << 7;
56 }
57
58 MorseWord { code }
59 }
60
61 pub const fn to_array(self) -> (usize, [MorseCode; 5]) {
88 let mut codes = [MorseCode::Dot; 5];
89 let n = self.len();
90
91 if n >= 1 {
92 codes[0] = if self.code & 0b0000_0001 == 0 {
93 MorseCode::Dot
94 } else {
95 MorseCode::Dash
96 };
97 }
98
99 if n >= 2 {
100 codes[1] = if self.code & 0b0000_0010 == 0 {
101 MorseCode::Dot
102 } else {
103 MorseCode::Dash
104 };
105 }
106
107 if n >= 3 {
108 codes[2] = if self.code & 0b0000_0100 == 0 {
109 MorseCode::Dot
110 } else {
111 MorseCode::Dash
112 };
113 }
114
115 if n >= 4 {
116 codes[3] = if self.code & 0b0000_1000 == 0 {
117 MorseCode::Dot
118 } else {
119 MorseCode::Dash
120 };
121 }
122
123 if n == 5 {
124 codes[4] = if self.code & 0b0001_0000 == 0 {
125 MorseCode::Dot
126 } else {
127 MorseCode::Dash
128 };
129 }
130
131 (n, codes)
132 }
133
134 pub const fn len(&self) -> usize {
136 debug_assert!(self.code & 0b0000_0111 <= 5);
137 (self.code & 0b0000_0111) as usize
138 }
139
140 pub const fn is_empty(&self) -> bool {
144 self.len() == 0
145 }
146
147 pub const fn to_sequence(self) -> (usize, [MorseSequence; 9]) {
161 let mut sequence = [MorseSequence::Pause; 9];
162
163 let (n, codes) = self.to_array();
164
165 debug_assert!(n <= 5);
166
167 if n >= 1 {
168 sequence[0] = MorseSequence::Code(codes[0]);
169 }
170
171 if n >= 2 {
172 sequence[2] = MorseSequence::Code(codes[1]);
173 }
174
175 if n >= 3 {
176 sequence[4] = MorseSequence::Code(codes[2]);
177 }
178
179 if n >= 4 {
180 sequence[6] = MorseSequence::Code(codes[3]);
181 }
182
183 if n == 5 {
184 sequence[8] = MorseSequence::Code(codes[4]);
185 }
186
187 let seq_len = 2 * n - 1;
188
189 debug_assert!(seq_len <= 9);
190
191 (seq_len, sequence)
192 }
193}
194
195impl TryFrom<char> for MorseWord {
202 type Error = ();
203
204 fn try_from(value: char) -> Result<Self, Self::Error> {
205 let as_lower = value.to_ascii_lowercase();
206
207 let word = match as_lower {
208 'a' => MorseWord::from([MorseCode::Dot, MorseCode::Dash]),
209 'b' => MorseWord::from([
210 MorseCode::Dash,
211 MorseCode::Dot,
212 MorseCode::Dot,
213 MorseCode::Dot,
214 ]),
215 'c' => MorseWord::from([
216 MorseCode::Dash,
217 MorseCode::Dot,
218 MorseCode::Dash,
219 MorseCode::Dot,
220 ]),
221 'd' => MorseWord::from([MorseCode::Dash, MorseCode::Dot, MorseCode::Dot]),
222 'e' => MorseWord::from([MorseCode::Dot]),
223 'f' => MorseWord::from([
224 MorseCode::Dot,
225 MorseCode::Dot,
226 MorseCode::Dash,
227 MorseCode::Dot,
228 ]),
229 'g' => MorseWord::from([MorseCode::Dash, MorseCode::Dash, MorseCode::Dot]),
230 'h' => MorseWord::from([
231 MorseCode::Dot,
232 MorseCode::Dot,
233 MorseCode::Dot,
234 MorseCode::Dot,
235 ]),
236 'i' => MorseWord::from([MorseCode::Dot, MorseCode::Dot]),
237 'j' => MorseWord::from([
238 MorseCode::Dot,
239 MorseCode::Dash,
240 MorseCode::Dash,
241 MorseCode::Dash,
242 ]),
243 'k' => MorseWord::from([MorseCode::Dash, MorseCode::Dot, MorseCode::Dash]),
244 'l' => MorseWord::from([
245 MorseCode::Dot,
246 MorseCode::Dash,
247 MorseCode::Dot,
248 MorseCode::Dot,
249 ]),
250 'm' => MorseWord::from([MorseCode::Dash, MorseCode::Dash]),
251 'n' => MorseWord::from([MorseCode::Dash, MorseCode::Dot]),
252 'o' => MorseWord::from([MorseCode::Dash, MorseCode::Dash, MorseCode::Dash]),
253 'p' => MorseWord::from([
254 MorseCode::Dot,
255 MorseCode::Dash,
256 MorseCode::Dash,
257 MorseCode::Dot,
258 ]),
259 'q' => MorseWord::from([
260 MorseCode::Dash,
261 MorseCode::Dash,
262 MorseCode::Dot,
263 MorseCode::Dash,
264 ]),
265 'r' => MorseWord::from([MorseCode::Dot, MorseCode::Dash, MorseCode::Dot]),
266 's' => MorseWord::from([MorseCode::Dot, MorseCode::Dot, MorseCode::Dot]),
267 't' => MorseWord::from([MorseCode::Dash]),
268 'u' => MorseWord::from([MorseCode::Dot, MorseCode::Dot, MorseCode::Dash]),
269 'v' => MorseWord::from([
270 MorseCode::Dot,
271 MorseCode::Dot,
272 MorseCode::Dot,
273 MorseCode::Dash,
274 ]),
275 'w' => MorseWord::from([MorseCode::Dot, MorseCode::Dash, MorseCode::Dash]),
276 'x' => MorseWord::from([
277 MorseCode::Dash,
278 MorseCode::Dot,
279 MorseCode::Dot,
280 MorseCode::Dash,
281 ]),
282 'y' => MorseWord::from([
283 MorseCode::Dash,
284 MorseCode::Dot,
285 MorseCode::Dash,
286 MorseCode::Dash,
287 ]),
288 'z' => MorseWord::from([
289 MorseCode::Dash,
290 MorseCode::Dash,
291 MorseCode::Dot,
292 MorseCode::Dot,
293 ]),
294 '0' => MorseWord::from([
295 MorseCode::Dash,
296 MorseCode::Dash,
297 MorseCode::Dash,
298 MorseCode::Dash,
299 MorseCode::Dash,
300 ]),
301 '1' => MorseWord::from([
302 MorseCode::Dot,
303 MorseCode::Dash,
304 MorseCode::Dash,
305 MorseCode::Dash,
306 MorseCode::Dash,
307 ]),
308 '2' => MorseWord::from([
309 MorseCode::Dot,
310 MorseCode::Dot,
311 MorseCode::Dash,
312 MorseCode::Dash,
313 MorseCode::Dash,
314 ]),
315 '3' => MorseWord::from([
316 MorseCode::Dot,
317 MorseCode::Dot,
318 MorseCode::Dot,
319 MorseCode::Dash,
320 MorseCode::Dash,
321 ]),
322 '4' => MorseWord::from([
323 MorseCode::Dot,
324 MorseCode::Dot,
325 MorseCode::Dot,
326 MorseCode::Dot,
327 MorseCode::Dash,
328 ]),
329 '5' => MorseWord::from([
330 MorseCode::Dot,
331 MorseCode::Dot,
332 MorseCode::Dot,
333 MorseCode::Dot,
334 MorseCode::Dot,
335 ]),
336 '6' => MorseWord::from([
337 MorseCode::Dash,
338 MorseCode::Dot,
339 MorseCode::Dot,
340 MorseCode::Dot,
341 MorseCode::Dot,
342 ]),
343 '7' => MorseWord::from([
344 MorseCode::Dash,
345 MorseCode::Dash,
346 MorseCode::Dot,
347 MorseCode::Dot,
348 MorseCode::Dot,
349 ]),
350 '8' => MorseWord::from([
351 MorseCode::Dash,
352 MorseCode::Dash,
353 MorseCode::Dash,
354 MorseCode::Dot,
355 MorseCode::Dot,
356 ]),
357 '9' => MorseWord::from([
358 MorseCode::Dash,
359 MorseCode::Dash,
360 MorseCode::Dash,
361 MorseCode::Dash,
362 MorseCode::Dot,
363 ]),
364 _ => return Err(()),
365 };
366
367 Ok(word)
368 }
369}