rxing/datamatrix/decoder/
decoded_bit_stream_parser.rs

1/*
2 * Copyright 2008 ZXing authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::{
18    common::{BitSource, CharacterSet, DecoderRXingResult, ECIStringBuilder, Eci, Result},
19    Exceptions,
20};
21
22/**
23 * <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes
24 * in one Data Matrix Code. This class decodes the bits back into text.</p>
25 *
26 * <p>See ISO 16022:2006, 5.2.1 - 5.2.9.2</p>
27 *
28 * @author bbrown@google.com (Brian Brown)
29 * @author Sean Owen
30 */
31
32#[derive(Debug, PartialEq, Eq, Clone, Copy)]
33enum Mode {
34    PAD_ENCODE, // Not really a mode
35    ASCII_ENCODE,
36    C40_ENCODE,
37    TEXT_ENCODE,
38    ANSIX12_ENCODE,
39    EDIFACT_ENCODE,
40    BASE256_ENCODE,
41    ECI_ENCODE,
42}
43
44/**
45 * See ISO 16022:2006, Annex C Table C.1
46 * The C40 Basic Character Set (*'s used for placeholders for the shift values)
47 */
48const C40_BASIC_SET_CHARS: [char; 40] = [
49    '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
50    'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
51    'Y', 'Z',
52];
53
54const C40_SHIFT2_SET_CHARS: [char; 27] = [
55    '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=',
56    '>', '?', '@', '[', '\\', ']', '^', '_',
57];
58
59/**
60 * See ISO 16022:2006, Annex C Table C.2
61 * The Text Basic Character Set (*'s used for placeholders for the shift values)
62 */
63const TEXT_BASIC_SET_CHARS: [char; 40] = [
64    '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
65    'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
66    'y', 'z',
67];
68
69// Shift 2 for Text is the same encoding as C40
70const TEXT_SHIFT2_SET_CHARS: [char; 27] = C40_SHIFT2_SET_CHARS;
71
72const TEXT_SHIFT3_SET_CHARS: [char; 32] = [
73    '`',
74    'A',
75    'B',
76    'C',
77    'D',
78    'E',
79    'F',
80    'G',
81    'H',
82    'I',
83    'J',
84    'K',
85    'L',
86    'M',
87    'N',
88    'O',
89    'P',
90    'Q',
91    'R',
92    'S',
93    'T',
94    'U',
95    'V',
96    'W',
97    'X',
98    'Y',
99    'Z',
100    '{',
101    '|',
102    '}',
103    '~',
104    127 as char,
105];
106
107const INSERT_STRING_CONST: &str = "\u{001E}\u{0004}";
108const VALUE_236: &str = "[)>\u{001E}05\u{001D}";
109const VALUE_237: &str = "[)>\u{001E}06\u{001D}";
110
111pub fn decode(bytes: &[u8], is_flipped: bool) -> Result<DecoderRXingResult> {
112    let mut bits = BitSource::new(bytes);
113    let mut result = ECIStringBuilder::with_capacity(100);
114    let mut resultTrailer = String::new();
115    let mut byteSegments = Vec::new();
116    let mut mode = Mode::ASCII_ENCODE;
117    // Could look directly at 'bytes', if we're sure of not having to account for multi byte values
118    let mut fnc1Positions = Vec::new();
119    let symbologyModifier;
120    let mut isECIencoded = false;
121    let mut known_eci = true;
122    let mut is_gs1 = false;
123    loop {
124        match mode {
125            Mode::ASCII_ENCODE => {
126                mode = decodeAsciiSegment(
127                    &mut bits,
128                    &mut result,
129                    &mut resultTrailer,
130                    &mut fnc1Positions,
131                    &mut is_gs1,
132                )?
133            }
134            Mode::C40_ENCODE => {
135                decodeC40Segment(&mut bits, &mut result, &mut fnc1Positions)?;
136                mode = Mode::ASCII_ENCODE;
137            }
138            Mode::TEXT_ENCODE => {
139                decodeTextSegment(&mut bits, &mut result, &mut fnc1Positions)?;
140                mode = Mode::ASCII_ENCODE;
141            }
142            Mode::ANSIX12_ENCODE => {
143                decodeAnsiX12Segment(&mut bits, &mut result)?;
144                mode = Mode::ASCII_ENCODE;
145            }
146            Mode::EDIFACT_ENCODE => {
147                decodeEdifactSegment(&mut bits, &mut result)?;
148                mode = Mode::ASCII_ENCODE;
149            }
150            Mode::BASE256_ENCODE => {
151                decodeBase256Segment(&mut bits, &mut result, &mut byteSegments)?;
152                mode = Mode::ASCII_ENCODE;
153            }
154            Mode::ECI_ENCODE => {
155                known_eci &= decodeECISegment(&mut bits, &mut result)?;
156                isECIencoded = true; // ECI detection only, atm continue decoding as ASCII
157                mode = Mode::ASCII_ENCODE;
158            }
159            _ => return Err(Exceptions::FORMAT),
160        }
161
162        if !(mode != Mode::PAD_ENCODE && bits.available() > 0) {
163            break;
164        }
165    } //while (mode != Mode.PAD_ENCODE && bits.available() > 0);
166    if !resultTrailer.is_empty() {
167        result.appendCharacters(&resultTrailer);
168    }
169    if isECIencoded && known_eci {
170        // Examples for this numbers can be found in this documentation of a hardware barcode scanner:
171        // https://honeywellaidc.force.com/supportppr/s/article/List-of-barcode-symbology-AIM-Identifiers
172        if fnc1Positions.contains(&0) || fnc1Positions.contains(&4) {
173            symbologyModifier = 5;
174        } else if fnc1Positions.contains(&1) || fnc1Positions.contains(&5) {
175            symbologyModifier = 6;
176        } else {
177            symbologyModifier = 4;
178        }
179    } else if fnc1Positions.contains(&0) || fnc1Positions.contains(&4) {
180        symbologyModifier = 2;
181    } else if fnc1Positions.contains(&1) || fnc1Positions.contains(&5) {
182        symbologyModifier = 3;
183    } else {
184        symbologyModifier = 1;
185    }
186
187    let mut result = DecoderRXingResult::with_symbology(
188        bytes.to_vec(),
189        result.build_result().to_string(),
190        byteSegments,
191        String::new(),
192        symbologyModifier,
193    );
194    if is_gs1 {
195        result.setContentType(String::from("GS1"));
196    }
197
198    if !known_eci {
199        result.setContentType(String::from("UnknownECI"));
200    }
201
202    if is_flipped {
203        result.setIsMirrored(is_flipped);
204    }
205
206    Ok(result)
207}
208
209/**
210 * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
211 */
212fn decodeAsciiSegment(
213    bits: &mut BitSource,
214    result: &mut ECIStringBuilder,
215    resultTrailer: &mut String,
216    fnc1positions: &mut Vec<usize>,
217    is_gs1: &mut bool,
218) -> Result<Mode> {
219    let mut upperShift = false;
220    let mut firstFNC1Position = 1;
221    let mut firstCodeword = true;
222    let mut sai = StructuredAppendInfo::default();
223    loop {
224        let mut oneByte = bits.readBits(8)?;
225        match oneByte {
226            0 => return Err(Exceptions::FORMAT),
227            1..=128 => {
228                // ASCII data (ASCII value + 1)
229                if upperShift {
230                    oneByte += 128;
231                    //upperShift = false;
232                }
233                result.append_char(char::from_u32(oneByte - 1).ok_or(Exceptions::PARSE)?);
234                return Ok(Mode::ASCII_ENCODE);
235            }
236            129 => return Ok(Mode::PAD_ENCODE), // Pad
237            130..=229 => {
238                // 2-digit data 00-99 (Numeric Value + 130)
239                let value = oneByte - 130;
240                if value < 10 {
241                    // pad with '0' for single digit values
242                    result.append_char('0');
243                }
244                result.append_string(&format!("{value}"));
245            }
246            230 =>
247            // Latch to C40 encodation
248            {
249                return Ok(Mode::C40_ENCODE)
250            }
251            231 =>
252            // Latch to Base 256 encodation
253            {
254                return Ok(Mode::BASE256_ENCODE)
255            }
256            232 => {
257                // FNC1
258                if bits.getByteOffset() == firstFNC1Position {
259                    /*result.symbology.modifier = '2';*/
260                    *is_gs1 = true;
261                }
262                // GS1
263                else if bits.getByteOffset() == firstFNC1Position + 1 {
264                    /*result.symbology.modifier = '3';*/
265                }
266                // AIM, note no AIM Application Indicator format defined, ISO 16022:2006 11.2
267                else {
268                    result.append_char(29 as char);
269                } // translate as ASCII 29
270
271                fnc1positions.push(result.len());
272            }
273            233 =>
274            // Structured Append
275            {
276                if !firstCodeword
277                // Must be first ISO 16022:2006 5.6.1
278                {
279                    return Err(Exceptions::format_with(
280                        "structured append tag must be first code word",
281                    ));
282                }
283                parse_structured_append(bits, &mut sai)?;
284                firstFNC1Position = 5;
285            }
286            234 =>
287                // Reader Programming
288            // Ignore these symbols for now
289            //throw ReaderException.getInstance();
290                {}
291            235 =>
292            // Upper Shift (shift to Extended ASCII)
293            {
294                upperShift = true
295            }
296            236 => {
297                // 05 Macro
298                result.append_string(VALUE_236);
299                resultTrailer.replace_range(0..0, INSERT_STRING_CONST);
300                // resultTrailer.insert(0, "\u{001E}\u{0004}");
301            }
302            237 => {
303                // 06 Macro
304                result.append_string(VALUE_237);
305                resultTrailer.replace_range(0..0, INSERT_STRING_CONST);
306                // resultTrailer.insert(0, "\u{001E}\u{0004}");
307            }
308            238 =>
309            // Latch to ANSI X12 encodation
310            {
311                return Ok(Mode::ANSIX12_ENCODE)
312            }
313            239 =>
314            // Latch to Text encodation
315            {
316                return Ok(Mode::TEXT_ENCODE)
317            }
318            240 =>
319            // Latch to EDIFACT encodation
320            {
321                return Ok(Mode::EDIFACT_ENCODE)
322            }
323            241 =>
324            // ECI Character
325            {
326                return Ok(Mode::ECI_ENCODE)
327            }
328            _ => {
329                // Not to be used in ASCII encodation
330                // but work around encoders that end with 254, latch back to ASCII
331                if oneByte != 254 || bits.available() != 0 {
332                    return Err(Exceptions::FORMAT);
333                }
334            }
335        }
336
337        if bits.available() == 0 {
338            break;
339        }
340        firstCodeword = false;
341    } //while (bits.available() > 0);
342    Ok(Mode::ASCII_ENCODE)
343}
344
345/**
346 * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
347 */
348fn decodeC40Segment(
349    bits: &mut BitSource,
350    result: &mut ECIStringBuilder,
351    fnc1positions: &mut Vec<usize>,
352) -> Result<()> {
353    // Three C40 values are encoded in a 16-bit value as
354    // (1600 * C1) + (40 * C2) + C3 + 1
355    // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
356    let mut upperShift = false;
357
358    let mut cValues = [0; 3];
359    let mut shift = 0;
360
361    loop {
362        // If there is only one byte left then it will be encoded as ASCII
363        if bits.available() == 8 {
364            return Ok(());
365        }
366        let firstByte = bits.readBits(8)?;
367        if firstByte == 254 {
368            // Unlatch codeword
369            return Ok(());
370        }
371
372        parseTwoBytes(firstByte, bits.readBits(8)?, &mut cValues);
373
374        for cValue in cValues {
375            // for i in 0..3 {
376            // for (int i = 0; i < 3; i++) {
377            // let cValue = cValues[i];
378            match shift {
379                0 => {
380                    if cValue < 3 {
381                        shift = cValue + 1;
382                    } else if cValue < C40_BASIC_SET_CHARS.len() as u32 {
383                        let c40char = C40_BASIC_SET_CHARS[cValue as usize];
384                        if upperShift {
385                            result.append_char(
386                                char::from_u32(c40char as u32 + 128).ok_or(Exceptions::PARSE)?,
387                            );
388                            upperShift = false;
389                        } else {
390                            result.append_char(c40char);
391                        }
392                    } else {
393                        return Err(Exceptions::FORMAT);
394                    }
395                }
396                1 => {
397                    if upperShift {
398                        result.append_char(char::from_u32(cValue + 128).ok_or(Exceptions::PARSE)?);
399                        upperShift = false;
400                    } else {
401                        result.append_char(char::from_u32(cValue).ok_or(Exceptions::PARSE)?);
402                    }
403                    shift = 0;
404                }
405                2 => {
406                    if cValue < C40_SHIFT2_SET_CHARS.len() as u32 {
407                        let c40char = C40_SHIFT2_SET_CHARS[cValue as usize];
408                        if upperShift {
409                            result.append_char(
410                                char::from_u32(c40char as u32 + 128).ok_or(Exceptions::PARSE)?,
411                            );
412                            upperShift = false;
413                        } else {
414                            result.append_char(c40char);
415                        }
416                    } else {
417                        match cValue {
418                            27 => {
419                                // FNC1
420                                fnc1positions.push(result.len());
421                                result.append_char(29 as char); // translate as ASCII 29
422                            }
423                            30 =>
424                            // Upper Shift
425                            {
426                                upperShift = true
427                            }
428
429                            _ => return Err(Exceptions::FORMAT),
430                        }
431                    }
432                    shift = 0;
433                }
434                3 => {
435                    if upperShift {
436                        result.append_char(char::from_u32(cValue + 224).ok_or(Exceptions::PARSE)?);
437                        upperShift = false;
438                    } else {
439                        result.append_char(char::from_u32(cValue + 96).ok_or(Exceptions::PARSE)?);
440                    }
441                    shift = 0;
442                }
443
444                _ => return Err(Exceptions::FORMAT),
445            }
446        }
447        if bits.available() == 0 {
448            break;
449        }
450    } //while (bits.available() > 0);
451    Ok(())
452}
453
454/**
455 * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
456 */
457fn decodeTextSegment(
458    bits: &mut BitSource,
459    result: &mut ECIStringBuilder,
460    fnc1positions: &mut Vec<usize>,
461) -> Result<()> {
462    // Three Text values are encoded in a 16-bit value as
463    // (1600 * C1) + (40 * C2) + C3 + 1
464    // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
465    let mut upperShift = false;
466
467    let mut cValues = [0; 3]; //new int[3];
468    let mut shift = 0;
469    loop {
470        // If there is only one byte left then it will be encoded as ASCII
471        if bits.available() == 8 {
472            return Ok(());
473        }
474        let firstByte = bits.readBits(8)?;
475        if firstByte == 254 {
476            // Unlatch codeword
477            return Ok(());
478        }
479
480        parseTwoBytes(firstByte, bits.readBits(8)?, &mut cValues);
481
482        for cValue in cValues {
483            // for (int i = 0; i < 3; i++) {
484            // int cValue = cValues[i];
485            match shift {
486                0 => {
487                    if cValue < 3 {
488                        shift = cValue + 1;
489                    } else if cValue < TEXT_BASIC_SET_CHARS.len() as u32 {
490                        let textChar = TEXT_BASIC_SET_CHARS[cValue as usize];
491                        if upperShift {
492                            result.append_char(
493                                char::from_u32(textChar as u32 + 128).ok_or(Exceptions::PARSE)?,
494                            );
495                            upperShift = false;
496                        } else {
497                            result.append_char(textChar);
498                        }
499                    } else {
500                        return Err(Exceptions::FORMAT);
501                    }
502                }
503                1 => {
504                    if upperShift {
505                        result.append_char(char::from_u32(cValue + 128).ok_or(Exceptions::PARSE)?);
506                        upperShift = false;
507                    } else {
508                        result.append_char(char::from_u32(cValue).ok_or(Exceptions::PARSE)?);
509                    }
510                    shift = 0;
511                }
512
513                2 => {
514                    // Shift 2 for Text is the same encoding as C40
515                    if cValue < TEXT_SHIFT2_SET_CHARS.len() as u32 {
516                        let textChar = TEXT_SHIFT2_SET_CHARS[cValue as usize];
517                        if upperShift {
518                            result.append_char(
519                                char::from_u32(textChar as u32 + 128).ok_or(Exceptions::PARSE)?,
520                            );
521                            upperShift = false;
522                        } else {
523                            result.append_char(textChar);
524                        }
525                    } else {
526                        match cValue {
527                            27 => {
528                                // FNC1
529                                fnc1positions.push(result.len());
530                                result.append_char(29 as char); // translate as ASCII 29
531                            }
532                            30 =>
533                            // Upper Shift
534                            {
535                                upperShift = true
536                            }
537
538                            _ => return Err(Exceptions::FORMAT),
539                        }
540                    }
541                    shift = 0;
542                }
543                3 => {
544                    if cValue < TEXT_SHIFT3_SET_CHARS.len() as u32 {
545                        let textChar = TEXT_SHIFT3_SET_CHARS[cValue as usize];
546                        if upperShift {
547                            result.append_char(
548                                char::from_u32(textChar as u32 + 128).ok_or(Exceptions::PARSE)?,
549                            );
550                            upperShift = false;
551                        } else {
552                            result.append_char(textChar);
553                        }
554                        shift = 0;
555                    } else {
556                        return Err(Exceptions::FORMAT);
557                    }
558                }
559
560                _ => return Err(Exceptions::FORMAT),
561            }
562        }
563        if bits.available() == 0 {
564            break;
565        }
566    } //while (bits.available() > 0);
567
568    Ok(())
569}
570
571/**
572 * See ISO 16022:2006, 5.2.7
573 */
574fn decodeAnsiX12Segment(bits: &mut BitSource, result: &mut ECIStringBuilder) -> Result<()> {
575    // Three ANSI X12 values are encoded in a 16-bit value as
576    // (1600 * C1) + (40 * C2) + C3 + 1
577
578    let mut cValues = [0; 3]; //new int[3];
579    loop {
580        // If there is only one byte left then it will be encoded as ASCII
581        if bits.available() == 8 {
582            return Ok(());
583        }
584        let firstByte = bits.readBits(8)?;
585        if firstByte == 254 {
586            // Unlatch codeword
587            return Ok(());
588        }
589
590        parseTwoBytes(firstByte, bits.readBits(8)?, &mut cValues);
591
592        for cValue in cValues {
593            // for (int i = 0; i < 3; i++) {
594            //   int cValue = cValues[i];
595            match cValue {
596                0 =>
597                // X12 segment terminator <CR>
598                {
599                    result.append_char('\r')
600                }
601
602                1 =>
603                // X12 segment separator *
604                {
605                    result.append_char('*')
606                }
607
608                2 =>
609                // X12 sub-element separator >
610                {
611                    result.append_char('>')
612                }
613
614                3 =>
615                // space
616                {
617                    result.append_char(' ')
618                }
619
620                _ => {
621                    if cValue < 14 {
622                        // 0 - 9
623                        result.append_char(char::from_u32(cValue + 44).ok_or(Exceptions::PARSE)?);
624                    } else if cValue < 40 {
625                        // A - Z
626                        result.append_char(char::from_u32(cValue + 51).ok_or(Exceptions::PARSE)?);
627                    } else {
628                        return Err(Exceptions::FORMAT);
629                    }
630                }
631            }
632        }
633        if bits.available() == 0 {
634            break;
635        }
636    } //while (bits.available() > 0);
637
638    Ok(())
639}
640
641fn parseTwoBytes(firstByte: u32, secondByte: u32, result: &mut [u32]) {
642    let mut fullBitValue = (firstByte << 8) + secondByte - 1;
643    let mut temp = fullBitValue / 1600;
644    result[0] = temp;
645    fullBitValue -= temp * 1600;
646    temp = fullBitValue / 40;
647    result[1] = temp;
648    result[2] = fullBitValue - temp * 40;
649}
650
651/**
652 * See ISO 16022:2006, 5.2.8 and Annex C Table C.3
653 */
654fn decodeEdifactSegment(bits: &mut BitSource, result: &mut ECIStringBuilder) -> Result<()> {
655    loop {
656        // If there is only two or less bytes left then it will be encoded as ASCII
657        if bits.available() <= 16 {
658            return Ok(());
659        }
660
661        for _i in 0..4 {
662            // for (int i = 0; i < 4; i++) {
663            let mut edifactValue = bits.readBits(6)?;
664
665            // Check for the unlatch character
666            if edifactValue == 0x1F {
667                // 011111
668                // Read rest of byte, which should be 0, and stop
669                let bitsLeft = 8 - bits.getBitOffset();
670                if bitsLeft != 8 {
671                    bits.readBits(bitsLeft)?;
672                }
673                return Ok(());
674            }
675
676            if (edifactValue & 0x20) == 0 {
677                // no 1 in the leading (6th) bit
678                edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value
679            }
680            result.append_char(char::from_u32(edifactValue).ok_or(Exceptions::PARSE)?);
681        }
682
683        if bits.available() == 0 {
684            break;
685        }
686    }
687
688    Ok(())
689}
690
691/**
692 * See ISO 16022:2006, 5.2.9 and Annex B, B.2
693 */
694fn decodeBase256Segment(
695    bits: &mut BitSource,
696    result: &mut ECIStringBuilder,
697    byteSegments: &mut Vec<Vec<u8>>,
698) -> Result<()> {
699    // Figure out how long the Base 256 Segment is.
700    let mut codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed
701    let d1 = unrandomize255State(bits.readBits(8)?, codewordPosition);
702    codewordPosition += 1;
703    let count;
704    if d1 == 0 {
705        // Read the remainder of the symbol
706        count = bits.available() as u32 / 8;
707    } else if d1 < 250 {
708        count = d1;
709    } else {
710        count = 250 * (d1 - 249) + unrandomize255State(bits.readBits(8)?, codewordPosition);
711        codewordPosition += 1;
712    }
713
714    // We're seeing NegativeArraySizeException errors from users.
715    // but we shouldn't in rust because it's unsigned
716    // if count < 0 {
717    //     return Err(Exceptions::formatEmpty());
718    // }
719
720    let mut bytes = vec![0u8; count as usize];
721    for byte in bytes.iter_mut().take(count as usize) {
722        // Have seen this particular error in the wild, such as at
723        // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
724        if bits.available() < 8 {
725            return Err(Exceptions::FORMAT);
726        }
727        *byte = unrandomize255State(bits.readBits(8)?, codewordPosition) as u8;
728        codewordPosition += 1;
729    }
730    result.append_string(&CharacterSet::ISO8859_1.decode(&bytes)?);
731    byteSegments.push(bytes);
732
733    Ok(())
734}
735
736/**
737 * See ISO 16022:2007, 5.4.1
738 */
739fn decodeECISegment(bits: &mut BitSource, result: &mut ECIStringBuilder) -> Result<bool> {
740    let firstByte = bits.readBits(8)?;
741    if firstByte <= 127 {
742        result.append_eci(Eci::from(firstByte - 1));
743        return Ok(true);
744    }
745
746    let secondByte = bits.readBits(8)?;
747    if firstByte <= 191 {
748        result.append_eci(Eci::from((firstByte - 128) * 254 + 127 + secondByte - 1));
749        return Ok((firstByte - 128) * 254 + 127 + secondByte - 1 > 900);
750    }
751
752    let thirdByte = bits.readBits(8)?;
753
754    result.append_eci(Eci::from(
755        (firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1,
756    ));
757    Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900)
758}
759
760/**
761* See ISO 16022:2006, 5.6
762*/
763fn parse_structured_append(bits: &mut BitSource, sai: &mut StructuredAppendInfo) -> Result<()> {
764    // 5.6.2 Table 8
765    let symbolSequenceIndicator = bits.readBits(8)?;
766    sai.index = (symbolSequenceIndicator >> 4) as i32;
767    sai.count = (17 - (symbolSequenceIndicator & 0x0F)) as i32; // 2-16 permitted, 17 invalid
768
769    if sai.count == 17 || sai.count <= sai.index
770    // If info doesn't make sense
771    {
772        sai.count = 0; // Choose to mark count as unknown
773    }
774
775    let fileId1 = bits.readBits(8)?; // File identification 1
776    let fileId2 = bits.readBits(8)?; // File identification 2
777
778    // There's no conversion method or meaning given to the 2 file id codewords in Section 5.6.3, apart from
779    // saying that each value should be 1-254. Choosing here to represent them as base 256.
780    sai.id = ((fileId1 << 8) | fileId2).to_string();
781    Ok(())
782}
783struct StructuredAppendInfo {
784    index: i32, //= -1;
785    count: i32, // = -1;
786    id: String,
787}
788
789impl Default for StructuredAppendInfo {
790    fn default() -> Self {
791        Self {
792            index: -1,
793            count: -1,
794            id: Default::default(),
795        }
796    }
797}
798
799/**
800 * See ISO 16022:2006, Annex B, B.2
801 */
802fn unrandomize255State(randomizedBase256Codeword: u32, base256CodewordPosition: usize) -> u32 {
803    let pseudoRandomNumber = ((149 * base256CodewordPosition as u32) % 255) + 1;
804    let tempVariable = randomizedBase256Codeword as i32 - pseudoRandomNumber as i32;
805
806    if tempVariable >= 0 {
807        tempVariable as u32
808    } else {
809        (tempVariable + 256) as u32
810    }
811}
812
813#[cfg(test)]
814mod tests {
815    use crate::datamatrix::decoder::decoded_bit_stream_parser;
816
817    #[test]
818    fn testAsciiStandardDecode() {
819        // ASCII characters 0-127 are encoded as the value + 1
820        let bytes = [
821            (b'a' + 1),
822            (b'b' + 1),
823            (b'c' + 1),
824            (b'A' + 1),
825            (b'B' + 1),
826            (b'C' + 1),
827        ];
828        let decodedString = String::from(
829            decoded_bit_stream_parser::decode(&bytes, false)
830                .expect("decode")
831                .getText(),
832        );
833        assert_eq!("abcABC", decodedString);
834    }
835
836    #[test]
837    fn testAsciiDoubleDigitDecode() {
838        // ASCII double digit (00 - 99) Numeric Value + 130
839        let bytes = [130, (1 + 130), (98 + 130), (99 + 130)];
840        let decodedString = String::from(
841            decoded_bit_stream_parser::decode(&bytes, false)
842                .expect("decode")
843                .getText(),
844        );
845        assert_eq!("00019899", decodedString);
846    }
847
848    // TODO(bbrown): Add test cases for each encoding type
849    // TODO(bbrown): Add test cases for switching encoding types
850}