mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
repurpose CharacterSetECI as encoding abstraction
This commit is contained in:
@@ -204,9 +204,9 @@ fn decodeHanziSegment(bits: &mut BitSource, result: &mut String, count: usize) -
|
||||
}
|
||||
|
||||
let gb_encoder =
|
||||
encoding::label::encoding_from_whatwg_label("GBK").ok_or(Exceptions::ILLEGAL_STATE)?;
|
||||
CharacterSetECI::GB18030;
|
||||
let encode_string = gb_encoder
|
||||
.decode(&buffer, encoding::DecoderTrap::Strict)
|
||||
.decode(&buffer)
|
||||
.map_err(|e| Exceptions::parse_with(format!("unable to decode buffer {buffer:?}: {e}")))?;
|
||||
result.push_str(&encode_string);
|
||||
Ok(())
|
||||
@@ -250,7 +250,7 @@ fn decodeKanjiSegment(
|
||||
let encoder = {
|
||||
let _ = currentCharacterSetECI;
|
||||
let _ = hints;
|
||||
encoding::label::encoding_from_whatwg_label("SJIS").ok_or(Exceptions::FORMAT)?
|
||||
CharacterSetECI::SJIS
|
||||
};
|
||||
|
||||
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
|
||||
@@ -258,16 +258,16 @@ fn decodeKanjiSegment(
|
||||
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
|
||||
{
|
||||
if let Some(ccse) = ¤tCharacterSetECI {
|
||||
CharacterSetECI::getCharset(ccse)
|
||||
CharacterSetECI::getCharacterSetECIByName(ccse)
|
||||
} else {
|
||||
encoding::all::ISO_8859_1
|
||||
CharacterSetECI::ISO8859_1
|
||||
}
|
||||
} else {
|
||||
encoding::label::encoding_from_whatwg_label("SJIS").ok_or(Exceptions::FORMAT)?
|
||||
CharacterSetECI::SJIS
|
||||
};
|
||||
|
||||
let encode_string = encoder
|
||||
.decode(&buffer, encoding::DecoderTrap::Strict)
|
||||
.decode(&buffer)
|
||||
.map_err(|e| Exceptions::parse_with(format!("unable to decode buffer {buffer:?}: {e}")))?;
|
||||
|
||||
result.push_str(&encode_string);
|
||||
@@ -308,37 +308,26 @@ fn decodeByteSegment(
|
||||
if let Some(DecodeHintValue::QrAssumeSpecConformInput(true)) =
|
||||
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
|
||||
{
|
||||
encoding::all::ISO_8859_1
|
||||
CharacterSetECI::ISO8859_1
|
||||
} else {
|
||||
StringUtils::guessCharset(&readBytes, hints).ok_or(Exceptions::ILLEGAL_STATE)?
|
||||
}
|
||||
} else {
|
||||
CharacterSetECI::getCharset(
|
||||
currentCharacterSetECI
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::ILLEGAL_STATE)?,
|
||||
)
|
||||
currentCharacterSetECI.ok_or(Exceptions::ILLEGAL_STATE)?
|
||||
// CharacterSetECI::getCharset(
|
||||
// currentCharacterSetECI
|
||||
// .as_ref()
|
||||
// .ok_or(Exceptions::ILLEGAL_STATE)?,
|
||||
// )
|
||||
};
|
||||
|
||||
let encode_string = if currentCharacterSetECI.is_some()
|
||||
&& currentCharacterSetECI
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::ILLEGAL_STATE)?
|
||||
== &CharacterSetECI::Cp437
|
||||
{
|
||||
{
|
||||
use codepage_437::BorrowFromCp437;
|
||||
use codepage_437::CP437_CONTROL;
|
||||
|
||||
String::borrow_from_cp437(&readBytes, &CP437_CONTROL)
|
||||
}
|
||||
} else {
|
||||
let encode_string =
|
||||
encoding
|
||||
.decode(&readBytes, encoding::DecoderTrap::Strict)
|
||||
.decode(&readBytes)
|
||||
.map_err(|e| {
|
||||
Exceptions::parse_with(format!("unable to decode buffer {readBytes:?}: {e}"))
|
||||
})?
|
||||
};
|
||||
;
|
||||
|
||||
result.push_str(&encode_string);
|
||||
byteSegments.push(readBytes);
|
||||
|
||||
@@ -17,20 +17,19 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::BitArray,
|
||||
common::{BitArray, CharacterSetECI},
|
||||
qrcode::{
|
||||
decoder::{ErrorCorrectionLevel, Mode, Version},
|
||||
encoder::{qrcode_encoder, MinimalEncoder},
|
||||
},
|
||||
EncodeHintType, EncodeHintValue,
|
||||
};
|
||||
use encoding::EncodingRef;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::QRCode;
|
||||
|
||||
static SHIFT_JIS_CHARSET: Lazy<EncodingRef> =
|
||||
Lazy::new(|| encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
|
||||
static SHIFT_JIS_CHARSET: Lazy<CharacterSetECI> =
|
||||
Lazy::new(|| CharacterSetECI::SJIS);
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
@@ -1075,10 +1074,9 @@ fn testMinimalEncoder41() {
|
||||
#[test]
|
||||
fn testMinimalEncoder42() {
|
||||
// test halfwidth Katakana character (they are single byte encoded in Shift_JIS)
|
||||
// NOTE: Changed to windows-31j because that is what is supported in encoding crate
|
||||
verifyMinimalEncoding(
|
||||
"Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}",
|
||||
"ECI(windows-31j),BYTE(Katakana:......)",
|
||||
"ECI(shift_jis),BYTE(Katakana:......)",
|
||||
None,
|
||||
false,
|
||||
);
|
||||
@@ -1100,10 +1098,9 @@ fn testMinimalEncoder44() {
|
||||
// The character \u30A2 encodes as double byte in Shift_JIS but KANJI is not more compact in this case because
|
||||
// KANJI is only more compact when it encodes pairs of characters. In the case of mixed text it can however be
|
||||
// that Shift_JIS encoding is more compact as in this example
|
||||
// NOTE: Changed to windows-31j because that is what is supported in encoding crate
|
||||
verifyMinimalEncoding(
|
||||
"Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}",
|
||||
"ECI(windows-31j),BYTE(Katakana:.a.a.a.a.a.)",
|
||||
"ECI(shift_jis),BYTE(Katakana:.a.a.a.a.a.)",
|
||||
None,
|
||||
false,
|
||||
);
|
||||
@@ -1112,7 +1109,7 @@ fn testMinimalEncoder44() {
|
||||
fn verifyMinimalEncoding(
|
||||
input: &str,
|
||||
expectedRXingResult: &str,
|
||||
priorityCharset: Option<EncodingRef>,
|
||||
priorityCharset: Option<CharacterSetECI>,
|
||||
isGS1: bool,
|
||||
) {
|
||||
let result = MinimalEncoder::encode_with_details(
|
||||
@@ -1198,7 +1195,7 @@ fn verifyNotGS1EncodedData(qrCode: &QRCode) {
|
||||
|
||||
fn shiftJISString(bytes: &[u8]) -> String {
|
||||
SHIFT_JIS_CHARSET
|
||||
.decode(bytes, encoding::DecoderTrap::Strict)
|
||||
.decode(bytes)
|
||||
.expect("decode should be ok")
|
||||
// return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
use std::{fmt, rc::Rc};
|
||||
|
||||
use encoding::EncodingRef;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, ECIEncoderSet, Result},
|
||||
common::{BitArray, ECIEncoderSet, Result, CharacterSetECI},
|
||||
qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef},
|
||||
Exceptions,
|
||||
};
|
||||
@@ -107,7 +105,7 @@ impl MinimalEncoder {
|
||||
*/
|
||||
pub fn new(
|
||||
stringToEncode: &str,
|
||||
priorityCharset: Option<EncodingRef>,
|
||||
priorityCharset: Option<CharacterSetECI>,
|
||||
isGS1: bool,
|
||||
ecLevel: ErrorCorrectionLevel,
|
||||
) -> Self {
|
||||
@@ -142,7 +140,7 @@ impl MinimalEncoder {
|
||||
pub fn encode_with_details(
|
||||
stringToEncode: &str,
|
||||
version: Option<VersionRef>,
|
||||
priorityCharset: Option<EncodingRef>,
|
||||
priorityCharset: Option<CharacterSetECI>,
|
||||
isGS1: bool,
|
||||
ecLevel: ErrorCorrectionLevel,
|
||||
) -> Result<RXingResultList> {
|
||||
@@ -1044,10 +1042,10 @@ impl fmt::Display for RXingResultNode {
|
||||
result.push('(');
|
||||
if self.mode == Mode::ECI {
|
||||
result.push_str(
|
||||
self.encoders
|
||||
&self.encoders
|
||||
.getCharset(self.charsetEncoderIndex)
|
||||
.ok_or(fmt::Error)?
|
||||
.name(),
|
||||
.getCharsetName(),
|
||||
);
|
||||
} else {
|
||||
let sub_string: String = self
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
*/
|
||||
use std::collections::HashMap;
|
||||
|
||||
use encoding::EncodingRef;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{
|
||||
@@ -35,8 +32,8 @@ use crate::{
|
||||
|
||||
use super::{mask_util, matrix_util, BlockPair, ByteMatrix, MinimalEncoder, QRCode};
|
||||
|
||||
static SHIFT_JIS_CHARSET: Lazy<EncodingRef> =
|
||||
Lazy::new(|| encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
|
||||
static SHIFT_JIS_CHARSET: CharacterSetECI =
|
||||
CharacterSetECI::SJIS;
|
||||
|
||||
// The original table is defined in the table 5 of JISX0510:2004 (p.19).
|
||||
const ALPHANUMERIC_TABLE: [i8; 96] = [
|
||||
@@ -48,7 +45,7 @@ const ALPHANUMERIC_TABLE: [i8; 96] = [
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
|
||||
];
|
||||
|
||||
pub const DEFAULT_BYTE_MODE_ENCODING: EncodingRef = encoding::all::ISO_8859_1;
|
||||
pub const DEFAULT_BYTE_MODE_ENCODING: CharacterSetECI = CharacterSetECI::ISO8859_1;
|
||||
|
||||
// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
|
||||
// Basically it applies four rules and summate all penalties.
|
||||
@@ -101,7 +98,7 @@ pub fn encode_with_hints(
|
||||
if has_encoding_hint {
|
||||
if let Some(EncodeHintValue::CharacterSet(v)) = hints.get(&EncodeHintType::CHARACTER_SET) {
|
||||
encoding =
|
||||
Some(encoding::label::encoding_from_whatwg_label(v).ok_or(Exceptions::WRITER)?)
|
||||
Some(CharacterSetECI::getCharacterSetECIByName(v).ok_or(Exceptions::WRITER)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,12 +123,12 @@ pub fn encode_with_hints(
|
||||
let encoding = if let Some(encoding) = encoding {
|
||||
encoding
|
||||
} else if let Ok(_encs) =
|
||||
DEFAULT_BYTE_MODE_ENCODING.encode(content, encoding::EncoderTrap::Strict)
|
||||
DEFAULT_BYTE_MODE_ENCODING.encode(content)
|
||||
{
|
||||
DEFAULT_BYTE_MODE_ENCODING
|
||||
} else {
|
||||
has_encoding_hint = true;
|
||||
encoding::all::UTF_8
|
||||
CharacterSetECI::UTF8
|
||||
};
|
||||
|
||||
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use
|
||||
@@ -144,9 +141,7 @@ pub fn encode_with_hints(
|
||||
|
||||
// Append ECI segment if applicable
|
||||
if mode == Mode::BYTE && has_encoding_hint {
|
||||
if let Some(eci) = CharacterSetECI::getCharacterSetECI(encoding) {
|
||||
appendECI(&eci, &mut header_bits)?;
|
||||
}
|
||||
appendECI(&encoding, &mut header_bits)?;
|
||||
}
|
||||
|
||||
// Append the FNC1 mode header for GS1 formatted data if applicable
|
||||
@@ -304,15 +299,15 @@ pub fn getAlphanumericCode(code: u32) -> i8 {
|
||||
}
|
||||
|
||||
pub fn chooseMode(content: &str) -> Mode {
|
||||
chooseModeWithEncoding(content, encoding::all::ISO_8859_1)
|
||||
chooseModeWithEncoding(content, CharacterSetECI::ISO8859_1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the best mode by examining the content. Note that 'encoding' is used as a hint;
|
||||
* if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.
|
||||
*/
|
||||
fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
|
||||
if SHIFT_JIS_CHARSET.name() == encoding.name() && isOnlyDoubleByteKanji(content) {
|
||||
fn chooseModeWithEncoding(content: &str, encoding: CharacterSetECI) -> Mode {
|
||||
if SHIFT_JIS_CHARSET == encoding && isOnlyDoubleByteKanji(content) {
|
||||
// Choose Kanji mode if all input are double-byte characters
|
||||
return Mode::KANJI;
|
||||
}
|
||||
@@ -337,7 +332,7 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
|
||||
}
|
||||
|
||||
pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
|
||||
let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET.encode(content, encoding::EncoderTrap::Strict) {
|
||||
let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET.encode(content) {
|
||||
byt
|
||||
} else {
|
||||
return false;
|
||||
@@ -638,7 +633,7 @@ pub fn appendBytes(
|
||||
content: &str,
|
||||
mode: Mode,
|
||||
bits: &mut BitArray,
|
||||
encoding: EncodingRef,
|
||||
encoding: CharacterSetECI,
|
||||
) -> Result<()> {
|
||||
match mode {
|
||||
Mode::NUMERIC => appendNumericBytes(content, bits),
|
||||
@@ -725,9 +720,9 @@ pub fn appendAlphanumericBytes(content: &str, bits: &mut BitArray) -> Result<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) -> Result<()> {
|
||||
pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: CharacterSetECI) -> Result<()> {
|
||||
let bytes = encoding
|
||||
.encode(content, encoding::EncoderTrap::Strict)
|
||||
.encode(content)
|
||||
.map_err(|e| Exceptions::writer_with(format!("error {e}")))?;
|
||||
for b in bytes {
|
||||
bits.appendBits(b as u32, 8)?;
|
||||
@@ -739,7 +734,7 @@ pub fn appendKanjiBytes(content: &str, bits: &mut BitArray) -> Result<()> {
|
||||
let sjis = &SHIFT_JIS_CHARSET;
|
||||
|
||||
let bytes = sjis
|
||||
.encode(content, encoding::EncoderTrap::Strict)
|
||||
.encode(content)
|
||||
.map_err(|e| Exceptions::writer_with(format!("error {e}")))?;
|
||||
if bytes.len() % 2 != 0 {
|
||||
return Err(Exceptions::writer_with("Kanji byte size not even"));
|
||||
|
||||
Reference in New Issue
Block a user