rxing/aztec/encoder/
state.rs1use std::fmt;
18
19use crate::{
20 common::{BitArray, CharacterSet, Eci, Result},
21 exceptions::Exceptions,
22};
23
24use super::{HighLevelEncoder, Token};
25
26#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct State {
32 mode: u32,
37 token: Token,
40 binary_shift_byte_count: u32,
43 bit_count: u32,
45 binary_shift_cost: u32,
46}
47impl State {
48 pub fn new(token: Token, mode: u32, binary_bytes: u32, bit_count: u32) -> Self {
49 Self {
50 mode,
51 token,
52 binary_shift_byte_count: binary_bytes,
53 bit_count,
54 binary_shift_cost: Self::calculate_binary_shift_cost(binary_bytes),
55 }
56 }
57
58 pub fn getMode(&self) -> u32 {
59 self.mode
60 }
61
62 pub fn getToken(&self) -> &Token {
63 &self.token
64 }
65
66 pub fn getBinaryShiftByteCount(&self) -> u32 {
67 self.binary_shift_byte_count
68 }
69
70 pub fn getBitCount(&self) -> u32 {
71 self.bit_count
72 }
73
74 pub fn appendFLGn(self, eci: Eci) -> Result<Self> {
75 let bit_count = self.bit_count;
76 let mode = self.mode;
77 let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); let mut token = result.token;
79 let mut bits_added = 3;
80 if eci as u32 > 999999 {
84 return Err(Exceptions::illegal_argument_with(
85 "ECI code must be between 0 and 999999",
86 ));
87 } else {
89 let Ok(eci_digits) = CharacterSet::ISO8859_1.encode(&format!("{eci}")) else {
90 return Err(Exceptions::ILLEGAL_ARGUMENT);
91 };
92 token.add(eci_digits.len() as i32, 3); for eci_digit in &eci_digits {
95 token.add((eci_digit - b'0' + 2) as i32, 4);
97 }
98 bits_added += eci_digits.len() * 4;
99 }
100 Ok(State::new(token, mode, 0, bit_count + bits_added as u32))
101 }
103
104 pub fn latchAndAppend(self, mode: u32, value: u32) -> State {
107 let mut bitCount = self.bit_count;
108 let mut token = self.token;
109 if mode != self.mode {
110 let latch = HighLevelEncoder::LATCH_TABLE[self.mode as usize][mode as usize];
111 token.add(latch as i32 & 0xFFFF, latch >> 16);
112 bitCount += latch >> 16;
113 }
114 let latchModeBitCount = if mode == HighLevelEncoder::MODE_DIGIT as u32 {
115 4
116 } else {
117 5
118 };
119 token.add(value as i32, latchModeBitCount);
120
121 State::new(token, mode, 0, bitCount + latchModeBitCount)
122 }
123
124 pub fn shiftAndAppend(self, mode: u32, value: u32) -> State {
127 let mut token = self.token;
128 let thisModeBitCount = if self.mode == HighLevelEncoder::MODE_DIGIT as u32 {
129 4
130 } else {
131 5
132 };
133 token.add(
135 HighLevelEncoder::SHIFT_TABLE[self.mode as usize][mode as usize],
136 thisModeBitCount,
137 );
138 token.add(value as i32, 5);
139 State::new(token, self.mode, 0, self.bit_count + thisModeBitCount + 5)
140 }
141
142 pub fn addBinaryShiftChar(self, index: u32) -> State {
145 let mut token = self.token;
146 let mut mode = self.mode;
147 let mut bitCount = self.bit_count;
148 if self.mode == HighLevelEncoder::MODE_PUNCT as u32
149 || self.mode == HighLevelEncoder::MODE_DIGIT as u32
150 {
151 let latch = HighLevelEncoder::LATCH_TABLE[mode as usize][HighLevelEncoder::MODE_UPPER];
152 token.add(latch as i32 & 0xFFFF, latch >> 16);
153 bitCount += latch >> 16;
154 mode = HighLevelEncoder::MODE_UPPER as u32;
155 }
156 let deltaBitCount =
157 if self.binary_shift_byte_count == 0 || self.binary_shift_byte_count == 31 {
158 18
159 } else if self.binary_shift_byte_count == 62 {
160 9
161 } else {
162 8
163 };
164 let mut result = State::new(
165 token,
166 mode,
167 self.binary_shift_byte_count + 1,
168 bitCount + deltaBitCount,
169 );
170 if result.binary_shift_byte_count == 2047 + 31 {
171 result = result.endBinaryShift(index + 1);
173 }
174 result
175 }
176
177 pub fn endBinaryShift(self, index: u32) -> State {
180 if self.binary_shift_byte_count == 0 {
181 return self;
182 }
183 let mut token = self.token;
184 token.addBinaryShift(
185 index - self.binary_shift_byte_count,
186 self.binary_shift_byte_count,
187 );
188
189 State::new(token, self.mode, 0, self.bit_count)
190 }
191
192 pub const fn isBetterThanOrEqualTo(&self, other: &State) -> bool {
195 let mut new_mode_bit_count = self.bit_count
196 + (HighLevelEncoder::LATCH_TABLE[self.mode as usize][other.mode as usize] >> 16);
197 if self.binary_shift_byte_count < other.binary_shift_byte_count {
198 new_mode_bit_count += other.binary_shift_cost - self.binary_shift_cost;
200 } else if self.binary_shift_byte_count > other.binary_shift_byte_count
201 && other.binary_shift_byte_count > 0
202 {
203 new_mode_bit_count += 10;
205 }
206 new_mode_bit_count <= other.bit_count
207 }
208
209 pub fn toBitArray(self, text: &[u8]) -> Result<BitArray> {
210 let tok = self.endBinaryShift(text.len() as u32).token;
211
212 let symbols = tok.into_iter().collect::<Vec<_>>();
213
214 let mut bit_array = BitArray::new();
215 for symbol in symbols.into_iter().rev() {
217 symbol.appendTo(&mut bit_array, text)?;
220 }
221 Ok(bit_array)
222 }
223
224 #[inline(always)]
225 const fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
226 if binary_shift_byte_count > 62 {
227 21 } else if binary_shift_byte_count > 31 {
229 20 } else if binary_shift_byte_count > 0 {
231 10 } else {
233 0
234 }
235 }
236}
237
238impl fmt::Display for State {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 write!(
241 f,
242 "{} bits={} bytes={}",
243 HighLevelEncoder::MODE_NAMES[self.mode as usize],
244 self.bit_count,
245 self.binary_shift_byte_count
246 )
247 }
248}