1#![warn(missing_docs)]
2use std::{collections::HashMap, fmt::Display};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum BarcodeType {
15 CodeA,
17 CodeB,
19 CodeC,
21}
22
23impl BarcodeType {
24 fn other_set(&self) -> Option<Self> {
25 match self {
26 BarcodeType::CodeA => Some(BarcodeType::CodeB),
27 BarcodeType::CodeB => Some(BarcodeType::CodeA),
28 BarcodeType::CodeC => None,
30 }
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum BarcodeValue {
38 RegularCharacter(char),
40 Digit(u8),
42 FNC1,
44 FNC2,
46 FNC3,
48 FNC4,
50 StartA,
52 StartB,
54 StartC,
56 Stop,
58 ShiftA,
60 ShiftB,
62 CodeA,
64 CodeB,
66 CodeC,
68}
69
70impl From<char> for BarcodeValue {
71 fn from(value: char) -> Self {
72 BarcodeValue::RegularCharacter(value)
73 }
74}
75
76impl From<u8> for BarcodeValue {
77 fn from(value: u8) -> Self {
78 BarcodeValue::Digit(value)
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub struct TableEntry {
85 value: u8,
86 pub a: BarcodeValue,
88 pub b: BarcodeValue,
90 pub c: BarcodeValue,
92 latin: char,
93}
94
95impl TableEntry {
96 pub fn new(
98 value: u8,
99 a: impl Into<BarcodeValue>,
100 b: impl Into<BarcodeValue>,
101 c: impl Into<BarcodeValue>,
102 latin: char,
103 ) -> Self {
104 Self::new_barcode_value(value, a.into(), b.into(), c.into(), latin)
105 }
106
107 const fn new_barcode_value(
108 value: u8,
109 a: BarcodeValue,
110 b: BarcodeValue,
111 c: BarcodeValue,
112 latin: char,
113 ) -> Self {
114 TableEntry {
115 value,
116 a,
117 b,
118 c,
119 latin,
120 }
121 }
122
123 const fn new_barcode_chars(value: u8, a: char, b: char, c: u8, latin: char) -> Self {
124 Self::new_barcode_value(
125 value,
126 BarcodeValue::RegularCharacter(a),
127 BarcodeValue::RegularCharacter(b),
128 BarcodeValue::Digit(c),
129 latin,
130 )
131 }
132
133 pub fn value(&self) -> u8 {
135 self.value
136 }
137
138 pub fn latin(&self) -> char {
140 self.latin
141 }
142
143 pub fn barcode_bits(&self) -> u32 {
145 BARCODE_BITS[self.value() as usize].0
146 }
147
148 pub fn barcode_runs(&self) -> &'static str {
152 BARCODE_BITS[self.value() as usize].1
153 }
154}
155
156const BARCODE_BITS: [(u32, &str); 109] = [
157 (0b11011001100, "212222"),
158 (0b11001101100, "222122"),
159 (0b11001100110, "222221"),
160 (0b10010011000, "121223"),
161 (0b10010001100, "121322"),
162 (0b10001001100, "131222"),
163 (0b10011001000, "122213"),
164 (0b10011000100, "122312"),
165 (0b10001100100, "132212"),
166 (0b11001001000, "221213"),
167 (0b11001000100, "221312"),
168 (0b11000100100, "231212"),
169 (0b10110011100, "112232"),
170 (0b10011011100, "122132"),
171 (0b10011001110, "122231"),
172 (0b10111001100, "113222"),
173 (0b10011101100, "123122"),
174 (0b10011100110, "123221"),
175 (0b11001110010, "223211"),
176 (0b11001011100, "221132"),
177 (0b11001001110, "221231"),
178 (0b11011100100, "213212"),
179 (0b11001110100, "223112"),
180 (0b11101101110, "312131"),
181 (0b11101001100, "311222"),
182 (0b11100101100, "321122"),
183 (0b11100100110, "321221"),
184 (0b11101100100, "312212"),
185 (0b11100110100, "322112"),
186 (0b11100110010, "322211"),
187 (0b11011011000, "212123"),
188 (0b11011000110, "212321"),
189 (0b11000110110, "232121"),
190 (0b10100011000, "111323"),
191 (0b10001011000, "131123"),
192 (0b10001000110, "131321"),
193 (0b10110001000, "112313"),
194 (0b10001101000, "132113"),
195 (0b10001100010, "132311"),
196 (0b11010001000, "211313"),
197 (0b11000101000, "231113"),
198 (0b11000100010, "231311"),
199 (0b10110111000, "112133"),
200 (0b10110001110, "112331"),
201 (0b10001101110, "132131"),
202 (0b10111011000, "113123"),
203 (0b10111000110, "113321"),
204 (0b10001110110, "133121"),
205 (0b11101110110, "313121"),
206 (0b11010001110, "211331"),
207 (0b11000101110, "231131"),
208 (0b11011101000, "213113"),
209 (0b11011100010, "213311"),
210 (0b11011101110, "213131"),
211 (0b11101011000, "311123"),
212 (0b11101000110, "311321"),
213 (0b11100010110, "331121"),
214 (0b11101101000, "312113"),
215 (0b11101100010, "312311"),
216 (0b11100011010, "332111"),
217 (0b11101111010, "314111"),
218 (0b11001000010, "221411"),
219 (0b11110001010, "431111"),
220 (0b10100110000, "111224"),
221 (0b10100001100, "111422"),
222 (0b10010110000, "121124"),
223 (0b10010000110, "121421"),
224 (0b10000101100, "141122"),
225 (0b10000100110, "141221"),
226 (0b10110010000, "112214"),
227 (0b10110000100, "112412"),
228 (0b10011010000, "122114"),
229 (0b10011000010, "122411"),
230 (0b10000110100, "142112"),
231 (0b10000110010, "142211"),
232 (0b11000010010, "241211"),
233 (0b11001010000, "221114"),
234 (0b11110111010, "413111"),
235 (0b11000010100, "241112"),
236 (0b10001111010, "134111"),
237 (0b10100111100, "111242"),
238 (0b10010111100, "121142"),
239 (0b10010011110, "121241"),
240 (0b10111100100, "114212"),
241 (0b10011110100, "124112"),
242 (0b10011110010, "124211"),
243 (0b11110100100, "411212"),
244 (0b11110010100, "421112"),
245 (0b11110010010, "421211"),
246 (0b11011011110, "212141"),
247 (0b11011110110, "214121"),
248 (0b11110110110, "412121"),
249 (0b10101111000, "111143"),
250 (0b10100011110, "111341"),
251 (0b10001011110, "131141"),
252 (0b10111101000, "114113"),
253 (0b10111100010, "114311"),
254 (0b11110101000, "411113"),
255 (0b11110100010, "411311"),
256 (0b10111011110, "113141"),
257 (0b10111101110, "114131"),
258 (0b11101011110, "311141"),
259 (0b11110101110, "411131"),
260 (0b11010000100, "211412"),
261 (0b11010010000, "211214"),
262 (0b11010011100, "211232"),
263 (0b11000111010, "233111"),
264 (0b11010111000, "211133"),
265 (0b1100011101011, "2331112"),
266];
267
268#[derive(Debug, Clone)]
270pub struct Table {
271 entries: [TableEntry; 107],
272}
273
274impl Table {
275 pub const fn new() -> Self {
277 Table {
278 entries: [
279 TableEntry::new_barcode_chars(0, ' ', ' ', 0, ' '),
280 TableEntry::new_barcode_chars(1, '!', '!', 1, '!'),
281 TableEntry::new_barcode_chars(2, '"', '"', 2, '"'),
282 TableEntry::new_barcode_chars(3, '#', '#', 3, '#'),
283 TableEntry::new_barcode_chars(4, '$', '$', 4, '$'),
284 TableEntry::new_barcode_chars(5, '%', '%', 5, '%'),
285 TableEntry::new_barcode_chars(6, '&', '&', 6, '&'),
286 TableEntry::new_barcode_chars(7, '\'', '\'', 7, '\''),
287 TableEntry::new_barcode_chars(8, '(', '(', 8, '('),
288 TableEntry::new_barcode_chars(9, ')', ')', 9, ')'),
289 TableEntry::new_barcode_chars(10, '*', '*', 10, '*'),
290 TableEntry::new_barcode_chars(11, '+', '+', 11, '+'),
291 TableEntry::new_barcode_chars(12, ',', ',', 12, ','),
292 TableEntry::new_barcode_chars(13, '-', '-', 13, '-'),
293 TableEntry::new_barcode_chars(14, '.', '.', 14, '.'),
294 TableEntry::new_barcode_chars(15, '/', '/', 15, '/'),
295 TableEntry::new_barcode_chars(16, '0', '0', 16, '0'),
296 TableEntry::new_barcode_chars(17, '1', '1', 17, '1'),
297 TableEntry::new_barcode_chars(18, '2', '2', 18, '2'),
298 TableEntry::new_barcode_chars(19, '3', '3', 19, '3'),
299 TableEntry::new_barcode_chars(20, '4', '4', 20, '4'),
300 TableEntry::new_barcode_chars(21, '5', '5', 21, '5'),
301 TableEntry::new_barcode_chars(22, '6', '6', 22, '6'),
302 TableEntry::new_barcode_chars(23, '7', '7', 23, '7'),
303 TableEntry::new_barcode_chars(24, '8', '8', 24, '8'),
304 TableEntry::new_barcode_chars(25, '9', '9', 25, '9'),
305 TableEntry::new_barcode_chars(26, ':', ':', 26, ':'),
306 TableEntry::new_barcode_chars(27, ';', ';', 27, ';'),
307 TableEntry::new_barcode_chars(28, '<', '<', 28, '<'),
308 TableEntry::new_barcode_chars(29, '=', '=', 29, '='),
309 TableEntry::new_barcode_chars(30, '>', '>', 30, '>'),
310 TableEntry::new_barcode_chars(31, '?', '?', 31, '?'),
311 TableEntry::new_barcode_chars(32, '@', '@', 32, '@'),
312 TableEntry::new_barcode_chars(33, 'A', 'A', 33, 'A'),
313 TableEntry::new_barcode_chars(34, 'B', 'B', 34, 'B'),
314 TableEntry::new_barcode_chars(35, 'C', 'C', 35, 'C'),
315 TableEntry::new_barcode_chars(36, 'D', 'D', 36, 'D'),
316 TableEntry::new_barcode_chars(37, 'E', 'E', 37, 'E'),
317 TableEntry::new_barcode_chars(38, 'F', 'F', 38, 'F'),
318 TableEntry::new_barcode_chars(39, 'G', 'G', 39, 'G'),
319 TableEntry::new_barcode_chars(40, 'H', 'H', 40, 'H'),
320 TableEntry::new_barcode_chars(41, 'I', 'I', 41, 'I'),
321 TableEntry::new_barcode_chars(42, 'J', 'J', 42, 'J'),
322 TableEntry::new_barcode_chars(43, 'K', 'K', 43, 'K'),
323 TableEntry::new_barcode_chars(44, 'L', 'L', 44, 'L'),
324 TableEntry::new_barcode_chars(45, 'M', 'M', 45, 'M'),
325 TableEntry::new_barcode_chars(46, 'N', 'N', 46, 'N'),
326 TableEntry::new_barcode_chars(47, 'O', 'O', 47, 'O'),
327 TableEntry::new_barcode_chars(48, 'P', 'P', 48, 'P'),
328 TableEntry::new_barcode_chars(49, 'Q', 'Q', 49, 'Q'),
329 TableEntry::new_barcode_chars(50, 'R', 'R', 50, 'R'),
330 TableEntry::new_barcode_chars(51, 'S', 'S', 51, 'S'),
331 TableEntry::new_barcode_chars(52, 'T', 'T', 52, 'T'),
332 TableEntry::new_barcode_chars(53, 'U', 'U', 53, 'U'),
333 TableEntry::new_barcode_chars(54, 'V', 'V', 54, 'V'),
334 TableEntry::new_barcode_chars(55, 'W', 'W', 55, 'W'),
335 TableEntry::new_barcode_chars(56, 'X', 'X', 56, 'X'),
336 TableEntry::new_barcode_chars(57, 'Y', 'Y', 57, 'Y'),
337 TableEntry::new_barcode_chars(58, 'Z', 'Z', 58, 'Z'),
338 TableEntry::new_barcode_chars(59, '[', '[', 59, '['),
339 TableEntry::new_barcode_chars(60, '\\', '\\', 60, '\\'),
340 TableEntry::new_barcode_chars(61, ']', ']', 61, ']'),
341 TableEntry::new_barcode_chars(62, '^', '^', 62, '^'),
342 TableEntry::new_barcode_chars(63, '_', '_', 63, '_'),
343 TableEntry::new_barcode_chars(64, '\x00', '`', 64, '`'),
344 TableEntry::new_barcode_chars(65, '\x01', 'a', 65, 'a'),
345 TableEntry::new_barcode_chars(66, '\x02', 'b', 66, 'b'),
346 TableEntry::new_barcode_chars(67, '\x03', 'c', 67, 'c'),
347 TableEntry::new_barcode_chars(68, '\x04', 'd', 68, 'd'),
348 TableEntry::new_barcode_chars(69, '\x05', 'e', 69, 'e'),
349 TableEntry::new_barcode_chars(70, '\x06', 'f', 70, 'f'),
350 TableEntry::new_barcode_chars(71, '\x07', 'g', 71, 'g'),
351 TableEntry::new_barcode_chars(72, '\x08', 'h', 72, 'h'),
352 TableEntry::new_barcode_chars(73, '\x09', 'i', 73, 'i'),
353 TableEntry::new_barcode_chars(74, '\x0A', 'j', 74, 'j'),
354 TableEntry::new_barcode_chars(75, '\x0B', 'k', 75, 'k'),
355 TableEntry::new_barcode_chars(76, '\x0C', 'l', 76, 'l'),
356 TableEntry::new_barcode_chars(77, '\x0D', 'm', 77, 'm'),
357 TableEntry::new_barcode_chars(78, '\x0E', 'n', 78, 'n'),
358 TableEntry::new_barcode_chars(79, '\x0F', 'o', 79, 'o'),
359 TableEntry::new_barcode_chars(80, '\x10', 'p', 80, 'p'),
360 TableEntry::new_barcode_chars(81, '\x11', 'q', 81, 'q'),
361 TableEntry::new_barcode_chars(82, '\x12', 'r', 82, 'r'),
362 TableEntry::new_barcode_chars(83, '\x13', 's', 83, 's'),
363 TableEntry::new_barcode_chars(84, '\x14', 't', 84, 't'),
364 TableEntry::new_barcode_chars(85, '\x15', 'u', 85, 'u'),
365 TableEntry::new_barcode_chars(86, '\x16', 'v', 86, 'v'),
366 TableEntry::new_barcode_chars(87, '\x17', 'w', 87, 'w'),
367 TableEntry::new_barcode_chars(88, '\x18', 'x', 88, 'x'),
368 TableEntry::new_barcode_chars(89, '\x19', 'y', 89, 'y'),
369 TableEntry::new_barcode_chars(90, '\x1A', 'z', 90, 'z'),
370 TableEntry::new_barcode_chars(91, '\x1B', '{', 91, '{'),
371 TableEntry::new_barcode_chars(92, '\x1C', '|', 92, '|'),
372 TableEntry::new_barcode_chars(93, '\x1D', '}', 93, '}'),
373 TableEntry::new_barcode_chars(94, '\x1E', '~', 94, '~'),
374 TableEntry::new_barcode_chars(95, '\x1F', '\x7F', 95, 'Ã'),
375 TableEntry::new_barcode_value(
376 96,
377 BarcodeValue::FNC3,
378 BarcodeValue::FNC3,
379 BarcodeValue::Digit(96),
380 'Ä',
381 ),
382 TableEntry::new_barcode_value(
383 97,
384 BarcodeValue::FNC2,
385 BarcodeValue::FNC2,
386 BarcodeValue::Digit(97),
387 'Å',
388 ),
389 TableEntry::new_barcode_value(
390 98,
391 BarcodeValue::ShiftB,
392 BarcodeValue::ShiftA,
393 BarcodeValue::Digit(98),
394 'Æ',
395 ),
396 TableEntry::new_barcode_value(
397 99,
398 BarcodeValue::CodeC,
399 BarcodeValue::CodeC,
400 BarcodeValue::Digit(99),
401 'Ç',
402 ),
403 TableEntry::new_barcode_value(
404 100,
405 BarcodeValue::CodeB,
406 BarcodeValue::FNC4,
407 BarcodeValue::CodeB,
408 'È',
409 ),
410 TableEntry::new_barcode_value(
411 101,
412 BarcodeValue::FNC4,
413 BarcodeValue::CodeA,
414 BarcodeValue::CodeA,
415 'É',
416 ),
417 TableEntry::new_barcode_value(
418 102,
419 BarcodeValue::FNC1,
420 BarcodeValue::FNC1,
421 BarcodeValue::FNC1,
422 'Ê',
423 ),
424 TableEntry::new_barcode_value(
425 103,
426 BarcodeValue::StartA,
427 BarcodeValue::StartA,
428 BarcodeValue::StartA,
429 'Ë',
430 ),
431 TableEntry::new_barcode_value(
432 104,
433 BarcodeValue::StartB,
434 BarcodeValue::StartB,
435 BarcodeValue::StartB,
436 'Ì',
437 ),
438 TableEntry::new_barcode_value(
439 105,
440 BarcodeValue::StartC,
441 BarcodeValue::StartC,
442 BarcodeValue::StartC,
443 'Í',
444 ),
445 TableEntry::new_barcode_value(
446 108,
447 BarcodeValue::Stop,
448 BarcodeValue::Stop,
449 BarcodeValue::Stop,
450 'Î',
451 ),
452 ],
453 }
454 }
455
456 pub const fn new_from(entries: [TableEntry; 107]) -> Self {
461 Table { entries }
462 }
463
464 pub fn modify(&self, mut f: impl FnMut(&mut TableEntry)) -> Self {
468 let mut new_entries = self.entries;
469 for entry in &mut new_entries {
470 f(entry);
471 }
472 Table::new_from(new_entries)
473 }
474
475 pub fn entry_in_set(
480 &self,
481 value: impl Into<BarcodeValue>,
482 set: BarcodeType,
483 ) -> Option<&TableEntry> {
484 let value = value.into();
485 self.entries.iter().find(|entry| match set {
486 BarcodeType::CodeA => entry.a == value,
487 BarcodeType::CodeB => entry.b == value,
488 BarcodeType::CodeC => entry.c == value,
489 })
490 }
491}
492
493impl Default for Table {
494 fn default() -> Self {
495 Self::new()
496 }
497}
498
499#[derive(Debug, PartialEq, Eq)]
501pub struct Barcode<'table> {
502 code: Vec<&'table TableEntry>,
503}
504
505impl PartialOrd for Barcode<'_> {
506 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
507 Some(self.cmp(other))
508 }
509}
510
511impl Ord for Barcode<'_> {
512 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
513 self.code.len().cmp(&other.code.len())
514 }
515}
516
517impl Display for Barcode<'_> {
518 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
519 let mut output = String::new();
520 for entry in &self.code {
521 output.push(entry.latin());
522 }
523 write!(f, "{output}")
524 }
525}
526
527impl<'table> IntoIterator for Barcode<'table> {
528 type Item = &'table TableEntry;
529
530 type IntoIter = std::vec::IntoIter<Self::Item>;
531
532 fn into_iter(self) -> Self::IntoIter {
533 self.code.into_iter()
534 }
535}
536
537pub const TABLE: Table = Table::new();
539
540pub fn make_barcode(text: &str) -> Option<Barcode<'_>> {
542 make_barcode_prefer_set(text, BarcodeType::CodeB)
543}
544
545pub fn make_barcode_prefer_set(text: &str, prefer: BarcodeType) -> Option<Barcode<'_>> {
547 make_barcode_custom_table(&TABLE, text, prefer)
548}
549
550pub fn make_barcode_custom_table<'table>(
553 table: &'table Table,
554 mut text: &str,
555 prefer: BarcodeType,
556) -> Option<Barcode<'table>> {
557 let mut map = HashMap::new();
558 for c in BarcodeBuilder::new(table, text) {
559 map.insert(c.key(), c);
560 }
561
562 while !text.is_empty() {
563 let next_char = text.chars().next().unwrap().len_utf8();
564 for ty in [BarcodeType::CodeA, BarcodeType::CodeB, BarcodeType::CodeC] {
565 for fnc_state in [false, true] {
566 if let Some(builder) = map.get(&BarcodeKey::new(text, ty).with_fnc(fnc_state)) {
567 let options = builder.create_child_options();
568 for current in options {
569 let key = current.key();
570 if let Some(previous) = map.get(&key) {
571 let prev_cost = previous.cost();
572 let curr_cost = current.cost();
573 if prev_cost > curr_cost || key.set == prefer && prev_cost == curr_cost
574 {
575 map.insert(key, current);
576 }
577 } else {
578 map.insert(key, current);
579 }
580 }
581 }
582 }
583 }
584 text = &text[next_char..];
585 }
586
587 map.into_iter()
588 .filter_map(|(k, v)| if k.is_empty() { Some(v.build()) } else { None })
589 .min_by_key(|v| v.code.len())
590}
591
592#[derive(Debug, Clone)]
593struct BarcodeBuilder<'table, 's> {
594 table: &'table Table,
595 code: Vec<&'table TableEntry>,
596 key: BarcodeKey<'s>,
597}
598
599impl<'table, 's> BarcodeBuilder<'table, 's> {
600 fn new(table: &'table Table, code: &'s str) -> [BarcodeBuilder<'table, 's>; 3] {
601 [
602 Self {
603 code: vec![
604 table
605 .entry_in_set(BarcodeValue::StartA, BarcodeType::CodeA)
606 .unwrap(),
607 ],
608 table,
609 key: BarcodeKey::new(code, BarcodeType::CodeA),
610 },
611 Self {
612 code: vec![
613 table
614 .entry_in_set(BarcodeValue::StartB, BarcodeType::CodeB)
615 .unwrap(),
616 ],
617 table,
618 key: BarcodeKey::new(code, BarcodeType::CodeB),
619 },
620 Self {
621 code: vec![
622 table
623 .entry_in_set(BarcodeValue::StartC, BarcodeType::CodeC)
624 .unwrap(),
625 ],
626 table,
627 key: BarcodeKey::new(code, BarcodeType::CodeC),
628 },
629 ]
630 }
631
632 fn cost(&self) -> usize {
633 self.code.len()
634 }
635
636 fn create_child_options(&self) -> Vec<Self> {
637 let mut options = Vec::new();
638 let old_set = self.key.set;
639
640 if self.key.remaining.len() >= 2 {
642 let first_two_characters = self.key.remaining.chars().take(2).collect::<String>();
643 if first_two_characters.chars().all(|c| c.is_ascii_digit()) {
644 if let Ok(v) = first_two_characters.parse::<u8>() {
645 if let Some(s) = self.try_push(|mut s| {
646 if !matches!(old_set, BarcodeType::CodeC) {
647 s.code.push(s.in_set(BarcodeValue::CodeC)?);
648 s.key.set = BarcodeType::CodeC;
649 }
650 s.code.push(s.in_set(v)?);
651
652 s.key.remaining = &s.key.remaining[first_two_characters.len()..];
653 Some(s)
654 }) {
655 options.push(s)
656 };
657 }
658 }
659 }
660
661 if let Some(fc) = self.key.remaining.chars().next() {
663 if let Some(s) = self.try_push(|mut s| {
665 s.code.push(s.in_set(fc)?);
666 s.key.remaining = &s.key.remaining[fc.len_utf8()..];
667 Some(s)
668 }) {
669 options.push(s);
670 }
671
672 if let Some(s) = self.try_push(|mut s| {
674 s.code.push(s.in_set(BarcodeValue::FNC4)?);
675 s.key.fnc4 = !s.key.fnc4;
676 s.code.push(s.in_set(fc)?);
677 s.key.fnc4 = !s.key.fnc4;
678 s.key.remaining = &s.key.remaining[fc.len_utf8()..];
679 Some(s)
680 }) {
681 options.push(s);
682 }
683 if let Some(s) = self.try_push(|mut s| {
684 s.code.push(s.in_set(BarcodeValue::FNC4)?);
685 s.code.push(s.in_set(BarcodeValue::FNC4)?);
686 s.key.fnc4 = !s.key.fnc4;
687 s.code.push(s.in_set(fc)?);
688 s.key.remaining = &s.key.remaining[fc.len_utf8()..];
689 Some(s)
690 }) {
691 options.push(s);
692 }
693
694 if let Some(new_set) = old_set.other_set() {
696 let shift_to = match new_set {
697 BarcodeType::CodeA => BarcodeValue::ShiftA,
698 BarcodeType::CodeB => BarcodeValue::ShiftB,
699 BarcodeType::CodeC => unreachable!(),
700 };
701 if let Some(s) = self.try_push(|mut s| {
702 s.code.push(s.in_set(shift_to)?);
703 s.key.set = new_set;
704 s.code.push(s.in_set(fc)?);
705 s.key.set = old_set;
706 s.key.remaining = &s.key.remaining[fc.len_utf8()..];
707 Some(s)
708 }) {
709 options.push(s);
710 }
711
712 let force_to = match new_set {
713 BarcodeType::CodeA => BarcodeValue::CodeA,
714 BarcodeType::CodeB => BarcodeValue::CodeB,
715 BarcodeType::CodeC => unreachable!(),
716 };
717
718 if let Some(s) = self.try_push(|mut s| {
719 s.code.push(s.in_set(force_to)?);
720 s.key.set = new_set;
721 s.code.push(s.in_set(fc)?);
722 s.key.remaining = &s.key.remaining[fc.len_utf8()..];
723 Some(s)
724 }) {
725 options.push(s);
726 }
727 }
728 }
729
730 options
731 }
732
733 fn try_push(&self, to_try: impl FnOnce(Self) -> Option<Self>) -> Option<Self> {
734 to_try(self.clone())
735 }
736
737 fn in_set(&self, v: impl Into<BarcodeValue>) -> Option<&'table TableEntry> {
738 let v = v.into();
739 if self.key.fnc4 {
740 if let BarcodeValue::RegularCharacter(c) = v {
741 let c = (c as u32).checked_sub(128)?;
742 let c = char::from_u32(c)?;
743 return self.table.entry_in_set(c, self.key.set);
744 }
745 }
746 self.table.entry_in_set(v, self.key.set)
747 }
748
749 fn build(mut self) -> Barcode<'table> {
750 let mut total = 0;
751 for (mut idx, character) in self.code.iter().enumerate() {
752 if idx == 0 {
753 idx = 1;
754 }
755 total += character.value() as usize * idx
756 }
757 total %= 103;
758 self.code.push(
759 self.table
760 .entries
761 .iter()
762 .find(|v| v.value() as usize == total)
763 .unwrap(),
764 );
765 self.code.push(
766 self.table
767 .entry_in_set(BarcodeValue::Stop, self.key.set)
768 .unwrap(),
769 );
770 Barcode { code: self.code }
771 }
772
773 fn key(&self) -> BarcodeKey<'s> {
774 self.key
775 }
776}
777
778#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
780pub struct BarcodeKey<'s> {
781 remaining: &'s str,
782 set: BarcodeType,
783 fnc4: bool,
784}
785
786impl<'s> BarcodeKey<'s> {
787 pub fn new(text: &'s str, set: BarcodeType) -> Self {
789 Self {
790 remaining: text,
791 set,
792 fnc4: false,
793 }
794 }
795
796 pub fn with_fnc(mut self, fnc4: bool) -> Self {
798 self.fnc4 = fnc4;
799 self
800 }
801
802 pub fn is_empty(&self) -> bool {
804 self.remaining.is_empty()
805 }
806}