rxing/datamatrix/encoder/
minimal_encoder.rs

1/*
2 * Copyright 2021 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 std::{fmt, sync::Arc};
18
19use crate::{
20    common::{CharacterSet, ECIInput, Eci, MinimalECIInput, Result},
21    Exceptions,
22};
23
24use super::{high_level_encoder, SymbolShapeHint};
25
26const ISO_8859_1_ENCODER: CharacterSet = CharacterSet::ISO8859_1;
27
28/**
29 * Encoder that encodes minimally
30 *
31 * Algorithm:
32 *
33 * Uses Dijkstra to produce mathematically minimal encodings that are in some cases smaller than the results produced
34 * by the algorithm described in annex S in the specification ISO/IEC 16022:200(E). The biggest improvment of this
35 * algorithm over that one is the case when the algorithm enters the most inefficient mode, the B256 Mode:: The
36 * algorithm from the specification algorithm will exit this mode only if it encounters digits so that arbitrarily
37 * inefficient results can be produced if the postfix contains no digits.
38 *
39 * Multi ECI support and ECI switching:
40 *
41 * For multi language content the algorithm selects the most compact representation using ECI modes. Note that unlike
42 * the compaction algorithm used for QR-Codes, this implementation operates in two stages and therfore is not
43 * mathematically optimal. In the first stage, the input string is encoded minimally as a stream of ECI character set
44 * selectors and bytes encoded in the selected encoding. In this stage the algorithm might for example decide to
45 * encode ocurrences of the characters "\u0150\u015C" (O-double-acute, S-circumflex) in UTF-8 by a single ECI or
46 * alternatively by multiple ECIs that switch between IS0-8859-2 and ISO-8859-3 (e.g. in the case that the input
47 * contains many * characters from ISO-8859-2 (Latin 2) and few from ISO-8859-3 (Latin 3)).
48 * In a second stage this stream of ECIs and bytes is minimally encoded using the various Data Matrix encoding modes.
49 * While both stages encode mathematically minimally it is not ensured that the result is mathematically minimal since
50 * the size growth for inserting an ECI in the first stage can only be approximated as the first stage does not know
51 * in which mode the ECI will occur in the second stage (may, or may not require an extra latch to ASCII depending on
52 * the current mode). The reason for this shortcoming are difficulties in implementing it in a straightforward and
53 * readable manner.
54 *
55 * GS1 support
56 *
57 * FNC1 delimiters can be encoded in the input string by using the FNC1 character specified in the encoding function.
58 * When a FNC1 character is specified then a leading FNC1 will be encoded and all ocurrences of delimiter characters
59 * while result in FNC1 codewords in the symbol.
60 *
61 * @author Alex Geller
62 */
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq)]
65enum Mode {
66    Ascii,
67    C40,
68    Text,
69    X12,
70    Edf,
71    B256,
72}
73
74impl Mode {
75    pub fn ordinal(&self) -> usize {
76        match self {
77            Mode::Ascii => 0,
78            Mode::C40 => 1,
79            Mode::Text => 2,
80            Mode::X12 => 3,
81            Mode::Edf => 4,
82            Mode::B256 => 5,
83        }
84    }
85}
86
87const C40_SHIFT2_CHARS: [char; 27] = [
88    '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=',
89    '>', '?', '@', '[', '\\', ']', '^', '_',
90];
91
92pub fn isExtendedASCII(ch: char, fnc1: Option<char>) -> bool {
93    let is_fnc1 = if let Some(fnc1) = fnc1 {
94        ch != fnc1
95    } else {
96        true
97    };
98    is_fnc1 && ch as u8 >= 128 //&& ch as u8 <= 255
99                               // return ch != fnc1 && ch as u8 >= 128 && ch as u8 <= 255;
100}
101
102#[inline]
103fn isInC40Shift1Set(ch: char) -> bool {
104    ch as u8 <= 31
105}
106
107fn isInC40Shift2Set(ch: char, fnc1: Option<char>) -> bool {
108    for c40Shift2Char in C40_SHIFT2_CHARS {
109        // for (char c40Shift2Char : C40_SHIFT2_CHARS) {
110        if c40Shift2Char == ch {
111            return true;
112        }
113    }
114    if let Some(fnc1) = fnc1 {
115        ch == fnc1
116    } else {
117        false
118    }
119    // return ch as u8 as i32 == fnc1;
120}
121
122fn isInTextShift1Set(ch: char) -> bool {
123    isInC40Shift1Set(ch)
124}
125
126fn isInTextShift2Set(ch: char, fnc1: Option<char>) -> bool {
127    isInC40Shift2Set(ch, fnc1)
128}
129
130/**
131 * Performs message encoding of a DataMatrix message
132 *
133 * @param msg the message
134 * @return the encoded message (the char values range from 0 to 255)
135 */
136pub fn encodeHighLevel(msg: &str) -> Result<String> {
137    encodeHighLevelWithDetails(msg, None, None, SymbolShapeHint::FORCE_NONE)
138}
139
140/**
141 * Performs message encoding of a DataMatrix message
142 *
143 * @param msg the message
144 * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm
145 *   chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority
146 *   charset to encode any character in the input that can be encoded by it if the charset is among the
147 *   supported charsets.
148 * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not a GS1
149 *   bar code. If the value is not -1 then a FNC1 is also prepended.
150 * @param shape requested shape.
151 * @return the encoded message (the char values range from 0 to 255)
152 */
153pub fn encodeHighLevelWithDetails(
154    msg: &str,
155    priorityCharset: Option<CharacterSet>,
156    fnc1: Option<char>,
157    shape: SymbolShapeHint,
158) -> Result<String> {
159    let mut msg = msg;
160    let mut macroId = 0;
161    if msg.starts_with(high_level_encoder::MACRO_05_HEADER)
162        && msg.ends_with(high_level_encoder::MACRO_TRAILER)
163    {
164        macroId = 5;
165        // msg = msg.substring(high_level_encoder::MACRO_05_HEADER.len(), msg.len() - 2);
166        msg = &msg[high_level_encoder::MACRO_05_HEADER.chars().count()..(msg.chars().count() - 2)];
167    } else if msg.starts_with(high_level_encoder::MACRO_06_HEADER)
168        && msg.ends_with(high_level_encoder::MACRO_TRAILER)
169    {
170        macroId = 6;
171        // msg = msg.substring(high_level_encoder::MACRO_06_HEADER.len(), msg.len() - 2);
172        msg = &msg[high_level_encoder::MACRO_06_HEADER.chars().count()..(msg.chars().count() - 2)];
173    }
174    Ok(ISO_8859_1_ENCODER
175        .decode(&encode(msg, priorityCharset, fnc1, shape, macroId)?)
176        .expect("should decode"))
177    // return new String(encode(msg, priorityCharset, fnc1, shape, macroId), StandardCharsets.ISO_8859_1);
178}
179
180/**
181 * Encodes input minimally and returns an array of the codewords
182 *
183 * @param input The string to encode
184 * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm
185 *   chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority
186 *   charset to encode any character in the input that can be encoded by it if the charset is among the
187 *   supported charsets.
188 * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not a GS1
189 *   bar code. If the value is not -1 then a FNC1 is also prepended.
190 * @param shape requested shape.
191 * @param macroId Prepends the specified macro function in case that a value of 5 or 6 is specified.
192 * @return An array of bytes representing the codewords of a minimal encoding.
193 */
194fn encode(
195    input: &str,
196    priorityCharset: Option<CharacterSet>,
197    fnc1: Option<char>,
198    shape: SymbolShapeHint,
199    macroId: i32,
200) -> Result<Vec<u8>> {
201    Ok(encodeMinimally(Arc::new(Input::new(
202        input,
203        priorityCharset,
204        fnc1,
205        shape,
206        macroId,
207    )))?
208    .getBytes()
209    .to_vec())
210}
211
212fn addEdge(edges: &mut [Vec<Option<Arc<Edge>>>], edge: Arc<Edge>) -> Result<()> {
213    let vertexIndex = (edge.fromPosition + edge.characterLength) as usize;
214    if edges[vertexIndex][edge.getEndMode()?.ordinal()].is_none()
215        || edges[vertexIndex][edge.getEndMode()?.ordinal()]
216            .as_ref()
217            .ok_or(Exceptions::ILLEGAL_STATE)?
218            .cachedTotalSize
219            > edge.cachedTotalSize
220    {
221        edges[vertexIndex][edge.getEndMode()?.ordinal()] = Some(edge.clone());
222    }
223    Ok(())
224}
225
226/** @return the number of words in which the string starting at from can be encoded in c40 or text Mode::
227 *  The number of characters encoded is returned in characterLength.
228 *  The number of characters encoded is also minimal in the sense that the algorithm stops as soon
229 *  as a character encoding fills a C40 word competely (three C40 values). An exception is at the
230 *  end of the string where two C40 values are allowed (according to the spec the third c40 value
231 *  is filled  with 0 (Shift 1) in this case).
232 */
233fn getNumberOfC40Words(
234    input: Arc<Input>,
235    from: u32,
236    c40: bool,
237    characterLength: &mut [u32],
238) -> Result<u32> {
239    let mut thirdsCount = 0;
240    for i in (from as usize)..input.length() {
241        // for (int i = from; i < input.length(); i++) {
242        if input.isECI(i as u32)? {
243            characterLength[0] = 0;
244            return Ok(0);
245        }
246        let ci = input.charAt(i)?;
247        if c40 && high_level_encoder::isNativeC40(ci)
248            || !c40 && high_level_encoder::isNativeText(ci)
249        {
250            thirdsCount += 1; //native
251        } else if !isExtendedASCII(ci, input.getFNC1Character()) {
252            thirdsCount += 2; //shift
253        } else {
254            let asciiValue = ci as u8;
255            if asciiValue >= 128
256                && (c40 && high_level_encoder::isNativeC40((asciiValue - 128) as char)
257                    || !c40 && high_level_encoder::isNativeText((asciiValue - 128) as char))
258            {
259                thirdsCount += 3; // shift, Upper shift
260            } else {
261                thirdsCount += 4; // shift, Upper shift, shift
262            }
263        }
264
265        if thirdsCount % 3 == 0 || ((thirdsCount - 2) % 3 == 0 && i + 1 == input.length()) {
266            characterLength[0] = i as u32 - from + 1;
267            // return (int) Math.ceil(((double) thirdsCount) / 3.0);
268            return Ok(((thirdsCount as f64) / 3.0).ceil() as u32);
269        }
270    }
271    characterLength[0] = 0;
272
273    Ok(0)
274}
275
276fn addEdges(
277    input: Arc<Input>,
278    edges: &mut [Vec<Option<Arc<Edge>>>],
279    from: u32,
280    previous: Option<Arc<Edge>>,
281) -> Result<()> {
282    if input.isECI(from)? {
283        addEdge(
284            edges,
285            Arc::new(Edge::new(input, Mode::Ascii, from, 1, previous)?),
286        )?;
287        return Ok(());
288    }
289
290    let ch = input.charAt(from as usize)?;
291    if previous.is_none() || previous.as_ref().unwrap().getEndMode()? != Mode::Edf {
292        //not possible to unlatch a full EDF edge to something
293        //else
294        if high_level_encoder::isDigit(ch)
295            && input.haveNCharacters(from as usize, 2)?
296            && high_level_encoder::isDigit(input.charAt(from as usize + 1)?)
297        {
298            // two digits ASCII encoded
299            addEdge(
300                edges,
301                Arc::new(Edge::new(
302                    input.clone(),
303                    Mode::Ascii,
304                    from,
305                    2,
306                    previous.clone(),
307                )?),
308            )?;
309        } else {
310            // one ASCII encoded character or an extended character via Upper Shift
311            addEdge(
312                edges,
313                Arc::new(Edge::new(
314                    input.clone(),
315                    Mode::Ascii,
316                    from,
317                    1,
318                    previous.clone(),
319                )?),
320            )?;
321        }
322
323        let modes = [Mode::C40, Mode::Text];
324        for mode in modes {
325            // for (Mode mode : modes) {
326            let mut characterLength = [0u32; 1];
327            if getNumberOfC40Words(input.clone(), from, mode == Mode::C40, &mut characterLength)?
328                > 0
329            {
330                addEdge(
331                    edges,
332                    Arc::new(Edge::new(
333                        input.clone(),
334                        mode,
335                        from,
336                        characterLength[0],
337                        previous.clone(),
338                    )?),
339                )?;
340            }
341        }
342
343        if input.haveNCharacters(from as usize, 3)?
344            && high_level_encoder::isNativeX12(input.charAt(from as usize)?)
345            && high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?)
346            && high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?)
347        {
348            addEdge(
349                edges,
350                Arc::new(Edge::new(
351                    input.clone(),
352                    Mode::X12,
353                    from,
354                    3,
355                    previous.clone(),
356                )?),
357            )?;
358        }
359
360        addEdge(
361            edges,
362            Arc::new(Edge::new(
363                input.clone(),
364                Mode::B256,
365                from,
366                1,
367                previous.clone(),
368            )?),
369        )?;
370    }
371
372    //We create 4 EDF edges,  with 1, 2 3 or 4 characters length. The fourth normally doesn't have a latch to ASCII
373    //unless it is 2 characters away from the end of the input.
374    let mut i: u32 = 0;
375    while i < 3 {
376        // for (i = 0; i < 3; i++) {
377        let pos = from + i;
378        if input.haveNCharacters(pos as usize, 1)?
379            && high_level_encoder::isNativeEDIFACT(input.charAt(pos as usize)?)
380        {
381            addEdge(
382                edges,
383                Arc::new(Edge::new(
384                    input.clone(),
385                    Mode::Edf,
386                    from,
387                    i + 1,
388                    previous.clone(),
389                )?),
390            )?;
391        } else {
392            break;
393        }
394        i += 1;
395    }
396    if i == 3
397        && input.haveNCharacters(from as usize, 4)?
398        && high_level_encoder::isNativeEDIFACT(input.charAt(from as usize + 3)?)
399    {
400        addEdge(
401            edges,
402            Arc::new(Edge::new(input, Mode::Edf, from, 4, previous)?),
403        )?;
404    }
405    Ok(())
406}
407
408fn encodeMinimally(input: Arc<Input>) -> Result<RXingResult> {
409    // @SuppressWarnings("checkstyle:lineLength")
410    /* The minimal encoding is computed by Dijkstra. The acyclic graph is modeled as follows:
411     * A vertex represents a combination of a position in the input and an encoding mode where position 0
412     * denotes the position left of the first character, 1 the position left of the second character and so on.
413     * Likewise the end vertices are located after the last character at position input.length().
414     * For any position there might be up to six vertices, one for each of the encoding types ASCII, C40, TEXT, X12,
415     * EDF and B256.
416     *
417     * As an example consider the input string "ABC123" then at position 0 there is only one vertex with the default
418     * ASCII encodation. At position 3 there might be vertices for the types ASCII, C40, X12, EDF and B256.
419     *
420     * An edge leading to such a vertex encodes one or more of the characters left of the position that the vertex
421     * represents. It encodes the characters in the encoding mode of the vertex that it ends on. In other words,
422     * all edges leading to a particular vertex encode the same characters (the length of the suffix can vary) using the same
423     * encoding Mode::
424     * As an example consider the input string "ABC123" and the vertex (4,EDF). Possible edges leading to this vertex
425     * are:
426     *   (0,ASCII)  --EDF(ABC1)--> (4,EDF)
427     *   (1,ASCII)  --EDF(BC1)-->  (4,EDF)
428     *   (1,B256)   --EDF(BC1)-->  (4,EDF)
429     *   (1,EDF)    --EDF(BC1)-->  (4,EDF)
430     *   (2,ASCII)  --EDF(C1)-->   (4,EDF)
431     *   (2,B256)   --EDF(C1)-->   (4,EDF)
432     *   (2,EDF)    --EDF(C1)-->   (4,EDF)
433     *   (3,ASCII)  --EDF(1)-->    (4,EDF)
434     *   (3,B256)   --EDF(1)-->    (4,EDF)
435     *   (3,EDF)    --EDF(1)-->    (4,EDF)
436     *   (3,C40)    --EDF(1)-->    (4,EDF)
437     *   (3,X12)    --EDF(1)-->    (4,EDF)
438     *
439     * The edges leading to a vertex are stored in such a way that there is a fast way to enumerate the edges ending
440     * on a particular vertex.
441     *
442     * The algorithm processes the vertices in order of their position thereby performing the following:
443     *
444     * For every vertex at position i the algorithm enumerates the edges ending on the vertex and removes all but the
445     * shortest from that list.
446     * Then it processes the vertices for the position i+1. If i+1 == input.length() then the algorithm ends
447     * and chooses the the edge with the smallest size from any of the edges leading to vertices at this position.
448     * Otherwise the algorithm computes all possible outgoing edges for the vertices at the position i+1
449     *
450     * Examples:
451     * The process is illustrated by showing the graph (edges) after each iteration from left to right over the input:
452     * An edge is drawn as follows "(" + fromVertex + ") -- " + encodingMode + "(" + encodedInput + ") (" +
453     * accumulatedSize + ") --> (" + toVertex + ")"
454     *
455     * Example 1 encoding the string "ABCDEFG":
456     *
457     *
458     * Situation after adding edges to the start vertex (0,ASCII)
459     * (0,ASCII) ASCII(A) (1) --> (1,ASCII)
460     * (0,ASCII) B256(A) (3) --> (1,B256)
461     * (0,ASCII) EDF(AB) (4) --> (2,EDF)
462     * (0,ASCII) C40(ABC) (3) --> (3,C40)
463     * (0,ASCII) TEXT(ABC) (5) --> (3,TEXT)
464     * (0,ASCII) X12(ABC) (3) --> (3,X12)
465     * (0,ASCII) EDF(ABC) (4) --> (3,EDF)
466     * (0,ASCII) EDF(ABCD) (4) --> (4,EDF)
467     *
468     * Situation after adding edges to vertices at position 1
469     * (0,ASCII) ASCII(A) (1) --> (1,ASCII)
470     * (0,ASCII) B256(A) (3) --> (1,B256)
471     * (0,ASCII) EDF(AB) (4) --> (2,EDF)
472     * (0,ASCII) C40(ABC) (3) --> (3,C40)
473     * (0,ASCII) TEXT(ABC) (5) --> (3,TEXT)
474     * (0,ASCII) X12(ABC) (3) --> (3,X12)
475     * (0,ASCII) EDF(ABC) (4) --> (3,EDF)
476     * (0,ASCII) EDF(ABCD) (4) --> (4,EDF)
477     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII)
478     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) B256(B) (4) --> (2,B256)
479     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BC) (5) --> (3,EDF)
480     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) C40(BCD) (4) --> (4,C40)
481     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) TEXT(BCD) (6) --> (4,TEXT)
482     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) X12(BCD) (4) --> (4,X12)
483     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BCD) (5) --> (4,EDF)
484     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BCDE) (5) --> (5,EDF)
485     * (0,ASCII) B256(A) (3) --> (1,B256) ASCII(B) (4) --> (2,ASCII)
486     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256)
487     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BC) (6) --> (3,EDF)
488     * (0,ASCII) B256(A) (3) --> (1,B256) C40(BCD) (5) --> (4,C40)
489     * (0,ASCII) B256(A) (3) --> (1,B256) TEXT(BCD) (7) --> (4,TEXT)
490     * (0,ASCII) B256(A) (3) --> (1,B256) X12(BCD) (5) --> (4,X12)
491     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BCD) (6) --> (4,EDF)
492     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BCDE) (6) --> (5,EDF)
493     *
494     * Edge "(1,ASCII) ASCII(B) (2) --> (2,ASCII)" is minimal for the vertex (2,ASCII) so that edge "(1,B256) ASCII(B) (4) --> (2,ASCII)" is removed.
495     * Edge "(1,B256) B256(B) (3) --> (2,B256)" is minimal for the vertext (2,B256) so that the edge "(1,ASCII) B256(B) (4) --> (2,B256)" is removed.
496     *
497     * Situation after adding edges to vertices at position 2
498     * (0,ASCII) ASCII(A) (1) --> (1,ASCII)
499     * (0,ASCII) B256(A) (3) --> (1,B256)
500     * (0,ASCII) EDF(AB) (4) --> (2,EDF)
501     * (0,ASCII) C40(ABC) (3) --> (3,C40)
502     * (0,ASCII) TEXT(ABC) (5) --> (3,TEXT)
503     * (0,ASCII) X12(ABC) (3) --> (3,X12)
504     * (0,ASCII) EDF(ABC) (4) --> (3,EDF)
505     * (0,ASCII) EDF(ABCD) (4) --> (4,EDF)
506     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII)
507     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BC) (5) --> (3,EDF)
508     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) C40(BCD) (4) --> (4,C40)
509     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) TEXT(BCD) (6) --> (4,TEXT)
510     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) X12(BCD) (4) --> (4,X12)
511     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BCD) (5) --> (4,EDF)
512     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BCDE) (5) --> (5,EDF)
513     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256)
514     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BC) (6) --> (3,EDF)
515     * (0,ASCII) B256(A) (3) --> (1,B256) C40(BCD) (5) --> (4,C40)
516     * (0,ASCII) B256(A) (3) --> (1,B256) TEXT(BCD) (7) --> (4,TEXT)
517     * (0,ASCII) B256(A) (3) --> (1,B256) X12(BCD) (5) --> (4,X12)
518     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BCD) (6) --> (4,EDF)
519     * (0,ASCII) B256(A) (3) --> (1,B256) EDF(BCDE) (6) --> (5,EDF)
520     * (0,ASCII) EDF(AB) (4) --> (2,EDF) ASCII(C) (5) --> (3,ASCII)
521     * (0,ASCII) EDF(AB) (4) --> (2,EDF) B256(C) (6) --> (3,B256)
522     * (0,ASCII) EDF(AB) (4) --> (2,EDF) EDF(CD) (7) --> (4,EDF)
523     * (0,ASCII) EDF(AB) (4) --> (2,EDF) C40(CDE) (6) --> (5,C40)
524     * (0,ASCII) EDF(AB) (4) --> (2,EDF) TEXT(CDE) (8) --> (5,TEXT)
525     * (0,ASCII) EDF(AB) (4) --> (2,EDF) X12(CDE) (6) --> (5,X12)
526     * (0,ASCII) EDF(AB) (4) --> (2,EDF) EDF(CDE) (7) --> (5,EDF)
527     * (0,ASCII) EDF(AB) (4) --> (2,EDF) EDF(CDEF) (7) --> (6,EDF)
528     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII)
529     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) B256(C) (5) --> (3,B256)
530     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) EDF(CD) (6) --> (4,EDF)
531     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) C40(CDE) (5) --> (5,C40)
532     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) TEXT(CDE) (7) --> (5,TEXT)
533     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) X12(CDE) (5) --> (5,X12)
534     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) EDF(CDE) (6) --> (5,EDF)
535     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) EDF(CDEF) (6) --> (6,EDF)
536     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) ASCII(C) (4) --> (3,ASCII)
537     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256)
538     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) EDF(CD) (6) --> (4,EDF)
539     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) C40(CDE) (5) --> (5,C40)
540     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) TEXT(CDE) (7) --> (5,TEXT)
541     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) X12(CDE) (5) --> (5,X12)
542     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) EDF(CDE) (6) --> (5,EDF)
543     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) EDF(CDEF) (6) --> (6,EDF)
544     *
545     * Edge "(2,ASCII) ASCII(C) (3) --> (3,ASCII)" is minimal for the vertex (3,ASCII) so that edges "(2,EDF) ASCII(C) (5) --> (3,ASCII)"
546     * and "(2,B256) ASCII(C) (4) --> (3,ASCII)" can be removed.
547     * Edge "(0,ASCII) EDF(ABC) (4) --> (3,EDF)" is minimal for the vertex (3,EDF) so that edges "(1,ASCII) EDF(BC) (5) --> (3,EDF)"
548     * and "(1,B256) EDF(BC) (6) --> (3,EDF)" can be removed.
549     * Edge "(2,B256) B256(C) (4) --> (3,B256)" is minimal for the vertex (3,B256) so that edges "(2,ASCII) B256(C) (5) --> (3,B256)"
550     * and "(2,EDF) B256(C) (6) --> (3,B256)" can be removed.
551     *
552     * This continues for vertices 3 thru 7
553     *
554     * Situation after adding edges to vertices at position 7
555     * (0,ASCII) ASCII(A) (1) --> (1,ASCII)
556     * (0,ASCII) B256(A) (3) --> (1,B256)
557     * (0,ASCII) EDF(AB) (4) --> (2,EDF)
558     * (0,ASCII) C40(ABC) (3) --> (3,C40)
559     * (0,ASCII) TEXT(ABC) (5) --> (3,TEXT)
560     * (0,ASCII) X12(ABC) (3) --> (3,X12)
561     * (0,ASCII) EDF(ABC) (4) --> (3,EDF)
562     * (0,ASCII) EDF(ABCD) (4) --> (4,EDF)
563     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII)
564     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) C40(BCD) (4) --> (4,C40)
565     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) TEXT(BCD) (6) --> (4,TEXT)
566     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) X12(BCD) (4) --> (4,X12)
567     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) EDF(BCDE) (5) --> (5,EDF)
568     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256)
569     * (0,ASCII) C40(ABC) (3) --> (3,C40) C40(DEF) (5) --> (6,C40)
570     * (0,ASCII) X12(ABC) (3) --> (3,X12) X12(DEF) (5) --> (6,X12)
571     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII)
572     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) C40(CDE) (5) --> (5,C40)
573     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) TEXT(CDE) (7) --> (5,TEXT)
574     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) X12(CDE) (5) --> (5,X12)
575     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) EDF(CDEF) (6) --> (6,EDF)
576     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) C40(BCD) (4) --> (4,C40) C40(EFG) (6) --> (7,C40)    //Solution 1
577     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) X12(BCD) (4) --> (4,X12) X12(EFG) (6) --> (7,X12)    //Solution 2
578     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256)
579     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) ASCII(D) (4) --> (4,ASCII)
580     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) TEXT(DEF) (8) --> (6,TEXT)
581     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) EDF(DEFG) (7) --> (7,EDF)
582     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256) B256(D) (5) --> (4,B256)
583     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) ASCII(D) (4) --> (4,ASCII) ASCII(E) (5) --> (5,ASCII)
584     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) ASCII(D) (4) --> (4,ASCII) TEXT(EFG) (9) --> (7,TEXT)
585     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256) B256(D) (5) --> (4,B256) B256(E) (6) --> (5,B256)
586     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) ASCII(D) (4) --> (4,ASCII) ASCII(E) (5) --> (5,ASCII) ASCII(F) (6) --> (6,ASCII)
587     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256) B256(D) (5) --> (4,B256) B256(E) (6) --> (5,B256) B256(F) (7) --> (6,B256)
588     * (0,ASCII) ASCII(A) (1) --> (1,ASCII) ASCII(B) (2) --> (2,ASCII) ASCII(C) (3) --> (3,ASCII) ASCII(D) (4) --> (4,ASCII) ASCII(E) (5) --> (5,ASCII) ASCII(F) (6) --> (6,ASCII) ASCII(G) (7) --> (7,ASCII)
589     * (0,ASCII) B256(A) (3) --> (1,B256) B256(B) (3) --> (2,B256) B256(C) (4) --> (3,B256) B256(D) (5) --> (4,B256) B256(E) (6) --> (5,B256) B256(F) (7) --> (6,B256) B256(G) (8) --> (7,B256)
590     *
591     * Hence a minimal encoding of "ABCDEFG" is either ASCII(A),C40(BCDEFG) or ASCII(A), X12(BCDEFG) with a size of 5 bytes.
592     */
593
594    let inputLength = input.length();
595
596    // Array that represents vertices. There is a vertex for every character and Mode::
597    // The last dimension in the array below encodes the 6 modes ASCII, C40, TEXT, X12, EDF and B256
598    // let edges = new Edge[inputLength + 1][6];
599    let mut edges = vec![vec![None; 6]; inputLength + 1];
600    addEdges(input.clone(), &mut edges, 0, None)?;
601
602    for i in 1..=inputLength {
603        for j in 0..6 {
604            if edges[i][j].is_some() && i < inputLength {
605                let edge = edges[i][j].clone();
606                addEdges(input.clone(), &mut edges, i as u32, edge)?;
607            }
608        }
609        //optimize memory by removing edges that have been passed.
610        edges[i - 1][..6].fill(None);
611    }
612
613    let mut minimalJ: i32 = -1;
614    let mut minimalSize = i32::MAX;
615    for j in 0..6 {
616        if let Some(edge) = &edges[inputLength][j] {
617            // if edges[inputLength][j].is_some() {
618            // let edge = edges[inputLength][j].as_ref().unwrap();
619            let size = if (1..=3).contains(&j) {
620                edge.cachedTotalSize + 1
621            } else {
622                edge.cachedTotalSize
623            }; //C40, TEXT and X12 need an
624               // extra unlatch at the end
625            if (size as i32) < minimalSize {
626                minimalSize = size as i32;
627                minimalJ = j as i32;
628            }
629        }
630    }
631
632    if minimalJ < 0 {
633        return Err(Exceptions::illegal_state_with(format!(
634            "Internal error: failed to encode \"{input}\""
635        )));
636    }
637    RXingResult::new(edges[inputLength][minimalJ as usize].clone())
638}
639
640const ALL_CODEWORD_CAPACITIES: [u32; 28] = [
641    3, 5, 8, 10, 12, 16, 18, 22, 30, 32, 36, 44, 49, 62, 86, 114, 144, 174, 204, 280, 368, 456,
642    576, 696, 816, 1050, 1304, 1558,
643];
644const SQUARE_CODEWORD_CAPACITIES: [u32; 24] = [
645    3, 5, 8, 12, 18, 22, 30, 36, 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816,
646    1050, 1304, 1558,
647];
648const RECTANGULAR_CODEWORD_CAPACITIES: [u32; 6] = [5, 10, 16, 33, 32, 49];
649
650struct Edge {
651    input: Arc<Input>,
652    mode: Mode, //the mode at the start of this edge.
653    fromPosition: u32,
654    characterLength: u32,
655    previous: Option<Arc<Edge>>,
656    cachedTotalSize: u32,
657}
658impl Edge {
659    fn new(
660        input: Arc<Input>,
661        mode: Mode,
662        fromPosition: u32,
663        characterLength: u32,
664        previous: Option<Arc<Edge>>,
665    ) -> Result<Self> {
666        if fromPosition + characterLength > input.length() as u32 {
667            return Err(Exceptions::FORMAT);
668        }
669
670        let mut size = if let Some(previous) = previous.clone() {
671            previous.cachedTotalSize
672        } else {
673            0
674        };
675
676        let previousMode = Self::getPreviousMode(previous.clone())?;
677
678        /*
679         * Switching modes
680         * ASCII -> C40: latch 230
681         * ASCII -> TEXT: latch 239
682         * ASCII -> X12: latch 238
683         * ASCII -> EDF: latch 240
684         * ASCII -> B256: latch 231
685         * C40 -> ASCII: word(c1,c2,c3), 254
686         * TEXT -> ASCII: word(c1,c2,c3), 254
687         * X12 -> ASCII: word(c1,c2,c3), 254
688         * EDIFACT -> ASCII: Unlatch character,0,0,0 or c1,Unlatch character,0,0 or c1,c2,Unlatch character,0 or
689         * c1,c2,c3,Unlatch character
690         * B256 -> ASCII: without latch after n bytes
691         */
692        match mode {
693            Mode::Ascii => {
694                size += 1;
695                if input.isECI(fromPosition)?
696                    || isExtendedASCII(
697                        input.charAt(fromPosition as usize)?,
698                        input.getFNC1Character(),
699                    )
700                {
701                    size += 1;
702                }
703                if previousMode == Mode::C40
704                    || previousMode == Mode::Text
705                    || previousMode == Mode::X12
706                {
707                    size += 1; // unlatch 254 to ASCII
708                }
709            }
710            Mode::B256 => {
711                size += 1;
712                if previousMode != Mode::B256 || Self::getB256Size(mode, previous.clone()) == 250 {
713                    size += 1; //byte count
714                }
715                // } else if Self::getB256Size(mode, previous.clone()) == 250 {
716                //     size += 1; //extra byte count
717                // }
718                if previousMode == Mode::Ascii {
719                    size += 1; //latch to B256
720                } else if previousMode == Mode::C40
721                    || previousMode == Mode::Text
722                    || previousMode == Mode::X12
723                {
724                    size += 2; //unlatch to ASCII, latch to B256
725                }
726            }
727            Mode::C40 | Mode::Text | Mode::X12 => {
728                if mode == Mode::X12 {
729                    size += 2;
730                } else {
731                    let mut charLen = [0u32; 1];
732                    size += getNumberOfC40Words(
733                        input.clone(),
734                        fromPosition,
735                        mode == Mode::C40,
736                        &mut charLen,
737                    )? * 2;
738                }
739
740                if previousMode == Mode::Ascii || previousMode == Mode::B256 {
741                    size += 1; //additional byte for latch from ASCII to this mode
742                } else if previousMode != mode
743                    && (previousMode == Mode::C40
744                        || previousMode == Mode::Text
745                        || previousMode == Mode::X12)
746                {
747                    size += 2; //unlatch 254 to ASCII followed by latch to this mode
748                }
749            }
750            Mode::Edf => {
751                size += 3;
752                if previousMode == Mode::Ascii || previousMode == Mode::B256 {
753                    size += 1; //additional byte for latch from ASCII to this mode
754                } else if previousMode == Mode::C40
755                    || previousMode == Mode::Text
756                    || previousMode == Mode::X12
757                {
758                    size += 2; //unlatch 254 to ASCII followed by latch to this mode
759                }
760            }
761        }
762        Ok(Self {
763            input,
764            mode,
765            fromPosition,
766            characterLength,
767            previous,
768            cachedTotalSize: size,
769        })
770        // cachedTotalSize = size;
771    }
772
773    // does not count beyond 250
774    pub fn getB256Size(mode: Mode, previous: Option<Arc<Edge>>) -> u32 {
775        if mode != Mode::B256 {
776            return 0;
777        }
778        let mut cnt = 1;
779        let mut current = previous;
780        while current.is_some() && current.as_ref().unwrap().mode == Mode::B256 && cnt <= 250 {
781            cnt += 1;
782            current.clone_from(&current.clone().as_ref().unwrap().previous);
783        }
784        // let cnt = 0;
785        // Edge current = this;
786        // while (current != null && current.mode == Mode::B256 && cnt <= 250) {
787        //   cnt+=1;
788        //   current = current.previous;
789        // }
790        cnt
791    }
792
793    pub fn getPreviousStartMode(previous: Option<Arc<Edge>>) -> Mode {
794        if let Some(prev) = previous {
795            prev.mode
796        } else {
797            Mode::Ascii
798        }
799        // if previous.is_none() { Mode::ASCII} else {previous.as_ref().unwrap().mode}
800    }
801
802    pub fn getPreviousMode(previous: Option<Arc<Edge>>) -> Result<Mode> {
803        if let Some(prev) = previous {
804            prev.getEndMode()
805        } else {
806            Ok(Mode::Ascii)
807        }
808        // return  previous == null ? Mode::ASCII : previous.getEndMode();
809    }
810
811    /** Returns Mode::ASCII in case that:
812     *  - Mode is EDIFACT and characterLength is less than 4 or the remaining characters can be encoded in at most 2
813     *    ASCII bytes.
814     *  - Mode is C40, TEXT or X12 and the remaining characters can be encoded in at most 1 ASCII byte.
815     *
816     *  Returns mode in all other cases.
817     * */
818    pub fn getEndMode(&self) -> Result<Mode> {
819        let mode = self.mode;
820        if mode == Mode::Edf {
821            if self.characterLength < 4 {
822                return Ok(Mode::Ascii);
823            }
824            let lastASCII = Self::getLastASCII(self)?; // see 5.2.8.2 EDIFACT encodation Rules
825            if lastASCII > 0
826                && self.getCodewordsRemaining(self.cachedTotalSize + lastASCII) <= 2 - lastASCII
827            {
828                return Ok(Mode::Ascii);
829            }
830        }
831        if mode == Mode::C40 || mode == Mode::Text || mode == Mode::X12 {
832            // see 5.2.5.2 C40 encodation rules and 5.2.7.2 ANSI X12 encodation rules
833            if self.fromPosition + self.characterLength >= self.input.length() as u32
834                && self.getCodewordsRemaining(self.cachedTotalSize) == 0
835            {
836                return Ok(Mode::Ascii);
837            }
838            let lastASCII = Self::getLastASCII(self)?;
839            if lastASCII == 1 && self.getCodewordsRemaining(self.cachedTotalSize + 1) == 0 {
840                return Ok(Mode::Ascii);
841            }
842        }
843
844        Ok(mode)
845    }
846
847    pub fn getMode(&self) -> Mode {
848        self.mode
849    }
850
851    /** Peeks ahead and returns 1 if the postfix consists of exactly two digits, 2 if the postfix consists of exactly
852     *  two consecutive digits and a non extended character or of 4 digits.
853     *  Returns 0 in any other case
854     **/
855    pub fn getLastASCII(&self) -> Result<u32> {
856        let length = self.input.length() as u32;
857        let from = self.fromPosition + self.characterLength;
858        if length - from > 4 || from >= length {
859            return Ok(0);
860        }
861        if length - from == 1 {
862            if isExtendedASCII(
863                self.input.charAt(from as usize)?,
864                self.input.getFNC1Character(),
865            ) {
866                return Ok(0);
867            }
868            return Ok(1);
869        }
870        if length - from == 2 {
871            if isExtendedASCII(
872                self.input.charAt(from as usize)?,
873                self.input.getFNC1Character(),
874            ) || isExtendedASCII(
875                self.input.charAt(from as usize + 1)?,
876                self.input.getFNC1Character(),
877            ) {
878                return Ok(0);
879            }
880            if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
881                && high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
882            {
883                return Ok(1);
884            }
885            return Ok(2);
886        }
887        if length - from == 3 {
888            if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
889                && high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
890                && !isExtendedASCII(
891                    self.input.charAt(from as usize + 2)?,
892                    self.input.getFNC1Character(),
893                )
894            {
895                return Ok(2);
896            }
897            if high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
898                && high_level_encoder::isDigit(self.input.charAt(from as usize + 2)?)
899                && !isExtendedASCII(
900                    self.input.charAt(from as usize)?,
901                    self.input.getFNC1Character(),
902                )
903            {
904                return Ok(2);
905            }
906            return Ok(0);
907        }
908        if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
909            && high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
910            && high_level_encoder::isDigit(self.input.charAt(from as usize + 2)?)
911            && high_level_encoder::isDigit(self.input.charAt(from as usize + 3)?)
912        {
913            return Ok(2);
914        }
915
916        Ok(0)
917    }
918
919    /** Returns the capacity in codewords of the smallest symbol that has enough capacity to fit the given minimal
920     * number of codewords.
921     **/
922    pub fn getMinSymbolSize(&self, minimum: u32) -> u32 {
923        match self.input.getShapeHint() {
924            SymbolShapeHint::FORCE_SQUARE => {
925                for capacity in SQUARE_CODEWORD_CAPACITIES {
926                    // for (int capacity : squareCodewordCapacities) {
927                    if capacity >= minimum {
928                        return capacity;
929                    }
930                }
931            }
932            SymbolShapeHint::FORCE_RECTANGLE => {
933                for capacity in RECTANGULAR_CODEWORD_CAPACITIES {
934                    // for (int capacity : rectangularCodewordCapacities) {
935                    if capacity >= minimum {
936                        return capacity;
937                    }
938                }
939            }
940            _ => {}
941        }
942        for capacity in ALL_CODEWORD_CAPACITIES {
943            // for (int capacity : allCodewordCapacities) {
944            if capacity >= minimum {
945                return capacity;
946            }
947        }
948
949        ALL_CODEWORD_CAPACITIES[ALL_CODEWORD_CAPACITIES.len() - 1]
950    }
951
952    /** Returns the remaining capacity in codewords of the smallest symbol that has enough capacity to fit the given
953     * minimal number of codewords.
954     **/
955    pub fn getCodewordsRemaining(&self, minimum: u32) -> u32 {
956        Self::getMinSymbolSize(self, minimum) - minimum
957    }
958
959    #[inline]
960    pub fn getBytes1(c: u32) -> Vec<u8> {
961        // let result = vec![0u8;1];
962        // result[0] =  c as u8;
963        // result
964        vec![c as u8]
965    }
966
967    #[inline]
968    pub fn getBytes2(c1: u32, c2: u32) -> Vec<u8> {
969        // byte[] result = new byte[2];
970        // result[0] = (byte) c1;
971        // result[1] = (byte) c2;
972        // return result;
973        vec![c1 as u8, c2 as u8]
974    }
975
976    pub fn setC40Word(bytes: &mut [u8], offset: u32, c1: u32, c2: u32, c3: u32) {
977        let val16 = (1600 * (c1 & 0xff)) + (40 * (c2 & 0xff)) + (c3 & 0xff) + 1;
978        bytes[offset as usize] = (val16 / 256) as u8;
979        bytes[offset as usize + 1] = (val16 % 256) as u8;
980    }
981
982    fn getX12Value(c: char) -> u32 {
983        let c = c as u32;
984        if c == 13 {
985            0
986        } else if c == 42 {
987            1
988        } else if c == 62 {
989            2
990        } else if c == 32 {
991            3
992        } else if (48..=57).contains(&c) {
993            c - 44
994        } else if (65..=90).contains(&c) {
995            c - 51
996        } else {
997            c
998        }
999    }
1000
1001    pub fn getX12Words(&self) -> Result<Vec<u8>> {
1002        assert!(self.characterLength % 3 == 0);
1003        let mut result = vec![0u8; self.characterLength as usize / 3 * 2];
1004        let mut i = 0;
1005        while i < result.len() {
1006            // for (int i = 0; i < result.length; i += 2) {
1007            Self::setC40Word(
1008                &mut result,
1009                i as u32,
1010                Self::getX12Value(self.input.charAt(self.fromPosition as usize + i / 2 * 3)?),
1011                Self::getX12Value(
1012                    self.input
1013                        .charAt(self.fromPosition as usize + i / 2 * 3 + 1)?,
1014                ),
1015                Self::getX12Value(
1016                    self.input
1017                        .charAt(self.fromPosition as usize + i / 2 * 3 + 2)?,
1018                ),
1019            );
1020            i += 2;
1021        }
1022        Ok(result)
1023    }
1024
1025    pub fn getShiftValue(c: char, c40: bool, fnc1: Option<char>) -> u32 {
1026        if c40 && isInC40Shift1Set(c) || !c40 && isInTextShift1Set(c) {
1027            0
1028        } else if c40 && isInC40Shift2Set(c, fnc1) || !c40 && isInTextShift2Set(c, fnc1) {
1029            1
1030        } else {
1031            2
1032        }
1033    }
1034
1035    fn getC40Value(c40: bool, setIndex: u32, c: char, fnc1: Option<char>) -> u32 {
1036        if let Some(fnc1_char) = fnc1 {
1037            if c == fnc1_char {
1038                assert!(setIndex == 2);
1039                return 27;
1040            }
1041        }
1042        if c40 {
1043            let c = c as u32;
1044            if c <= 31 {
1045                c
1046            } else if c == 32 {
1047                3
1048            } else if c <= 47 {
1049                c - 33
1050            } else if c <= 57 {
1051                c - 44
1052            } else if c <= 64 {
1053                c - 43
1054            } else if c <= 90 {
1055                c - 51
1056            } else if c <= 95 {
1057                c - 69
1058            } else if c <= 127 {
1059                c - 96
1060            } else {
1061                c
1062            }
1063        } else {
1064            let c = c as u32;
1065            if c == 0 {
1066                0
1067            } else if setIndex == 0 && c <= 3 {
1068                c - 1
1069            } else if
1070            //is this a bug in the spec?
1071            setIndex == 1 && c <= 31 {
1072                c
1073            } else if c == 32 {
1074                3
1075            } else if (33..=47).contains(&c) {
1076                c - 33
1077            } else if (48..=57).contains(&c) {
1078                c - 44
1079            } else if (58..=64).contains(&c) {
1080                c - 43
1081            } else if (65..=90).contains(&c) {
1082                c - 64
1083            } else if (91..=95).contains(&c) {
1084                c - 69
1085            } else if c == 96 {
1086                0
1087            } else if (97..=122).contains(&c) {
1088                c - 83
1089            } else if (123..=127).contains(&c) {
1090                c - 96
1091            } else {
1092                c
1093            }
1094        }
1095    }
1096
1097    pub fn getC40Words(&self, c40: bool, fnc1: Option<char>) -> Result<Vec<u8>> {
1098        let mut c40Values: Vec<u8> = Vec::new();
1099        let fromPosition = self.fromPosition as usize;
1100        for i in 0..self.characterLength as usize {
1101            // for (int i = 0; i < characterLength; i++) {
1102            let ci = self.input.charAt(fromPosition + i)?;
1103            if c40 && high_level_encoder::isNativeC40(ci)
1104                || !c40 && high_level_encoder::isNativeText(ci)
1105            {
1106                c40Values.push(Self::getC40Value(c40, 0, ci, fnc1) as u8);
1107            } else if !isExtendedASCII(ci, fnc1) {
1108                let shiftValue = Self::getShiftValue(ci, c40, fnc1);
1109                c40Values.push(shiftValue as u8); //Shift[123]
1110                c40Values.push(Self::getC40Value(c40, shiftValue, ci, fnc1) as u8);
1111            } else {
1112                let asciiValue = (ci as u8 - 128) as char;
1113                if c40 && high_level_encoder::isNativeC40(asciiValue)
1114                    || !c40 && high_level_encoder::isNativeText(asciiValue)
1115                {
1116                    c40Values.push(1); //Shift 2
1117                    c40Values.push(30); //Upper Shift
1118                    c40Values.push(Self::getC40Value(c40, 0, asciiValue, fnc1) as u8);
1119                } else {
1120                    c40Values.push(1); //Shift 2
1121                    c40Values.push(30); //Upper Shift
1122                    let shiftValue = Self::getShiftValue(asciiValue, c40, fnc1);
1123                    c40Values.push(shiftValue as u8); // Shift[123]
1124                    c40Values.push(Self::getC40Value(c40, shiftValue, asciiValue, fnc1) as u8);
1125                }
1126            }
1127        }
1128
1129        if (c40Values.len() % 3) != 0 {
1130            assert!(
1131                (c40Values.len() - 2) % 3 == 0
1132                    && fromPosition + self.characterLength as usize == self.input.length()
1133            );
1134            c40Values.push(0); // pad with 0 (Shift 1)
1135        }
1136
1137        let mut result = vec![0u8; c40Values.len() / 3 * 2];
1138        let mut byteIndex = 0;
1139        let mut i = 0;
1140        while i < c40Values.len() {
1141            // for (int i = 0; i < c40Values.size(); i += 3) {
1142            Self::setC40Word(
1143                &mut result,
1144                byteIndex,
1145                c40Values[i] as u32,
1146                c40Values[i + 1] as u32,
1147                c40Values[i + 2] as u32,
1148            );
1149            byteIndex += 2;
1150
1151            i += 3;
1152        }
1153
1154        Ok(result)
1155    }
1156
1157    pub fn getEDFBytes(&self) -> Result<Vec<u8>> {
1158        let numberOfThirds = (self.characterLength as f32 / 4.0).ceil() as usize;
1159        let mut result = vec![0u8; numberOfThirds * 3];
1160        let mut pos = self.fromPosition as usize;
1161        let endPos = (self.fromPosition as usize + self.characterLength as usize - 1)
1162            .min(self.input.length() - 1);
1163        let mut i = 0;
1164        while i < numberOfThirds {
1165            // for (int i = 0; i < numberOfThirds; i += 3) {
1166            let mut edfValues = [0u32; 4];
1167            for edfValue in &mut edfValues {
1168                // for j in 0..4 {
1169                // for (int j = 0; j < 4; j++) {
1170                if pos <= endPos {
1171                    *edfValue = self.input.charAt(pos)? as u32 & 0x3f;
1172                    pos += 1;
1173                } else {
1174                    *edfValue = if pos == endPos + 1 { 0x1f } else { 0 };
1175                }
1176            }
1177            let mut val24 = edfValues[0] << 18;
1178            val24 |= edfValues[1] << 12;
1179            val24 |= edfValues[2] << 6;
1180            val24 |= edfValues[3];
1181            result[i] = ((val24 >> 16) & 0xff) as u8;
1182            result[i + 1] = ((val24 >> 8) & 0xff) as u8;
1183            result[i + 2] = (val24 & 0xff) as u8;
1184
1185            i += 3;
1186        }
1187
1188        Ok(result)
1189    }
1190
1191    pub fn getLatchBytes(&self) -> Result<Vec<u8>> {
1192        match Self::getPreviousMode(self.previous.clone())? {
1193            Mode::Ascii | Mode::B256 =>
1194            //after B256 ends (via length) we are back to ASCII
1195            {
1196                match self.mode {
1197                    Mode::B256 => return Ok(Self::getBytes1(231)),
1198                    Mode::C40 => return Ok(Self::getBytes1(230)),
1199                    Mode::Text => return Ok(Self::getBytes1(239)),
1200                    Mode::X12 => return Ok(Self::getBytes1(238)),
1201                    Mode::Edf => return Ok(Self::getBytes1(240)),
1202                    _ => {}
1203                }
1204            }
1205            Mode::C40 | Mode::Text | Mode::X12
1206                if self.mode != Self::getPreviousMode(self.previous.clone())? =>
1207            {
1208                match self.mode {
1209                    Mode::Ascii => return Ok(Self::getBytes1(254)),
1210                    Mode::B256 => return Ok(Self::getBytes2(254, 231)),
1211                    Mode::C40 => return Ok(Self::getBytes2(254, 230)),
1212                    Mode::Text => return Ok(Self::getBytes2(254, 239)),
1213                    Mode::X12 => return Ok(Self::getBytes2(254, 238)),
1214                    Mode::Edf => return Ok(Self::getBytes2(254, 240)),
1215                }
1216            }
1217            Mode::C40 | Mode::Text | Mode::X12 => {}
1218            Mode::Edf => assert!(self.mode == Mode::Edf), //The rightmost EDIFACT edge always contains an unlatch character
1219        }
1220
1221        Ok(Vec::new())
1222    }
1223
1224    // Important: The function does not return the length bytes (one or two) in case of B256 encoding
1225    pub fn getDataBytes(&self) -> Result<Vec<u8>> {
1226        match self.mode {
1227            Mode::Ascii => {
1228                if self.input.isECI(self.fromPosition)? {
1229                    Ok(Self::getBytes2(
1230                        241,
1231                        self.input.getECIValue(self.fromPosition as usize)? as u32 + 1,
1232                    ))
1233                } else if isExtendedASCII(
1234                    self.input.charAt(self.fromPosition as usize)?,
1235                    self.input.getFNC1Character(),
1236                ) {
1237                    Ok(Self::getBytes2(
1238                        235,
1239                        self.input.charAt(self.fromPosition as usize)? as u32 - 127,
1240                    ))
1241                } else if self.characterLength == 2 {
1242                    Ok(Self::getBytes1(
1243                        (self.input.charAt(self.fromPosition as usize)? as u32 - b'0' as u32) * 10
1244                            + self.input.charAt(self.fromPosition as usize + 1)? as u32
1245                            - b'0' as u32
1246                            + 130,
1247                    ))
1248                } else if self.input.isFNC1(self.fromPosition as usize)? {
1249                    Ok(Self::getBytes1(232))
1250                } else {
1251                    Ok(Self::getBytes1(
1252                        self.input.charAt(self.fromPosition as usize)? as u32 + 1,
1253                    ))
1254                }
1255            }
1256            Mode::B256 => Ok(Self::getBytes1(
1257                self.input.charAt(self.fromPosition as usize)? as u32,
1258            )),
1259            Mode::C40 => self.getC40Words(true, self.input.getFNC1Character()),
1260            Mode::Text => self.getC40Words(false, self.input.getFNC1Character()),
1261            Mode::X12 => self.getX12Words(),
1262            Mode::Edf => self.getEDFBytes(),
1263        }
1264        // assert!( false);
1265        // Ok(vec![0])
1266    }
1267}
1268
1269struct RXingResult {
1270    bytes: Vec<u8>,
1271}
1272impl RXingResult {
1273    pub fn new(solution: Option<Arc<Edge>>) -> Result<Self> {
1274        let solution = if let Some(edge) = solution {
1275            edge
1276        } else {
1277            return Err(Exceptions::ILLEGAL_ARGUMENT);
1278        };
1279        let input = solution.input.clone();
1280        let mut size = 0;
1281        let mut bytesAL = Vec::new(); //new ArrayList<>();
1282        let mut randomizePostfixLength = Vec::new(); //new ArrayList<>();
1283        let mut randomizeLengths = Vec::new(); //new ArrayList<>();
1284        if (solution.mode == Mode::C40 || solution.mode == Mode::Text || solution.mode == Mode::X12)
1285            && solution.getEndMode()? != Mode::Ascii
1286        {
1287            size += Self::prepend(&Edge::getBytes1(254), &mut bytesAL);
1288        }
1289        let mut hold_current = Some(solution.clone());
1290        while let Some(current) = hold_current {
1291            // Fails on i = 77 should be 151 is 144
1292            size += Self::prepend(&current.getDataBytes()?, &mut bytesAL);
1293
1294            if current.previous.is_none()
1295                || Edge::getPreviousStartMode(current.previous.clone()) != current.getMode()
1296            {
1297                if current.getMode() == Mode::B256 {
1298                    if size <= 249 {
1299                        bytesAL.insert(0, size as u8);
1300                        size += 1;
1301                    } else {
1302                        bytesAL.insert(0, (size % 250) as u8);
1303                        bytesAL.insert(0, (size / 250 + 249) as u8);
1304                        size += 2;
1305                    }
1306                    randomizePostfixLength.push(bytesAL.len());
1307                    randomizeLengths.push(size);
1308                }
1309                Self::prepend(&current.getLatchBytes()?, &mut bytesAL);
1310                size = 0;
1311            }
1312
1313            hold_current = current.previous.clone();
1314        }
1315        if input.getMacroId() == 5 {
1316            _ = Self::prepend(&Edge::getBytes1(236), &mut bytesAL);
1317        } else if input.getMacroId() == 6 {
1318            _ = Self::prepend(&Edge::getBytes1(237), &mut bytesAL);
1319        }
1320
1321        if input.getFNC1Character().is_some() {
1322            _ = Self::prepend(&Edge::getBytes1(232), &mut bytesAL);
1323        }
1324        for i in 0..randomizePostfixLength.len() {
1325            // for (int i = 0; i < randomizePostfixLength.size(); i++) {
1326            let bytes_al_len = bytesAL.len() as u32;
1327            Self::applyRandomPattern(
1328                &mut bytesAL,
1329                bytes_al_len - *randomizePostfixLength.get(i).unwrap() as u32,
1330                *randomizeLengths.get(i).unwrap() as u32,
1331            );
1332        }
1333        //add padding
1334        let capacity = solution.getMinSymbolSize(bytesAL.len() as u32);
1335        if bytesAL.len() < capacity as usize {
1336            bytesAL.push(129);
1337        }
1338        while bytesAL.len() < capacity as usize {
1339            bytesAL.push(Self::randomize253State(bytesAL.len() as u32 + 1) as u8);
1340        }
1341
1342        let mut bytes = vec![0u8; bytesAL.len()];
1343        // for (i, byte) in bytes.iter_mut().enumerate() {
1344        //     // for (int i = 0; i < bytes.length; i++) {
1345        //     *byte = *bytesAL.get(i).unwrap();
1346        // }
1347        bytes[..].copy_from_slice(&bytesAL[..]);
1348
1349        Ok(Self { bytes })
1350    }
1351
1352    pub fn prepend(bytes: &[u8], into: &mut Vec<u8>) -> usize {
1353        for byte in bytes.iter().rev() {
1354            into.insert(0, *byte);
1355        }
1356        bytes.len()
1357    }
1358
1359    #[inline]
1360    fn randomize253State(codewordPosition: u32) -> u32 {
1361        let pseudoRandom = ((149 * codewordPosition) % 253) + 1;
1362        let tempVariable = 129 + pseudoRandom;
1363        if tempVariable <= 254 {
1364            tempVariable
1365        } else {
1366            tempVariable - 254
1367        }
1368    }
1369
1370    pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) {
1371        for i in 0..length as usize {
1372            //See "B.1 253-state algorithm
1373            let Pad_codeword_position = startPosition as usize + i;
1374            let Pad_codeword_value = bytesAL.get(Pad_codeword_position).unwrap_or(&0);
1375            let pseudo_random_number = ((149 * (Pad_codeword_position + 1)) % 255) + 1;
1376            let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16;
1377            bytesAL[Pad_codeword_position] = if temp_variable <= 255 {
1378                temp_variable as u8
1379            } else {
1380                (temp_variable - 256) as u8
1381            };
1382        }
1383    }
1384
1385    pub fn getBytes(&self) -> &[u8] {
1386        &self.bytes
1387    }
1388}
1389
1390struct Input {
1391    shape: SymbolShapeHint,
1392    macroId: i32,
1393    internal: MinimalECIInput,
1394}
1395
1396impl Input {
1397    pub fn new(
1398        stringToEncode: &str,
1399        priorityCharset: Option<CharacterSet>,
1400        fnc1: Option<char>,
1401        shape: SymbolShapeHint,
1402        macroId: i32,
1403    ) -> Self {
1404        let z = fnc1.unwrap_or_default().to_string();
1405        let v = if fnc1.is_some() {
1406            Some(z.as_str())
1407        } else {
1408            None
1409        };
1410        Self {
1411            shape,
1412            macroId,
1413            internal: MinimalECIInput::new(stringToEncode, priorityCharset, v),
1414        }
1415    }
1416
1417    pub fn getMacroId(&self) -> i32 {
1418        self.macroId
1419    }
1420
1421    pub fn getShapeHint(&self) -> SymbolShapeHint {
1422        self.shape
1423    }
1424
1425    pub fn length(&self) -> usize {
1426        self.internal.length()
1427    }
1428    pub fn isECI(&self, index: u32) -> Result<bool> {
1429        self.internal.isECI(index)
1430    }
1431    pub fn charAt(&self, index: usize) -> Result<char> {
1432        self.internal.charAt(index)
1433    }
1434    pub fn getFNC1Character(&self) -> Option<char> {
1435        if self.internal.getFNC1Character() == 1000 {
1436            None
1437        } else {
1438            Some(self.internal.getFNC1Character() as u8 as char)
1439        }
1440    }
1441    fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> {
1442        self.internal.haveNCharacters(index, n)
1443    }
1444    fn isFNC1(&self, index: usize) -> Result<bool> {
1445        self.internal.isFNC1(index)
1446    }
1447    fn getECIValue(&self, index: usize) -> Result<Eci> {
1448        self.internal.getECIValue(index)
1449    }
1450}
1451
1452impl fmt::Display for Input {
1453    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1454        self.internal.fmt(f)
1455    }
1456}