feature flag for optional compliant qr decode

This commit is contained in:
Henry Schimke
2023-01-09 11:38:23 -06:00
parent 379899d214
commit c04bf06d15
3 changed files with 76 additions and 7 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rxing" name = "rxing"
version = "0.2.11" version = "0.2.12"
description="A rust port of the zxing barcode library." description="A rust port of the zxing barcode library."
license="Apache-2.0" license="Apache-2.0"
repository="https://github.com/hschimke/rxing" repository="https://github.com/hschimke/rxing"
@@ -37,3 +37,4 @@ java-rand = "0.2.0"
[features] [features]
default = ["image"] default = ["image"]
image = ["dep:image", "dep:imageproc"] image = ["dep:image", "dep:imageproc"]
allow_forced_iso_ied_18004_compliance = []

View File

@@ -104,8 +104,19 @@ pub enum DecodeHintType {
* second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
*/ */
ALSO_INVERTED, ALSO_INVERTED,
// End of enumeration values.
/**
* Specifies that the codes are expected to be in conformance with the specification
* ISO/IEC 18004 regading the interpretation of character encoding. Values encoded in BYTE mode
* or in KANJI mode are interpreted as ISO-8859-1 characters unless an ECI specified at a prior
* location in the input specified a different encoding. By default the encoding of BYTE encoded
* values is determinied by the {@link #CHARACTER_SET} hint or otherwise by a heuristic that
* examines the bytes. By default KANJI encoded values are interpreted as the bytes of Shift-JIS
* encoded characters (note that this is the case even if an ECI specifies a different
* encoding).
*/
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
QR_ASSUME_SPEC_CONFORM_INPUT,
/* /*
* Data type the hint is expecting. * Data type the hint is expecting.
* Among the possible values the {@link Void} stands out as being used for * Among the possible values the {@link Void} stands out as being used for
@@ -201,5 +212,17 @@ pub enum DecodeHintValue {
* second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}. * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
*/ */
AlsoInverted(bool), AlsoInverted(bool),
// End of enumeration values.
/**
* Specifies that the codes are expected to be in conformance with the specification
* ISO/IEC 18004 regading the interpretation of character encoding. Values encoded in BYTE mode
* or in KANJI mode are interpreted as ISO-8859-1 characters unless an ECI specified at a prior
* location in the input specified a different encoding. By default the encoding of BYTE encoded
* values is determinied by the {@link #CHARACTER_SET} hint or otherwise by a heuristic that
* examines the bytes. By default KANJI encoded values are interpreted as the bytes of Shift-JIS
* encoded characters (note that this is the case even if an ECI specifies a different
* encoding).
*/
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
QrAssumeSpecConformInput(bool),
} }

View File

@@ -19,6 +19,9 @@ use crate::{
DecodingHintDictionary, Exceptions, DecodingHintDictionary, Exceptions,
}; };
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
use crate::{DecodeHintType, DecodeHintValue};
use super::{ErrorCorrectionLevel, Mode, VersionRef}; use super::{ErrorCorrectionLevel, Mode, VersionRef};
/** /**
@@ -125,7 +128,13 @@ pub fn decode(
&mut byteSegments, &mut byteSegments,
hints, hints,
)?, )?,
Mode::KANJI => decodeKanjiSegment(&mut bits, &mut result, count)?, Mode::KANJI => decodeKanjiSegment(
&mut bits,
&mut result,
count,
currentCharacterSetECI,
hints,
)?,
_ => return Err(Exceptions::FormatException(None)), _ => return Err(Exceptions::FormatException(None)),
} }
} }
@@ -217,6 +226,8 @@ fn decodeKanjiSegment(
bits: &mut BitSource, bits: &mut BitSource,
result: &mut String, result: &mut String,
count: usize, count: usize,
currentCharacterSetECI: Option<CharacterSetECI>,
hints: &DecodingHintDictionary,
) -> Result<(), Exceptions> { ) -> Result<(), Exceptions> {
// Don't crash trying to read more bits than we have available. // Don't crash trying to read more bits than we have available.
if count * 13 > bits.available() { if count * 13 > bits.available() {
@@ -245,10 +256,32 @@ fn decodeKanjiSegment(
count -= 1; count -= 1;
} }
let sjs_encoder = encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); #[cfg(not(feature = "allow_forced_iso_ied_18004_compliance"))]
let encode_string = sjs_encoder let encoder = {
let _ = currentCharacterSetECI;
let _ = hints;
encoding::label::encoding_from_whatwg_label("SJIS").unwrap()
};
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
let encoder = if let Some(DecodeHintValue::QrAssumeSpecConformInput(true)) =
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
{
// if (hints != null && hints.containsKey(DecodeHintType.QR_ASSUME_SPEC_CONFORM_INPUT)) {
if let Some(ccse) = &currentCharacterSetECI {
// if (currentCharacterSetECI == null) {
CharacterSetECI::getCharset(ccse)
} else {
encoding::all::ISO_8859_1
}
} else {
encoding::label::encoding_from_whatwg_label("SJIS").unwrap()
};
let encode_string = encoder
.decode(&buffer, encoding::DecoderTrap::Strict) .decode(&buffer, encoding::DecoderTrap::Strict)
.unwrap(); .unwrap();
result.push_str(&encode_string); result.push_str(&encode_string);
Ok(()) Ok(())
@@ -280,7 +313,19 @@ fn decodeByteSegment(
// upon decoding. I have seen ISO-8859-1 used as well as // upon decoding. I have seen ISO-8859-1 used as well as
// Shift_JIS -- without anything like an ECI designator to // Shift_JIS -- without anything like an ECI designator to
// give a hint. // give a hint.
StringUtils::guessCharset(&readBytes, hints) {
#[cfg(not(feature = "allow_forced_iso_ied_18004_compliance"))]
StringUtils::guessCharset(&readBytes, hints)
}
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
if let Some(DecodeHintValue::QrAssumeSpecConformInput(true)) =
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
{
encoding::all::ISO_8859_1
} else {
StringUtils::guessCharset(&readBytes, hints)
}
} else { } else {
CharacterSetECI::getCharset(currentCharacterSetECI.as_ref().unwrap()) CharacterSetECI::getCharset(currentCharacterSetECI.as_ref().unwrap())
}; };