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