rxing/decode_hints.rs
1/*
2 * Copyright 2007 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
17//package com.google.zxing;
18
19use std::collections::{HashMap, HashSet};
20
21use crate::{BarcodeFormat, PointCallback};
22
23#[cfg(feature = "serde")]
24use serde::{Deserialize, Serialize};
25
26/**
27 * Encapsulates a type of hint that a caller may pass to a barcode reader to help it
28 * more quickly or accurately decode it. It is up to implementations to decide what,
29 * if anything, to do with the information that is supplied.
30 *
31 * @author Sean Owen
32 * @author dswitkin@google.com (Daniel Switkin)
33 * @see Reader#decode(BinaryBitmap,java.util.Map)
34 */
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
37pub enum DecodeHintType {
38 /**
39 * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
40 */
41 OTHER,
42
43 /**
44 * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
45 * use {@link Boolean#TRUE}.
46 */
47 PURE_BARCODE,
48
49 /**
50 * Image is known to be of one of a few possible formats.
51 * Maps to a {@link List} of {@link BarcodeFormat}s.
52 */
53 POSSIBLE_FORMATS,
54
55 /**
56 * Spend more time to try to find a barcode; optimize for accuracy, not speed.
57 * Doesn't matter what it maps to; use {@link Boolean#TRUE}.
58 */
59 TRY_HARDER,
60
61 /**
62 * Specifies what character encoding to use when decoding, where applicable (type String)
63 */
64 CHARACTER_SET,
65
66 /**
67 * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}.
68 */
69 ALLOWED_LENGTHS,
70
71 /**
72 * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;
73 * use {@link Boolean#TRUE}.
74 */
75 ASSUME_CODE_39_CHECK_DIGIT,
76
77 /**
78 * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.
79 * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;
80 * use {@link Boolean#TRUE}.
81 */
82 ASSUME_GS1,
83
84 /**
85 * If true, return the start and end digits in a Codabar barcode instead of stripping them. They
86 * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
87 * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
88 */
89 RETURN_CODABAR_START_END,
90
91 /**
92 * The caller needs to be notified via callback when a possible {@link Point}
93 * is found. Maps to a {@link PointCallback}.
94 */
95 NEED_RESULT_POINT_CALLBACK,
96
97 /**
98 * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
99 * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5].
100 * If it is optional to have an extension, do not set this hint. If this is set,
101 * and a UPC or EAN barcode is found but an extension is not, then no result will be returned
102 * at all.
103 */
104 ALLOWED_EAN_EXTENSIONS,
105
106 /**
107 * If true, also tries to decode as inverted image. All configured decoders are simply called a
108 * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
109 */
110 ALSO_INVERTED,
111
112 /**
113 * Specifies that the codes are expected to be in conformance with the specification
114 * ISO/IEC 18004 regading the interpretation of character encoding. Values encoded in BYTE mode
115 * or in KANJI mode are interpreted as ISO-8859-1 characters unless an ECI specified at a prior
116 * location in the input specified a different encoding. By default the encoding of BYTE encoded
117 * values is determinied by the {@link #CHARACTER_SET} hint or otherwise by a heuristic that
118 * examines the bytes. By default KANJI encoded values are interpreted as the bytes of Shift-JIS
119 * encoded characters (note that this is the case even if an ECI specifies a different
120 * encoding).
121 */
122 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
123 QR_ASSUME_SPEC_CONFORM_INPUT,
124
125 /*
126 * Will translate the ASCII values parsed by the Telepen reader into the Telepen Numeric form.
127 */
128 TELEPEN_AS_NUMERIC,
129 /*
130 * Data type the hint is expecting.
131 * Among the possible values the {@link Void} stands out as being used for
132 * hints that do not expect a value to be supplied (flag hints). Such hints
133 * will possibly have their value ignored, or replaced by a
134 * {@link Boolean#TRUE}. Hint suppliers should probably use
135 * {@link Boolean#TRUE} as directed by the actual hint documentation.
136 */
137 /*
138 private final Class<?> valueType;
139
140 DecodeHintType(Class<?> valueType) {
141 this.valueType = valueType;
142 }
143
144 public Class<?> getValueType() {
145 return valueType;
146 }*/
147}
148
149#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
150#[derive(Clone)]
151pub enum DecodeHintValue {
152 /**
153 * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
154 */
155 Other(String),
156
157 /**
158 * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
159 * use {@link Boolean#TRUE}.
160 */
161 PureBarcode(bool),
162
163 /**
164 * Image is known to be of one of a few possible formats.
165 * Maps to a {@link List} of {@link BarcodeFormat}s.
166 */
167 PossibleFormats(HashSet<BarcodeFormat>),
168
169 /**
170 * Spend more time to try to find a barcode; optimize for accuracy, not speed.
171 * Doesn't matter what it maps to; use {@link Boolean#TRUE}.
172 */
173 TryHarder(bool),
174
175 /**
176 * Specifies what character encoding to use when decoding, where applicable (type String)
177 */
178 CharacterSet(String),
179
180 /**
181 * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}.
182 */
183 AllowedLengths(Vec<u32>),
184
185 /**
186 * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;
187 * use {@link Boolean#TRUE}.
188 */
189 AssumeCode39CheckDigit(bool),
190
191 /**
192 * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.
193 * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;
194 * use {@link Boolean#TRUE}.
195 */
196 AssumeGs1(bool),
197
198 /**
199 * If true, return the start and end digits in a Codabar barcode instead of stripping them. They
200 * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
201 * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
202 */
203 ReturnCodabarStartEnd(bool),
204
205 /**
206 * The caller needs to be notified via callback when a possible {@link Point}
207 * is found. Maps to a {@link PointCallback}.
208 */
209 #[cfg_attr(feature = "serde", serde(skip_serializing, skip_deserializing))]
210 NeedResultPointCallback(PointCallback),
211
212 /**
213 * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
214 * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5].
215 * If it is optional to have an extension, do not set this hint. If this is set,
216 * and a UPC or EAN barcode is found but an extension is not, then no result will be returned
217 * at all.
218 */
219 AllowedEanExtensions(Vec<u32>),
220
221 /**
222 * If true, also tries to decode as inverted image. All configured decoders are simply called a
223 * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
224 */
225 AlsoInverted(bool),
226
227 /**
228 * Specifies that the codes are expected to be in conformance with the specification
229 * ISO/IEC 18004 regading the interpretation of character encoding. Values encoded in BYTE mode
230 * or in KANJI mode are interpreted as ISO-8859-1 characters unless an ECI specified at a prior
231 * location in the input specified a different encoding. By default the encoding of BYTE encoded
232 * values is determinied by the {@link #CHARACTER_SET} hint or otherwise by a heuristic that
233 * examines the bytes. By default KANJI encoded values are interpreted as the bytes of Shift-JIS
234 * encoded characters (note that this is the case even if an ECI specifies a different
235 * encoding).
236 */
237 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
238 QrAssumeSpecConformInput(bool),
239
240 /**
241 * Translate the ASCII values parsed by the Telepen reader into the Telepen Numeric form; use {@link Boolean#TRUE}.
242 */
243 TelepenAsNumeric(bool),
244}
245
246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
247#[derive(Default, Clone)]
248pub struct DecodeHints {
249 /**
250 * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
251 */
252 pub Other: Option<String>,
253
254 /**
255 * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
256 * use {@link Boolean#TRUE}.
257 */
258 pub PureBarcode: Option<bool>,
259
260 /**
261 * Image is known to be of one of a few possible formats.
262 * Maps to a {@link List} of {@link BarcodeFormat}s.
263 */
264 pub PossibleFormats: Option<HashSet<BarcodeFormat>>,
265
266 /**
267 * Spend more time to try to find a barcode; optimize for accuracy, not speed.
268 * Doesn't matter what it maps to; use {@link Boolean#TRUE}.
269 */
270 pub TryHarder: Option<bool>,
271
272 /**
273 * Specifies what character encoding to use when decoding, where applicable (type String)
274 */
275 pub CharacterSet: Option<String>,
276
277 /**
278 * Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}.
279 */
280 pub AllowedLengths: Option<Vec<u32>>,
281
282 /**
283 * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;
284 * use {@link Boolean#TRUE}.
285 */
286 pub AssumeCode39CheckDigit: Option<bool>,
287
288 /**
289 * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.
290 * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;
291 * use {@link Boolean#TRUE}.
292 */
293 pub AssumeGs1: Option<bool>,
294
295 /**
296 * If true, return the start and end digits in a Codabar barcode instead of stripping them. They
297 * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
298 * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
299 */
300 pub ReturnCodabarStartEnd: Option<bool>,
301
302 /**
303 * The caller needs to be notified via callback when a possible {@link Point}
304 * is found. Maps to a {@link PointCallback}.
305 */
306 #[cfg_attr(feature = "serde", serde(skip_serializing, skip_deserializing))]
307 pub NeedResultPointCallback: Option<PointCallback>,
308
309 /**
310 * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
311 * Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5].
312 * If it is optional to have an extension, do not set this hint. If this is set,
313 * and a UPC or EAN barcode is found but an extension is not, then no result will be returned
314 * at all.
315 */
316 pub AllowedEanExtensions: Option<Vec<u32>>,
317
318 /**
319 * If true, also tries to decode as inverted image. All configured decoders are simply called a
320 * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
321 */
322 pub AlsoInverted: Option<bool>,
323
324 /**
325 * Specifies that the codes are expected to be in conformance with the specification
326 * ISO/IEC 18004 regading the interpretation of character encoding. Values encoded in BYTE mode
327 * or in KANJI mode are interpreted as ISO-8859-1 characters unless an ECI specified at a prior
328 * location in the input specified a different encoding. By default the encoding of BYTE encoded
329 * values is determinied by the {@link #CHARACTER_SET} hint or otherwise by a heuristic that
330 * examines the bytes. By default KANJI encoded values are interpreted as the bytes of Shift-JIS
331 * encoded characters (note that this is the case even if an ECI specifies a different
332 * encoding).
333 */
334 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
335 pub QrAssumeSpecConformInput: Option<bool>,
336
337 /**
338 * Translate the ASCII values parsed by the Telepen reader into the Telepen Numeric form; use {@link Boolean#TRUE}.
339 */
340 pub TelepenAsNumeric: Option<bool>,
341}
342
343impl From<super::DecodingHintDictionary> for DecodeHints {
344 fn from(value: super::DecodingHintDictionary) -> Self {
345 let mut new_self: Self = Self::default();
346 for (_, v) in value.into_iter() {
347 match v {
348 DecodeHintValue::Other(v) => new_self.Other = Some(v),
349 DecodeHintValue::PureBarcode(v) => new_self.PureBarcode = Some(v),
350 DecodeHintValue::PossibleFormats(v) => new_self.PossibleFormats = Some(v),
351 DecodeHintValue::TryHarder(v) => new_self.TryHarder = Some(v),
352 DecodeHintValue::CharacterSet(v) => new_self.CharacterSet = Some(v),
353 DecodeHintValue::AllowedLengths(v) => new_self.AllowedLengths = Some(v),
354 DecodeHintValue::AssumeCode39CheckDigit(v) => {
355 new_self.AssumeCode39CheckDigit = Some(v)
356 }
357 DecodeHintValue::AssumeGs1(v) => new_self.AssumeGs1 = Some(v),
358 DecodeHintValue::ReturnCodabarStartEnd(v) => {
359 new_self.ReturnCodabarStartEnd = Some(v)
360 }
361 DecodeHintValue::NeedResultPointCallback(v) => {
362 new_self.NeedResultPointCallback = Some(v)
363 }
364 DecodeHintValue::AllowedEanExtensions(v) => new_self.AllowedEanExtensions = Some(v),
365 DecodeHintValue::AlsoInverted(v) => new_self.AlsoInverted = Some(v),
366 DecodeHintValue::TelepenAsNumeric(v) => new_self.TelepenAsNumeric = Some(v),
367 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
368 DecodeHintValue::QrAssumeSpecConformInput(v) => {
369 new_self.QrAssumeSpecConformInput = Some(v)
370 }
371 }
372 }
373 new_self
374 }
375}
376
377impl From<DecodeHints> for super::DecodingHintDictionary {
378 fn from(value: DecodeHints) -> Self {
379 let mut new_self = HashMap::default();
380
381 if let Some(v) = value.Other {
382 new_self.insert(DecodeHintType::OTHER, DecodeHintValue::Other(v));
383 }
384
385 if let Some(v) = value.PureBarcode {
386 new_self.insert(
387 DecodeHintType::PURE_BARCODE,
388 DecodeHintValue::PureBarcode(v),
389 );
390 }
391
392 if let Some(v) = value.PossibleFormats {
393 new_self.insert(
394 DecodeHintType::POSSIBLE_FORMATS,
395 DecodeHintValue::PossibleFormats(v),
396 );
397 }
398
399 if let Some(v) = value.TryHarder {
400 new_self.insert(DecodeHintType::TRY_HARDER, DecodeHintValue::TryHarder(v));
401 }
402
403 if let Some(v) = value.CharacterSet {
404 new_self.insert(
405 DecodeHintType::CHARACTER_SET,
406 DecodeHintValue::CharacterSet(v),
407 );
408 }
409
410 if let Some(v) = value.AllowedLengths {
411 new_self.insert(
412 DecodeHintType::ALLOWED_LENGTHS,
413 DecodeHintValue::AllowedLengths(v),
414 );
415 }
416
417 if let Some(v) = value.AssumeCode39CheckDigit {
418 new_self.insert(
419 DecodeHintType::ASSUME_CODE_39_CHECK_DIGIT,
420 DecodeHintValue::AssumeCode39CheckDigit(v),
421 );
422 }
423
424 if let Some(v) = value.AssumeGs1 {
425 new_self.insert(DecodeHintType::ASSUME_GS1, DecodeHintValue::AssumeGs1(v));
426 }
427
428 if let Some(v) = value.ReturnCodabarStartEnd {
429 new_self.insert(
430 DecodeHintType::RETURN_CODABAR_START_END,
431 DecodeHintValue::ReturnCodabarStartEnd(v),
432 );
433 }
434
435 if let Some(v) = value.NeedResultPointCallback {
436 new_self.insert(
437 DecodeHintType::NEED_RESULT_POINT_CALLBACK,
438 DecodeHintValue::NeedResultPointCallback(v),
439 );
440 }
441
442 if let Some(v) = value.AllowedEanExtensions {
443 new_self.insert(
444 DecodeHintType::ALLOWED_EAN_EXTENSIONS,
445 DecodeHintValue::AllowedEanExtensions(v),
446 );
447 }
448
449 if let Some(v) = value.AlsoInverted {
450 new_self.insert(
451 DecodeHintType::ALSO_INVERTED,
452 DecodeHintValue::AlsoInverted(v),
453 );
454 }
455
456 if let Some(v) = value.TelepenAsNumeric {
457 new_self.insert(
458 DecodeHintType::TELEPEN_AS_NUMERIC,
459 DecodeHintValue::TelepenAsNumeric(v),
460 );
461 }
462
463 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
464 if let Some(v) = value.QrAssumeSpecConformInput {
465 new_self.insert(
466 DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT,
467 DecodeHintValue::QrAssumeSpecConformInput(v),
468 );
469 }
470
471 new_self
472 }
473}
474
475impl DecodeHints {
476 pub fn with(mut self, value: DecodeHintValue) -> Self {
477 match value {
478 DecodeHintValue::Other(v) => self.Other = Some(v),
479 DecodeHintValue::PureBarcode(v) => self.PureBarcode = Some(v),
480 DecodeHintValue::PossibleFormats(v) => self.PossibleFormats = Some(v),
481 DecodeHintValue::TryHarder(v) => self.TryHarder = Some(v),
482 DecodeHintValue::CharacterSet(v) => self.CharacterSet = Some(v),
483 DecodeHintValue::AllowedLengths(v) => self.AllowedLengths = Some(v),
484 DecodeHintValue::AssumeCode39CheckDigit(v) => self.AssumeCode39CheckDigit = Some(v),
485 DecodeHintValue::AssumeGs1(v) => self.AssumeGs1 = Some(v),
486 DecodeHintValue::ReturnCodabarStartEnd(v) => self.ReturnCodabarStartEnd = Some(v),
487 DecodeHintValue::NeedResultPointCallback(v) => self.NeedResultPointCallback = Some(v),
488 DecodeHintValue::AllowedEanExtensions(v) => self.AllowedEanExtensions = Some(v),
489 DecodeHintValue::AlsoInverted(v) => self.AlsoInverted = Some(v),
490 DecodeHintValue::TelepenAsNumeric(v) => self.TelepenAsNumeric = Some(v),
491 #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
492 DecodeHintValue::QrAssumeSpecConformInput(v) => self.QrAssumeSpecConformInput = Some(v),
493 }
494 self
495 }
496}