Merge pull request #22 from rxing-core/decouple-encoding-library

Decouple encoding library
This commit is contained in:
Henry A Schimke
2023-03-05 15:31:14 -08:00
committed by GitHub
35 changed files with 829 additions and 687 deletions

View File

@@ -3,6 +3,7 @@ use rxing::aztec::AztecReader;
use rxing::common::HybridBinarizer; use rxing::common::HybridBinarizer;
use rxing::datamatrix::DataMatrixReader; use rxing::datamatrix::DataMatrixReader;
use rxing::maxicode::MaxiCodeReader; use rxing::maxicode::MaxiCodeReader;
use rxing::multi::{GenericMultipleBarcodeReader, MultipleBarcodeReader};
use rxing::oned::rss::expanded::RSSExpandedReader; use rxing::oned::rss::expanded::RSSExpandedReader;
use rxing::oned::rss::RSS14Reader; use rxing::oned::rss::RSS14Reader;
use rxing::oned::{ use rxing::oned::{
@@ -11,10 +12,9 @@ use rxing::oned::{
}; };
use rxing::pdf417::PDF417Reader; use rxing::pdf417::PDF417Reader;
use rxing::qrcode::QRCodeReader; use rxing::qrcode::QRCodeReader;
use rxing::MultiFormatReader;
use rxing::{BinaryBitmap, BufferedImageLuminanceSource, Reader}; use rxing::{BinaryBitmap, BufferedImageLuminanceSource, Reader};
use std::path::Path; use std::path::Path;
use rxing::multi::{GenericMultipleBarcodeReader, MultipleBarcodeReader};
use rxing::MultiFormatReader;
fn get_image( fn get_image(
path: impl AsRef<Path>, path: impl AsRef<Path>,
@@ -188,7 +188,7 @@ fn upce_benchmark(c: &mut Criterion) {
fn multi_barcode_benchmark(c: &mut Criterion) { fn multi_barcode_benchmark(c: &mut Criterion) {
let mut image = get_image("test_resources/blackbox/multi-1/1.png"); let mut image = get_image("test_resources/blackbox/multi-1/1.png");
c.bench_function("multi_barcode", |b| { c.bench_function("multi_barcode", |b| {
b.iter( || { b.iter(|| {
let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default()); let mut reader = GenericMultipleBarcodeReader::new(MultiFormatReader::default());
let _res = reader.decode_multiple(&mut image); let _res = reader.decode_multiple(&mut image);
}); });

View File

@@ -16,8 +16,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use encoding::EncodingRef;
use crate::{ use crate::{
aztec::{ aztec::{
aztec_detector_result::AztecDetectorRXingResult, aztec_detector_result::AztecDetectorRXingResult,
@@ -25,6 +23,7 @@ use crate::{
encoder::HighLevelEncoder, encoder::HighLevelEncoder,
shared_test_methods::{stripSpace, toBitArray, toBooleanArray}, shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
}, },
common::CharacterSet,
BarcodeFormat, EncodeHintType, EncodeHintValue, Point, BarcodeFormat, EncodeHintType, EncodeHintValue, Point,
}; };
@@ -34,8 +33,6 @@ use crate::Writer;
use rand::Rng; use rand::Rng;
use encoding::Encoding;
/** /**
* Aztec 2D generator unit tests. * Aztec 2D generator unit tests.
* *
@@ -43,10 +40,10 @@ use encoding::Encoding;
* @author Frank Yellin * @author Frank Yellin
*/ */
const ISO_8859_1: EncodingRef = encoding::all::ISO_8859_1; //StandardCharsets.ISO_8859_1; const ISO_8859_1: CharacterSet = CharacterSet::ISO8859_1; //StandardCharsets.ISO_8859_1;
const UTF_8: EncodingRef = encoding::all::UTF_8; //StandardCharsets.UTF_8; const UTF_8: CharacterSet = CharacterSet::UTF8; //StandardCharsets.UTF_8;
const ISO_8859_15: EncodingRef = encoding::all::ISO_8859_15; //Charset.forName("ISO-8859-15"); const ISO_8859_15: CharacterSet = CharacterSet::ISO8859_15; //Charset.forName("ISO-8859-15");
const WINDOWS_1252: EncodingRef = encoding::all::WINDOWS_1252; //Charset.forName("Windows-1252"); const WINDOWS_1252: CharacterSet = CharacterSet::Cp1252; //Charset.forName("Windows-1252");
// const DOTX: &str = "[^.X]"; // const DOTX: &str = "[^.X]";
// const SPACES: &str = "\\s+"; // const SPACES: &str = "\\s+";
@@ -140,8 +137,9 @@ X X X X X X X X X X X X X
#[test] #[test]
fn testAztecWriter() { fn testAztecWriter() {
let shift_jis: EncodingRef = let shift_jis: CharacterSet =
encoding::label::encoding_from_whatwg_label("Shift_JIS").expect("must exist"); CharacterSet::get_character_set_by_name("Shift_JIS").expect("must exist");
testWriter("Espa\u{00F1}ol", None, 25, true, 1); // Without ECI (implicit ISO-8859-1) testWriter("Espa\u{00F1}ol", None, 25, true, 1); // Without ECI (implicit ISO-8859-1)
testWriter("Espa\u{00F1}ol", Some(ISO_8859_1), 25, true, 1); // Explicit ISO-8859-1 testWriter("Espa\u{00F1}ol", Some(ISO_8859_1), 25, true, 1); // Explicit ISO-8859-1
testWriter("\u{20AC} 1 sample data.", Some(WINDOWS_1252), 25, true, 2); // ISO-8859-1 can't encode Euro; Windows-1252 can testWriter("\u{20AC} 1 sample data.", Some(WINDOWS_1252), 25, true, 2); // ISO-8859-1 can't encode Euro; Windows-1252 can
@@ -150,7 +148,7 @@ fn testAztecWriter() {
testWriter("\u{20AC} 1 sample data.", Some(ISO_8859_15), 0, true, 2); testWriter("\u{20AC} 1 sample data.", Some(ISO_8859_15), 0, true, 2);
testWriter( testWriter(
"\u{20AC} 1 sample data.", "\u{20AC} 1 sample data.",
Some(encoding::all::UTF_16BE), Some(CharacterSet::UTF16BE),
0, 0,
true, true,
3, 3,
@@ -711,7 +709,7 @@ fn testEncodeDecode(data: &str, compact: bool, layers: u32) {
fn testWriter( fn testWriter(
data: &str, data: &str,
charset: Option<EncodingRef>, charset: Option<CharacterSet>,
ecc_percent: u32, ecc_percent: u32,
compact: bool, compact: bool,
layers: u32, layers: u32,
@@ -721,7 +719,7 @@ fn testWriter(
if charset.is_some() { if charset.is_some() {
hints.insert( hints.insert(
EncodeHintType::CHARACTER_SET, EncodeHintType::CHARACTER_SET,
EncodeHintValue::CharacterSet(charset.unwrap().name().to_owned()), EncodeHintValue::CharacterSet(charset.unwrap().get_charset_name().to_string()),
); );
} }
// if (null != charset) { // if (null != charset) {
@@ -737,7 +735,7 @@ fn testWriter(
let cset = match charset { let cset = match charset {
Some(cs) => cs, Some(cs) => cs,
None => encoding::all::ISO_8859_1, None => CharacterSet::ISO8859_1,
}; };
let aztec = aztec_encoder::encode_with_charset( let aztec = aztec_encoder::encode_with_charset(
data, data,
@@ -820,10 +818,10 @@ fn testStuffBits(wordSize: usize, bits: &str, expected: &str) {
fn testHighLevelEncodeStringUtf8(s: &str, expectedBits: &str) { fn testHighLevelEncodeStringUtf8(s: &str, expectedBits: &str) {
let bits = HighLevelEncoder::with_charset( let bits = HighLevelEncoder::with_charset(
encoding::all::UTF_8 CharacterSet::UTF8
.encode(s, encoding::EncoderTrap::Strict) .encode(s)
.expect("should encode to bytes"), .expect("should encode to bytes"),
encoding::all::UTF_8, CharacterSet::UTF8,
) )
.encode() .encode()
.expect("high level ok"); .expect("high level ok");
@@ -843,8 +841,8 @@ fn testHighLevelEncodeStringUtf8(s: &str, expectedBits: &str) {
fn testHighLevelEncodeString(s: &str, expectedBits: &str) { fn testHighLevelEncodeString(s: &str, expectedBits: &str) {
let bits = HighLevelEncoder::new( let bits = HighLevelEncoder::new(
encoding::all::ISO_8859_1 CharacterSet::ISO8859_1
.encode(s, encoding::EncoderTrap::Strict) .encode(s)
.expect("should encode to bytes"), .expect("should encode to bytes"),
) )
.encode() .encode()
@@ -864,8 +862,8 @@ fn testHighLevelEncodeString(s: &str, expectedBits: &str) {
fn testHighLevelEncodeStringCount(s: &str, expectedReceivedBits: u32) { fn testHighLevelEncodeStringCount(s: &str, expectedReceivedBits: u32) {
let bits = HighLevelEncoder::new( let bits = HighLevelEncoder::new(
encoding::all::ISO_8859_1 CharacterSet::ISO8859_1
.encode(s, encoding::EncoderTrap::Strict) .encode(s)
.expect("should encode to bytes"), .expect("should encode to bytes"),
) )
.encode() .encode()

View File

@@ -16,10 +16,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use encoding::EncodingRef;
use crate::{ use crate::{
common::{BitMatrix, Result}, common::{BitMatrix, CharacterSet, Result},
exceptions::Exceptions, exceptions::Exceptions,
BarcodeFormat, EncodeHintType, EncodeHintValue, Writer, BarcodeFormat, EncodeHintType, EncodeHintValue, Writer,
}; };
@@ -58,10 +56,7 @@ impl Writer for AztecWriter {
hints.get(&EncodeHintType::CHARACTER_SET) hints.get(&EncodeHintType::CHARACTER_SET)
{ {
if cset_name.to_lowercase() != "iso-8859-1" { if cset_name.to_lowercase() != "iso-8859-1" {
charset = Some( charset = CharacterSet::get_character_set_by_name(cset_name);
encoding::label::encoding_from_whatwg_label(cset_name)
.ok_or(Exceptions::ILLEGAL_ARGUMENT)?,
);
} }
} }
if let Some(EncodeHintValue::ErrorCorrection(ecc_level)) = if let Some(EncodeHintValue::ErrorCorrection(ecc_level)) =
@@ -91,7 +86,7 @@ fn encode(
format: BarcodeFormat, format: BarcodeFormat,
width: u32, width: u32,
height: u32, height: u32,
charset: Option<EncodingRef>, charset: Option<CharacterSet>,
ecc_percent: u32, ecc_percent: u32,
layers: i32, layers: i32,
) -> Result<BitMatrix> { ) -> Result<BitMatrix> {

View File

@@ -19,7 +19,7 @@ use crate::{
reedsolomon::{ reedsolomon::{
get_predefined_genericgf, GenericGFRef, PredefinedGenericGF, ReedSolomonDecoder, get_predefined_genericgf, GenericGFRef, PredefinedGenericGF, ReedSolomonDecoder,
}, },
BitMatrix, CharacterSetECI, DecoderRXingResult, DetectorRXingResult, Result, BitMatrix, CharacterSet, DecoderRXingResult, DetectorRXingResult, Eci, Result,
}, },
exceptions::Exceptions, exceptions::Exceptions,
}; };
@@ -113,8 +113,8 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
// Intermediary buffer of decoded bytes, which is decoded into a string and flushed // Intermediary buffer of decoded bytes, which is decoded into a string and flushed
// when character encoding changes (ECI) or input ends. // when character encoding changes (ECI) or input ends.
let mut decoded_bytes: Vec<u8> = Vec::new(); let mut decoded_bytes: Vec<u8> = Vec::new();
// let mut encdr: &'static dyn encoding::Encoding = encoding::all::UTF_8;
let mut encdr: encoding::EncodingRef = encoding::all::ISO_8859_1; let mut encdr: CharacterSet = CharacterSet::ISO8859_1;
let mut index = 0; let mut index = 0;
@@ -159,11 +159,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
let mut n = read_code(corrected_bits, index, 3); let mut n = read_code(corrected_bits, index, 3);
index += 3; index += 3;
// flush bytes, FLG changes state // flush bytes, FLG changes state
result.push_str( result.push_str(&encdr.decode(&decoded_bytes)?);
&encdr
.decode(&decoded_bytes, encoding::DecoderTrap::Strict)
.map_err(Exceptions::illegal_state_with)?,
);
decoded_bytes.clear(); decoded_bytes.clear();
match n { match n {
@@ -186,11 +182,11 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
eci = eci * 10 + (next_digit - 2); eci = eci * 10 + (next_digit - 2);
n -= 1; n -= 1;
} }
let charset_eci = CharacterSetECI::getCharacterSetECIByValue(eci); let charset_eci: Eci = eci.into();
if charset_eci.is_err() { if charset_eci == Eci::Unknown {
return Err(Exceptions::format_with("Charset must exist")); return Err(Exceptions::format_with("Charset must exist"));
} }
encdr = CharacterSetECI::getCharset(&charset_eci?); encdr = charset_eci.into();
} }
} }
// Go back to whatever mode we had been in // Go back to whatever mode we had been in
@@ -207,7 +203,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
} }
} else { } else {
// Though stored as a table of strings for convenience, codes actually represent 1 or 2 *bytes*. // Though stored as a table of strings for convenience, codes actually represent 1 or 2 *bytes*.
// let b = encoding::all::ASCII.encode(str, encoding::EncoderTrap::Strict).unwrap();
let b = str.as_bytes(); let b = str.as_bytes();
//let b = str.getBytes(StandardCharsets.US_ASCII); //let b = str.getBytes(StandardCharsets.US_ASCII);
//decodedBytes.write(b, 0, b.length); //decodedBytes.write(b, 0, b.length);
@@ -220,7 +216,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
} }
} }
//try { //try {
if let Ok(str) = encdr.decode(&decoded_bytes, encoding::DecoderTrap::Strict) { if let Ok(str) = encdr.decode(&decoded_bytes) {
result.push_str(&str); result.push_str(&str);
} else { } else {
return Err(Exceptions::illegal_state_with("bad encoding")); return Err(Exceptions::illegal_state_with("bad encoding"));

View File

@@ -14,14 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
use encoding::Encoding;
use crate::{ use crate::{
common::{ common::{
reedsolomon::{ reedsolomon::{
get_predefined_genericgf, GenericGFRef, PredefinedGenericGF, ReedSolomonEncoder, get_predefined_genericgf, GenericGFRef, PredefinedGenericGF, ReedSolomonEncoder,
}, },
BitArray, BitMatrix, Result, BitArray, BitMatrix, CharacterSet, Result,
}, },
exceptions::Exceptions, exceptions::Exceptions,
}; };
@@ -51,10 +49,9 @@ pub const WORD_SIZE: [u32; 33] = [
* @return Aztec symbol matrix with metadata * @return Aztec symbol matrix with metadata
*/ */
pub fn encode_simple(data: &str) -> Result<AztecCode> { pub fn encode_simple(data: &str) -> Result<AztecCode> {
let Ok(bytes) = encoding::all::ISO_8859_1 let Ok(bytes) =CharacterSet::ISO8859_1.encode_replace(data) else {
.encode(data, encoding::EncoderTrap::Replace) else { return Err(Exceptions::illegal_argument_with(format!("'{data}' cannot be encoded as ISO_8859_1")));
return Err(Exceptions::illegal_argument_with(format!("'{data}' cannot be encoded as ISO_8859_1"))); };
};
encode_bytes_simple(&bytes) encode_bytes_simple(&bytes)
} }
@@ -68,7 +65,7 @@ pub fn encode_simple(data: &str) -> Result<AztecCode> {
* @return Aztec symbol matrix with metadata * @return Aztec symbol matrix with metadata
*/ */
pub fn encode(data: &str, minECCPercent: u32, userSpecifiedLayers: i32) -> Result<AztecCode> { pub fn encode(data: &str, minECCPercent: u32, userSpecifiedLayers: i32) -> Result<AztecCode> {
if let Ok(bytes) = encoding::all::ISO_8859_1.encode(data, encoding::EncoderTrap::Strict) { if let Ok(bytes) = CharacterSet::ISO8859_1.encode(data) {
encode_bytes(&bytes, minECCPercent, userSpecifiedLayers) encode_bytes(&bytes, minECCPercent, userSpecifiedLayers)
} else { } else {
Err(Exceptions::illegal_argument_with(format!( Err(Exceptions::illegal_argument_with(format!(
@@ -93,9 +90,9 @@ pub fn encode_with_charset(
data: &str, data: &str,
minECCPercent: u32, minECCPercent: u32,
userSpecifiedLayers: i32, userSpecifiedLayers: i32,
charset: encoding::EncodingRef, charset: CharacterSet,
) -> Result<AztecCode> { ) -> Result<AztecCode> {
if let Ok(bytes) = charset.encode(data, encoding::EncoderTrap::Strict) { if let Ok(bytes) = charset.encode(data) {
encode_bytes_with_charset(&bytes, minECCPercent, userSpecifiedLayers, charset) encode_bytes_with_charset(&bytes, minECCPercent, userSpecifiedLayers, charset)
} else { } else {
Err(Exceptions::illegal_argument_with(format!( Err(Exceptions::illegal_argument_with(format!(
@@ -132,7 +129,7 @@ pub fn encode_bytes(
data, data,
minECCPercent, minECCPercent,
userSpecifiedLayers, userSpecifiedLayers,
encoding::all::ISO_8859_1, CharacterSet::ISO8859_1,
) )
} }
@@ -151,7 +148,7 @@ pub fn encode_bytes_with_charset(
data: &[u8], data: &[u8],
min_eccpercent: u32, min_eccpercent: u32,
user_specified_layers: i32, user_specified_layers: i32,
charset: encoding::EncodingRef, charset: CharacterSet,
) -> Result<AztecCode> { ) -> Result<AztecCode> {
// High-level encode // High-level encode
let bits = HighLevelEncoder::with_charset(data.into(), charset).encode()?; let bits = HighLevelEncoder::with_charset(data.into(), charset).encode()?;

View File

@@ -14,10 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::{ use crate::common::{BitArray, CharacterSet, Result};
common::{BitArray, CharacterSetECI, Result},
exceptions::Exceptions,
};
use super::{State, Token}; use super::{State, Token};
@@ -35,7 +32,7 @@ use super::{State, Token};
*/ */
pub struct HighLevelEncoder { pub struct HighLevelEncoder {
text: Vec<u8>, text: Vec<u8>,
charset: encoding::EncodingRef, charset: CharacterSet,
} }
impl HighLevelEncoder { impl HighLevelEncoder {
@@ -229,11 +226,11 @@ impl HighLevelEncoder {
pub fn new(text: Vec<u8>) -> Self { pub fn new(text: Vec<u8>) -> Self {
Self { Self {
text, text,
charset: encoding::all::ISO_8859_1, charset: CharacterSet::ISO8859_1,
} }
} }
pub fn with_charset(text: Vec<u8>, charset: encoding::EncodingRef) -> Self { pub fn with_charset(text: Vec<u8>, charset: CharacterSet) -> Self {
Self { text, charset } Self { text, charset }
} }
@@ -242,16 +239,16 @@ impl HighLevelEncoder {
*/ */
pub fn encode(&self) -> Result<BitArray> { pub fn encode(&self) -> Result<BitArray> {
let mut initial_state = State::new(Token::new(), Self::MODE_UPPER as u32, 0, 0); let mut initial_state = State::new(Token::new(), Self::MODE_UPPER as u32, 0, 0);
if let Some(eci) = CharacterSetECI::getCharacterSetECI(self.charset) { //if let Some(eci) = CharacterSetECI::getCharacterSetECI(self.charset) {
if eci != CharacterSetECI::ISO8859_1 { if self.charset != CharacterSet::ISO8859_1 {
//} && eci != CharacterSetECI::Cp1252 { //} && eci != CharacterSetECI::Cp1252 {
initial_state = initial_state.appendFLGn(CharacterSetECI::getValue(&eci))?; initial_state = initial_state.appendFLGn(self.charset.into())?;
}
} else {
return Err(Exceptions::illegal_argument_with(
"No ECI code for character set",
));
} }
// } else {
// return Err(Exceptions::illegal_argument_with(
// "No ECI code for character set",
// ));
// }
// if self.charset != null { // if self.charset != null {
// CharacterSetECI eci = CharacterSetECI.getCharacterSetECI(charset); // CharacterSetECI eci = CharacterSetECI.getCharacterSetECI(charset);
// if (null == eci) { // if (null == eci) {

View File

@@ -16,10 +16,8 @@
use std::fmt; use std::fmt;
use encoding::Encoding;
use crate::{ use crate::{
common::{BitArray, Result}, common::{BitArray, CharacterSet, Eci, Result},
exceptions::Exceptions, exceptions::Exceptions,
}; };
@@ -73,7 +71,7 @@ impl State {
self.bit_count self.bit_count
} }
pub fn appendFLGn(self, eci: u32) -> Result<Self> { pub fn appendFLGn(self, eci: Eci) -> Result<Self> {
let bit_count = self.bit_count; let bit_count = self.bit_count;
let mode = self.mode; let mode = self.mode;
let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); // 0: FLG(n) let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); // 0: FLG(n)
@@ -82,14 +80,14 @@ impl State {
/*if eci < 0 { /*if eci < 0 {
token.add(0, 3); // 0: FNC1 token.add(0, 3); // 0: FNC1
} else */ } else */
if eci > 999999 { if eci as u32 > 999999 {
return Err(Exceptions::illegal_argument_with( return Err(Exceptions::illegal_argument_with(
"ECI code must be between 0 and 999999", "ECI code must be between 0 and 999999",
)); ));
// throw new IllegalArgumentException("ECI code must be between 0 and 999999"); // throw new IllegalArgumentException("ECI code must be between 0 and 999999");
} else { } else {
let Ok(eci_digits) = encoding::all::ISO_8859_1 let Ok(eci_digits) = CharacterSet::ISO8859_1
.encode(&format!("{eci}"), encoding::EncoderTrap::Strict) .encode(&format!("{eci}"))
else { else {
return Err(Exceptions::ILLEGAL_ARGUMENT) return Err(Exceptions::ILLEGAL_ARGUMENT)
}; };

View File

@@ -20,7 +20,7 @@ use regex::Regex;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::RXingResult; use crate::{common::CharacterSet, RXingResult};
use uriparse::URI; use uriparse::URI;
@@ -404,10 +404,8 @@ fn maybeAppendFragment(fragmentBuffer: &mut Vec<u8>, charset: &str, result: &mut
if charset.is_empty() { if charset.is_empty() {
fragment = String::from_utf8(fragmentBytes).unwrap_or_else(|_| String::default()); fragment = String::from_utf8(fragmentBytes).unwrap_or_else(|_| String::default());
// fragment = new String(fragmentBytes, StandardCharsets.UTF_8); // fragment = new String(fragmentBytes, StandardCharsets.UTF_8);
} else if let Some(enc) = encoding::label::encoding_from_whatwg_label(charset) { } else if let Some(enc) = CharacterSet::get_character_set_by_name(charset) {
fragment = if let Ok(encoded_result) = fragment = if let Ok(encoded_result) = enc.decode(&fragmentBytes) {
enc.decode(&fragmentBytes, encoding::DecoderTrap::Strict)
{
encoded_result encoded_result
} else { } else {
String::from_utf8(fragmentBytes).unwrap_or_else(|_| String::default()) String::from_utf8(fragmentBytes).unwrap_or_else(|_| String::default())

View File

@@ -23,12 +23,13 @@
// import java.nio.charset.StandardCharsets; // import java.nio.charset.StandardCharsets;
// import java.util.Random; // import java.util.Random;
use encoding::{Encoding, EncodingRef};
use rand::Rng; use rand::Rng;
use std::collections::HashMap; use std::collections::HashMap;
use crate::common::StringUtils; use crate::common::StringUtils;
use super::CharacterSet;
#[test] #[test]
fn test_random() { fn test_random() {
let mut r = rand::thread_rng(); let mut r = rand::thread_rng();
@@ -38,27 +39,21 @@ fn test_random() {
// *byte = r.gen(); // *byte = r.gen();
// } // }
assert_eq!( assert_eq!(
encoding::all::UTF_8.name(), CharacterSet::UTF8,
StringUtils::guessCharset(&bytes, &HashMap::new()) StringUtils::guessCharset(&bytes, &HashMap::new()).unwrap()
.unwrap()
.name()
); );
} }
#[test] #[test]
fn test_short_shift_jis1() { fn test_short_shift_jis1() {
// 金魚 // 金魚
do_test( do_test(&[0x8b, 0xe0, 0x8b, 0x9b], CharacterSet::Shift_JIS, "SJIS");
&[0x8b, 0xe0, 0x8b, 0x9b],
encoding::label::encoding_from_whatwg_label("SJIS").unwrap(),
"SJIS",
);
} }
#[test] #[test]
fn test_short_iso885911() { fn test_short_iso885911() {
// båd // båd
do_test(&[0x62, 0xe5, 0x64], encoding::all::ISO_8859_1, "ISO8859_1"); do_test(&[0x62, 0xe5, 0x64], CharacterSet::ISO8859_1, "ISO8859_1");
} }
#[test] #[test]
@@ -66,7 +61,7 @@ fn test_short_utf8() {
// Español // Español
do_test( do_test(
&[0x45, 0x73, 0x70, 0x61, 0xc3, 0xb1, 0x6f, 0x6c], &[0x45, 0x73, 0x70, 0x61, 0xc3, 0xb1, 0x6f, 0x6c],
encoding::all::UTF_8, CharacterSet::UTF8,
"UTF8", "UTF8",
); );
} }
@@ -76,7 +71,7 @@ fn test_mixed_shift_jis1() {
// Hello 金! // Hello 金!
do_test( do_test(
&[0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x8b, 0xe0, 0x21], &[0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x8b, 0xe0, 0x21],
encoding::label::encoding_from_whatwg_label("SJIS").unwrap(), CharacterSet::Shift_JIS,
"SJIS", "SJIS",
); );
} }
@@ -86,8 +81,8 @@ fn test_utf16_be() {
// 调压柜 // 调压柜
do_test( do_test(
&[0xFE, 0xFF, 0x8c, 0x03, 0x53, 0x8b, 0x67, 0xdc], &[0xFE, 0xFF, 0x8c, 0x03, 0x53, 0x8b, 0x67, 0xdc],
encoding::all::UTF_16BE, CharacterSet::UTF16BE,
encoding::all::UTF_16BE.name(), CharacterSet::UTF16BE.get_charset_name(),
); );
} }
@@ -96,15 +91,15 @@ fn test_utf16_le() {
// 调压柜 // 调压柜
do_test( do_test(
&[0xFF, 0xFE, 0x03, 0x8c, 0x8b, 0x53, 0xdc, 0x67], &[0xFF, 0xFE, 0x03, 0x8c, 0x8b, 0x53, 0xdc, 0x67],
encoding::all::UTF_16LE, CharacterSet::UTF16LE,
encoding::all::UTF_16LE.name(), CharacterSet::UTF16LE.get_charset_name(),
); );
} }
fn do_test(bytes: &[u8], charset: EncodingRef, encoding: &str) { fn do_test(bytes: &[u8], charset: CharacterSet, encoding: &str) {
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()).unwrap(); let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()).unwrap();
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()).unwrap(); let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()).unwrap();
assert_eq!(charset.name(), guessedCharset.name()); assert_eq!(charset, guessedCharset);
assert_eq!(encoding, guessedEncoding); assert_eq!(encoding, guessedEncoding);
} }

351
src/common/character_set.rs Normal file
View File

@@ -0,0 +1,351 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use encoding::EncodingRef;
use crate::common::Result;
use crate::Exceptions;
/**
* Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
* of ISO 18004.
*
* @author Sean Owen
*/
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CharacterSet {
// Enum name is a Java encoding valid for java.lang and java.io
Cp437, //(new int[]{0,2}),
ISO8859_1, //(new int[]{1,3}, "ISO-8859-1"),
ISO8859_2, //(4, "ISO-8859-2"),
ISO8859_3, //(5, "ISO-8859-3"),
ISO8859_4, //(6, "ISO-8859-4"),
ISO8859_5, //(7, "ISO-8859-5"),
// ISO8859_6, //(8, "ISO-8859-6"),
ISO8859_7, //(9, "ISO-8859-7"),
// ISO8859_8, //(10, "ISO-8859-8"),
ISO8859_9, //(11, "ISO-8859-9"),
// ISO8859_10, //(12, "ISO-8859-10"),
// ISO8859_11, //(13, "ISO-8859-11"),
ISO8859_13, //(15, "ISO-8859-13"),
// ISO8859_14, //(16, "ISO-8859-14"),
ISO8859_15, //(17, "ISO-8859-15"),
ISO8859_16, //(18, "ISO-8859-16"),
Shift_JIS, //(20, "Shift_JIS"),
Cp1250, //(21, "windows-1250"),
Cp1251, //(22, "windows-1251"),
Cp1252, //(23, "windows-1252"),
Cp1256, //(24, "windows-1256"),
UTF16BE, //(25, "UTF-16BE", "UnicodeBig"),
UTF8, //(26, "UTF-8"),
ASCII, //(new int[] {27, 170}, "US-ASCII"),
Big5, //(28),
GB2312,
GB18030, //(29, "GB2312", "EUC_CN", "GBK"),
EUC_KR, //(30, "EUC-KR");
UTF16LE,
UTF32BE,
UTF32LE,
Binary,
Unknown,
}
impl CharacterSet {
// pub fn get_eci_value(&self) -> u32 {
// match self {
// CharacterSet::Cp437 => 0,
// CharacterSet::ISO8859_1 => 1,
// CharacterSet::ISO8859_2 => 4,
// CharacterSet::ISO8859_3 => 5,
// CharacterSet::ISO8859_4 => 6,
// CharacterSet::ISO8859_5 => 7,
// // CharacterSetECI::ISO8859_6 => 8,
// CharacterSet::ISO8859_7 => 9,
// // CharacterSetECI::ISO8859_8 => 10,
// CharacterSet::ISO8859_9 => 11,
// // CharacterSetECI::ISO8859_10 => 12,
// // CharacterSetECI::ISO8859_11 => 13,
// CharacterSet::ISO8859_13 => 15,
// // CharacterSetECI::ISO8859_14 => 16,
// CharacterSet::ISO8859_15 => 17,
// CharacterSet::ISO8859_16 => 18,
// CharacterSet::Shift_JIS => 20,
// CharacterSet::Cp1250 => 21,
// CharacterSet::Cp1251 => 22,
// CharacterSet::Cp1252 => 23,
// CharacterSet::Cp1256 => 24,
// CharacterSet::UTF16BE => 25,
// CharacterSet::UTF8 => 26,
// CharacterSet::ASCII => 27,
// CharacterSet::Big5 => 28,
// CharacterSet::GB2312 => 29,
// CharacterSet::GB18030 => 32,
// CharacterSet::EUC_KR => 30,
// CharacterSet::UTF16LE => 33,
// CharacterSet::UTF32BE => 34,
// CharacterSet::UTF32LE => 35,
// CharacterSet::Binary => 899,
// _=>1000,
// }
// }
fn get_base_encoder(&self) -> EncodingRef {
let name = match self {
CharacterSet::Cp437 => "cp437",
CharacterSet::ISO8859_1 => return encoding::all::ISO_8859_1,
CharacterSet::ISO8859_2 => "ISO-8859-2",
CharacterSet::ISO8859_3 => "ISO-8859-3",
CharacterSet::ISO8859_4 => "ISO-8859-4",
CharacterSet::ISO8859_5 => "ISO-8859-5",
// CharacterSet::ISO8859_6 => "ISO-8859-6",
CharacterSet::ISO8859_7 => "ISO-8859-7",
// CharacterSet::ISO8859_8 => "ISO-8859-8",
CharacterSet::ISO8859_9 => "ISO-8859-9",
// CharacterSet::ISO8859_10 => "ISO-8859-10",
// CharacterSet::ISO8859_11 => "ISO-8859-11",
CharacterSet::ISO8859_13 => "ISO-8859-13",
// CharacterSet::ISO8859_14 => "ISO-8859-14",
CharacterSet::ISO8859_15 => "ISO-8859-15",
CharacterSet::ISO8859_16 => "ISO-8859-16",
CharacterSet::Shift_JIS => "shift_jis",
CharacterSet::Cp1250 => "windows-1250",
CharacterSet::Cp1251 => "windows-1251",
CharacterSet::Cp1252 => "windows-1252",
CharacterSet::Cp1256 => "windows-1256",
CharacterSet::UTF16BE => "UTF-16BE",
CharacterSet::UTF16LE => "UTF-16LE",
CharacterSet::UTF8 => "UTF-8",
CharacterSet::ASCII => "US-ASCII",
CharacterSet::Big5 => "Big5",
CharacterSet::GB18030 => "GB18030",
CharacterSet::GB2312 => "GB2312",
CharacterSet::EUC_KR => "EUC-KR",
CharacterSet::UTF32BE => "utf-32be",
CharacterSet::UTF32LE => "utf-32le",
CharacterSet::Binary => "binary",
CharacterSet::Unknown => "unknown",
};
encoding::label::encoding_from_whatwg_label(name).unwrap()
}
pub fn get_charset_name(&self) -> &'static str {
match self {
CharacterSet::Cp437 => "cp437",
CharacterSet::ISO8859_1 => "iso-8859-1",
CharacterSet::ISO8859_2 => "iso-8859-2",
CharacterSet::ISO8859_3 => "iso-8859-3",
CharacterSet::ISO8859_4 => "iso-8859-4",
CharacterSet::ISO8859_5 => "iso-8859-5",
// CharacterSet::ISO8859_6 => "ISO-8859-6",
CharacterSet::ISO8859_7 => "iso-8859-7",
// CharacterSet::ISO8859_8 => "ISO-8859-8",
CharacterSet::ISO8859_9 => "iso-8859-9",
// CharacterSet::ISO8859_10 => "ISO-8859-10",
// CharacterSet::ISO8859_11 => "ISO-8859-11",
CharacterSet::ISO8859_13 => "iso-8859-13",
// CharacterSet::ISO8859_14 => "ISO-8859-14",
CharacterSet::ISO8859_15 => "iso-8859-15",
CharacterSet::ISO8859_16 => "iso-8859-16",
CharacterSet::Shift_JIS => "shift_jis",
CharacterSet::Cp1250 => "windows-1250",
CharacterSet::Cp1251 => "windows-1251",
CharacterSet::Cp1252 => "windows-1252",
CharacterSet::Cp1256 => "windows-1256",
CharacterSet::UTF16BE => "utf-16be",
CharacterSet::UTF16LE => "utf-16le",
CharacterSet::UTF8 => "utf-8",
CharacterSet::ASCII => "us-ascii",
CharacterSet::Big5 => "big5",
CharacterSet::GB18030 => "gb18030",
CharacterSet::GB2312 => "gb2312",
CharacterSet::EUC_KR => "euc-kr",
CharacterSet::UTF32BE => "utf-32be",
CharacterSet::UTF32LE => "utf-32le",
CharacterSet::Binary => "binary",
CharacterSet::Unknown => "unknown",
}
}
// /**
// * @param charset Java character set object
// * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
// * but unsupported
// */
// fn get_character_set_eci(charset: EncodingRef) -> Option<CharacterSetECI> {
// let name = if let Some(nm) = charset.whatwg_name() {
// nm
// } else {
// charset.name()
// };
// match name {
// "cp437" => Some(CharacterSetECI::Cp437),
// "iso-8859-1" => Some(CharacterSetECI::ISO8859_1),
// "iso-8859-2" => Some(CharacterSetECI::ISO8859_2),
// "iso-8859-3" => Some(CharacterSetECI::ISO8859_3),
// "iso-8859-4" => Some(CharacterSetECI::ISO8859_4),
// "iso-8859-5" => Some(CharacterSetECI::ISO8859_5),
// // "iso-8859-6" => Some(CharacterSetECI::ISO8859_6),
// "iso-8859-7" => Some(CharacterSetECI::ISO8859_7),
// // "iso-8859-8" => Some(CharacterSetECI::ISO8859_8),
// "iso-8859-9" => Some(CharacterSetECI::ISO8859_9),
// // "iso-8859-10" => Some(CharacterSetECI::ISO8859_10),
// // "iso-8859-11" => Some(CharacterSetECI::ISO8859_11),
// "iso-8859-13" => Some(CharacterSetECI::ISO8859_13),
// // "iso-8859-14" => Some(CharacterSetECI::ISO8859_14),
// "iso-8859-15" => Some(CharacterSetECI::ISO8859_15),
// "iso-8859-16" => Some(CharacterSetECI::ISO8859_16),
// "shift_jis" => Some(CharacterSetECI::SJIS),
// "windows-1250" => Some(CharacterSetECI::Cp1250),
// "windows-1251" => Some(CharacterSetECI::Cp1251),
// "windows-1252" => Some(CharacterSetECI::Cp1252),
// "windows-1256" => Some(CharacterSetECI::Cp1256),
// "utf-16be" => Some(CharacterSetECI::UnicodeBigUnmarked),
// "utf-8" | "utf8" => Some(CharacterSetECI::UTF8),
// "us-ascii" => Some(CharacterSetECI::ASCII),
// "big5" => Some(CharacterSetECI::Big5),
// "gb2312" => Some(CharacterSetECI::GB18030),
// "euc-kr" => Some(CharacterSetECI::EUC_KR),
// _ => None,
// }
// }
// /**
// * @param value character set ECI value
// * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but
// * unsupported
// * @throws FormatException if ECI value is invalid
// */
// pub fn get_character_set_by_eci(value: u32) -> Result<CharacterSet> {
// match value {
// 0 | 2 => Ok(CharacterSet::Cp437),
// 1 | 3 => Ok(CharacterSet::ISO8859_1),
// 4 => Ok(CharacterSet::ISO8859_2),
// 5 => Ok(CharacterSet::ISO8859_3),
// 6 => Ok(CharacterSet::ISO8859_4),
// 7 => Ok(CharacterSet::ISO8859_5),
// // 8 => Ok(CharacterSetECI::ISO8859_6),
// 9 => Ok(CharacterSet::ISO8859_7),
// // 10 => Ok(CharacterSetECI::ISO8859_8),
// 11 => Ok(CharacterSet::ISO8859_9),
// // 12 => Ok(CharacterSetECI::ISO8859_10),
// // 13 => Ok(CharacterSetECI::ISO8859_11),
// 15 => Ok(CharacterSet::ISO8859_13),
// // 16 => Ok(CharacterSetECI::ISO8859_14),
// 17 => Ok(CharacterSet::ISO8859_15),
// 18 => Ok(CharacterSet::ISO8859_16),
// 20 => Ok(CharacterSet::Shift_JIS),
// 21 => Ok(CharacterSet::Cp1250),
// 22 => Ok(CharacterSet::Cp1251),
// 23 => Ok(CharacterSet::Cp1252),
// 24 => Ok(CharacterSet::Cp1256),
// 25 => Ok(CharacterSet::UTF16BE),
// 26 => Ok(CharacterSet::UTF8),
// 27 => Ok(CharacterSet::ASCII),
// 28 => Ok(CharacterSet::Big5),
// 32 => Ok(CharacterSet::GB18030),
// 29 => Ok(CharacterSet::GB2312),
// 30 => Ok(CharacterSet::EUC_KR),
// 33 => Ok(CharacterSet::UTF16LE),
// 34 => Ok(CharacterSet::UTF32BE),
// 35 => Ok(CharacterSet::UTF32LE),
// 899 => Ok(CharacterSet::Binary),
// _ => Err(Exceptions::not_found_with("Bad ECI Value")),
// }
// }
/**
* @param name character set ECI encoding name
* @return CharacterSetECI representing ECI for character encoding, or null if it is legal
* but unsupported
*/
pub fn get_character_set_by_name(name: &str) -> Option<CharacterSet> {
match name.to_lowercase().as_str() {
"cp437" => Some(CharacterSet::Cp437),
"iso-8859-1" => Some(CharacterSet::ISO8859_1),
"iso-8859-2" => Some(CharacterSet::ISO8859_2),
"iso-8859-3" => Some(CharacterSet::ISO8859_3),
"iso-8859-4" => Some(CharacterSet::ISO8859_4),
"iso-8859-5" => Some(CharacterSet::ISO8859_5),
// "iso-8859-6" => Some(CharacterSet::ISO8859_6),
"iso-8859-7" => Some(CharacterSet::ISO8859_7),
// "iso-8859-8" => Some(CharacterSet::ISO8859_8),
"iso-8859-9" => Some(CharacterSet::ISO8859_9),
// "ISO-8859-10" => Some(CharacterSet::ISO8859_10),
// "ISO-8859-11" => Some(CharacterSet::ISO8859_11),
"iso-8859-13" => Some(CharacterSet::ISO8859_13),
// "ISO-8859-14" => Some(CharacterSet::ISO8859_14),
"iso-8859-15" => Some(CharacterSet::ISO8859_15),
"iso-8859-16" => Some(CharacterSet::ISO8859_16),
"shift_jis" => Some(CharacterSet::Shift_JIS),
"windows-1250" => Some(CharacterSet::Cp1250),
"windows-1251" => Some(CharacterSet::Cp1251),
"windows-1252" => Some(CharacterSet::Cp1252),
"windows-1256" => Some(CharacterSet::Cp1256),
"utf-16be" => Some(CharacterSet::UTF16BE),
"utf-8" | "utf8" => Some(CharacterSet::UTF8),
"us-ascii" => Some(CharacterSet::ASCII),
"big5" => Some(CharacterSet::Big5),
"gb2312" => Some(CharacterSet::GB2312),
"gb18030" => Some(CharacterSet::GB18030),
"euc-kr" => Some(CharacterSet::EUC_KR),
"utf-32be" => Some(CharacterSet::UTF32BE),
"utf-32le" => Some(CharacterSet::UTF32LE),
"binary" => Some(CharacterSet::Binary),
"unknown" => Some(CharacterSet::Unknown),
_ => None,
}
}
pub fn encode(&self, input: &str) -> Result<Vec<u8>> {
if self == &CharacterSet::Cp437 {
use codepage_437::ToCp437;
use codepage_437::CP437_CONTROL;
input
.to_cp437(&CP437_CONTROL)
.map(|data| data.to_vec())
.map_err(|e| Exceptions::format_with(format!("{e:?}")))
} else {
self.get_base_encoder()
.encode(input, encoding::EncoderTrap::Strict)
.map_err(|e| Exceptions::format_with(e.to_string()))
}
}
pub fn encode_replace(&self, input: &str) -> Result<Vec<u8>> {
self.get_base_encoder()
.encode(input, encoding::EncoderTrap::Replace)
.map_err(|e| Exceptions::format_with(e.to_string()))
}
pub fn decode(&self, input: &[u8]) -> Result<String> {
if self == &CharacterSet::Cp437 {
use codepage_437::BorrowFromCp437;
use codepage_437::CP437_CONTROL;
Ok(String::borrow_from_cp437(&input, &CP437_CONTROL))
} else {
self.get_base_encoder()
.decode(input, encoding::DecoderTrap::Strict)
.map_err(|e| Exceptions::format_with(e.to_string()))
}
}
pub fn decode_replace(&self, input: &[u8]) -> Result<String> {
self.get_base_encoder()
.decode(input, encoding::DecoderTrap::Replace)
.map_err(|e| Exceptions::format_with(e.to_string()))
}
}

View File

@@ -1,289 +0,0 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com.google.zxing.common;
// import com.google.zxing.FormatException;
// import java.nio.charset.Charset;
// import java.util.HashMap;
// import java.util.Map;
use encoding::EncodingRef;
use crate::common::Result;
use crate::Exceptions;
/**
* Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
* of ISO 18004.
*
* @author Sean Owen
*/
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CharacterSetECI {
// Enum name is a Java encoding valid for java.lang and java.io
Cp437, //(new int[]{0,2}),
ISO8859_1, //(new int[]{1,3}, "ISO-8859-1"),
ISO8859_2, //(4, "ISO-8859-2"),
ISO8859_3, //(5, "ISO-8859-3"),
ISO8859_4, //(6, "ISO-8859-4"),
ISO8859_5, //(7, "ISO-8859-5"),
//ISO8859_6, //(8, "ISO-8859-6"),
ISO8859_7, //(9, "ISO-8859-7"),
//ISO8859_8, //(10, "ISO-8859-8"),
ISO8859_9, //(11, "ISO-8859-9"),
// ISO8859_10, //(12, "ISO-8859-10"),
// ISO8859_11, //(13, "ISO-8859-11"),
ISO8859_13, //(15, "ISO-8859-13"),
// ISO8859_14, //(16, "ISO-8859-14"),
ISO8859_15, //(17, "ISO-8859-15"),
ISO8859_16, //(18, "ISO-8859-16"),
SJIS, //(20, "Shift_JIS"),
Cp1250, //(21, "windows-1250"),
Cp1251, //(22, "windows-1251"),
Cp1252, //(23, "windows-1252"),
Cp1256, //(24, "windows-1256"),
UnicodeBigUnmarked, //(25, "UTF-16BE", "UnicodeBig"),
UTF8, //(26, "UTF-8"),
ASCII, //(new int[] {27, 170}, "US-ASCII"),
Big5, //(28),
GB18030, //(29, "GB2312", "EUC_CN", "GBK"),
EUC_KR, //(30, "EUC-KR");
}
impl CharacterSetECI {
// private static final Map<Integer,CharacterSetECI> VALUE_TO_ECI = new HashMap<>();
// private static final Map<String,CharacterSetECI> NAME_TO_ECI = new HashMap<>();
// static {
// for (CharacterSetECI eci : values()) {
// for (int value : eci.values) {
// VALUE_TO_ECI.put(value, eci);
// }
// NAME_TO_ECI.put(eci.name(), eci);
// for (String name : eci.otherEncodingNames) {
// NAME_TO_ECI.put(name, eci);
// }
// }
// }
// private final int[] values;
// private final String[] otherEncodingNames;
// CharacterSetECI(int value) {
// this(new int[] {value});
// }
// CharacterSetECI(int value, String... otherEncodingNames) {
// this.values = new int[] {value};
// this.otherEncodingNames = otherEncodingNames;
// }
// CharacterSetECI(int[] values, String... otherEncodingNames) {
// this.values = values;
// this.otherEncodingNames = otherEncodingNames;
// }
pub fn getValueSelf(&self) -> u32 {
Self::getValue(self)
}
pub fn getValue(cs_eci: &CharacterSetECI) -> u32 {
match cs_eci {
CharacterSetECI::Cp437 => 0,
CharacterSetECI::ISO8859_1 => 1,
CharacterSetECI::ISO8859_2 => 4,
CharacterSetECI::ISO8859_3 => 5,
CharacterSetECI::ISO8859_4 => 6,
CharacterSetECI::ISO8859_5 => 7,
// CharacterSetECI::ISO8859_6 => 8,
CharacterSetECI::ISO8859_7 => 9,
// CharacterSetECI::ISO8859_8 => 10,
CharacterSetECI::ISO8859_9 => 11,
// CharacterSetECI::ISO8859_10 => 12,
// CharacterSetECI::ISO8859_11 => 13,
CharacterSetECI::ISO8859_13 => 15,
// CharacterSetECI::ISO8859_14 => 16,
CharacterSetECI::ISO8859_15 => 17,
CharacterSetECI::ISO8859_16 => 18,
CharacterSetECI::SJIS => 20,
CharacterSetECI::Cp1250 => 21,
CharacterSetECI::Cp1251 => 22,
CharacterSetECI::Cp1252 => 23,
CharacterSetECI::Cp1256 => 24,
CharacterSetECI::UnicodeBigUnmarked => 25,
CharacterSetECI::UTF8 => 26,
CharacterSetECI::ASCII => 27,
CharacterSetECI::Big5 => 28,
CharacterSetECI::GB18030 => 29,
CharacterSetECI::EUC_KR => 30,
}
}
pub fn getCharset(cs_eci: &CharacterSetECI) -> EncodingRef {
let name = match cs_eci {
// CharacterSetECI::Cp437 => "CP437",
CharacterSetECI::Cp437 => "UTF-8",
CharacterSetECI::ISO8859_1 => "ISO-8859-1",
CharacterSetECI::ISO8859_2 => "ISO-8859-2",
CharacterSetECI::ISO8859_3 => "ISO-8859-3",
CharacterSetECI::ISO8859_4 => "ISO-8859-4",
CharacterSetECI::ISO8859_5 => "ISO-8859-5",
// CharacterSetECI::ISO8859_6 => "ISO-8859-6",
CharacterSetECI::ISO8859_7 => "ISO-8859-7",
// CharacterSetECI::ISO8859_8 => "ISO-8859-8",
CharacterSetECI::ISO8859_9 => "ISO-8859-9",
// CharacterSetECI::ISO8859_10 => "ISO-8859-10",
// CharacterSetECI::ISO8859_11 => "ISO-8859-11",
CharacterSetECI::ISO8859_13 => "ISO-8859-13",
// CharacterSetECI::ISO8859_14 => "ISO-8859-14",
CharacterSetECI::ISO8859_15 => "ISO-8859-15",
CharacterSetECI::ISO8859_16 => "ISO-8859-16",
CharacterSetECI::SJIS => "Shift_JIS",
CharacterSetECI::Cp1250 => "windows-1250",
CharacterSetECI::Cp1251 => "windows-1251",
CharacterSetECI::Cp1252 => "windows-1252",
CharacterSetECI::Cp1256 => "windows-1256",
CharacterSetECI::UnicodeBigUnmarked => "UTF-16BE",
CharacterSetECI::UTF8 => "UTF-8",
CharacterSetECI::ASCII => "US-ASCII",
CharacterSetECI::Big5 => "Big5",
CharacterSetECI::GB18030 => "GB2312",
CharacterSetECI::EUC_KR => "EUC-KR",
};
encoding::label::encoding_from_whatwg_label(name).unwrap()
}
/**
* @param charset Java character set object
* @return CharacterSetECI representing ECI for character encoding, or null if it is legal
* but unsupported
*/
pub fn getCharacterSetECI(charset: EncodingRef) -> Option<CharacterSetECI> {
let name = if let Some(nm) = charset.whatwg_name() {
nm
} else {
charset.name()
};
match name {
"CP437" => Some(CharacterSetECI::Cp437),
"iso-8859-1" => Some(CharacterSetECI::ISO8859_1),
"iso-8859-2" => Some(CharacterSetECI::ISO8859_2),
"iso-8859-3" => Some(CharacterSetECI::ISO8859_3),
"iso-8859-4" => Some(CharacterSetECI::ISO8859_4),
"iso-8859-5" => Some(CharacterSetECI::ISO8859_5),
// "iso-8859-6" => Some(CharacterSetECI::ISO8859_6),
"iso-8859-7" => Some(CharacterSetECI::ISO8859_7),
// "iso-8859-8" => Some(CharacterSetECI::ISO8859_8),
"iso-8859-9" => Some(CharacterSetECI::ISO8859_9),
// "iso-8859-10" => Some(CharacterSetECI::ISO8859_10),
// "iso-8859-11" => Some(CharacterSetECI::ISO8859_11),
"iso-8859-13" => Some(CharacterSetECI::ISO8859_13),
// "iso-8859-14" => Some(CharacterSetECI::ISO8859_14),
"iso-8859-15" => Some(CharacterSetECI::ISO8859_15),
"iso-8859-16" => Some(CharacterSetECI::ISO8859_16),
"shift_jis" => Some(CharacterSetECI::SJIS),
"windows-1250" => Some(CharacterSetECI::Cp1250),
"windows-1251" => Some(CharacterSetECI::Cp1251),
"windows-1252" => Some(CharacterSetECI::Cp1252),
"windows-1256" => Some(CharacterSetECI::Cp1256),
"utf-16be" => Some(CharacterSetECI::UnicodeBigUnmarked),
"utf-8" => Some(CharacterSetECI::UTF8),
"us-ascii" => Some(CharacterSetECI::ASCII),
"big5" => Some(CharacterSetECI::Big5),
"gb2312" => Some(CharacterSetECI::GB18030),
"euc-kr" => Some(CharacterSetECI::EUC_KR),
_ => None,
}
}
/**
* @param value character set ECI value
* @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but
* unsupported
* @throws FormatException if ECI value is invalid
*/
pub fn getCharacterSetECIByValue(value: u32) -> Result<CharacterSetECI> {
match value {
0 | 2 => Ok(CharacterSetECI::Cp437),
1 | 3 => Ok(CharacterSetECI::ISO8859_1),
4 => Ok(CharacterSetECI::ISO8859_2),
5 => Ok(CharacterSetECI::ISO8859_3),
6 => Ok(CharacterSetECI::ISO8859_4),
7 => Ok(CharacterSetECI::ISO8859_5),
// 8 => Ok(CharacterSetECI::ISO8859_6),
9 => Ok(CharacterSetECI::ISO8859_7),
// 10 => Ok(CharacterSetECI::ISO8859_8),
11 => Ok(CharacterSetECI::ISO8859_9),
// 12 => Ok(CharacterSetECI::ISO8859_10),
// 13 => Ok(CharacterSetECI::ISO8859_11),
15 => Ok(CharacterSetECI::ISO8859_13),
// 16 => Ok(CharacterSetECI::ISO8859_14),
17 => Ok(CharacterSetECI::ISO8859_15),
18 => Ok(CharacterSetECI::ISO8859_16),
20 => Ok(CharacterSetECI::SJIS),
21 => Ok(CharacterSetECI::Cp1250),
22 => Ok(CharacterSetECI::Cp1251),
23 => Ok(CharacterSetECI::Cp1252),
24 => Ok(CharacterSetECI::Cp1256),
25 => Ok(CharacterSetECI::UnicodeBigUnmarked),
26 => Ok(CharacterSetECI::UTF8),
27 | 170 => Ok(CharacterSetECI::ASCII),
28 => Ok(CharacterSetECI::Big5),
29 => Ok(CharacterSetECI::GB18030),
30 => Ok(CharacterSetECI::EUC_KR),
_ => Err(Exceptions::not_found_with("Bad ECI Value")),
}
}
/**
* @param name character set ECI encoding name
* @return CharacterSetECI representing ECI for character encoding, or null if it is legal
* but unsupported
*/
pub fn getCharacterSetECIByName(name: &str) -> Option<CharacterSetECI> {
match name {
"CP437" => Some(CharacterSetECI::Cp437),
"ISO-8859-1" => Some(CharacterSetECI::ISO8859_1),
"ISO-8859-2" => Some(CharacterSetECI::ISO8859_2),
"ISO-8859-3" => Some(CharacterSetECI::ISO8859_3),
"ISO-8859-4" => Some(CharacterSetECI::ISO8859_4),
"ISO-8859-5" => Some(CharacterSetECI::ISO8859_5),
// "ISO-8859-6" => Some(CharacterSetECI::ISO8859_6),
"ISO-8859-7" => Some(CharacterSetECI::ISO8859_7),
// "ISO-8859-8" => Some(CharacterSetECI::ISO8859_8),
"ISO-8859-9" => Some(CharacterSetECI::ISO8859_9),
// "ISO-8859-10" => Some(CharacterSetECI::ISO8859_10),
// "ISO-8859-11" => Some(CharacterSetECI::ISO8859_11),
"ISO-8859-13" => Some(CharacterSetECI::ISO8859_13),
// "ISO-8859-14" => Some(CharacterSetECI::ISO8859_14),
"ISO-8859-15" => Some(CharacterSetECI::ISO8859_15),
"ISO-8859-16" => Some(CharacterSetECI::ISO8859_16),
"Shift_JIS" => Some(CharacterSetECI::SJIS),
"windows-1250" => Some(CharacterSetECI::Cp1250),
"windows-1251" => Some(CharacterSetECI::Cp1251),
"windows-1252" => Some(CharacterSetECI::Cp1252),
"windows-1256" => Some(CharacterSetECI::Cp1256),
"UTF-16BE" => Some(CharacterSetECI::UnicodeBigUnmarked),
"UTF-8" => Some(CharacterSetECI::UTF8),
"US-ASCII" => Some(CharacterSetECI::ASCII),
"Big5" => Some(CharacterSetECI::Big5),
"GB2312" => Some(CharacterSetECI::GB18030),
"EUC-KR" => Some(CharacterSetECI::EUC_KR),
_ => None,
}
}
}

181
src/common/eci.rs Normal file
View File

@@ -0,0 +1,181 @@
use std::fmt::Display;
use super::CharacterSet;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Eci {
Unknown = -1,
Cp437 = 2, // obsolete
ISO8859_1 = 3,
ISO8859_2 = 4,
ISO8859_3 = 5,
ISO8859_4 = 6,
ISO8859_5 = 7,
ISO8859_6 = 8,
ISO8859_7 = 9,
ISO8859_8 = 10,
ISO8859_9 = 11,
ISO8859_10 = 12,
ISO8859_11 = 13,
ISO8859_13 = 15,
ISO8859_14 = 16,
ISO8859_15 = 17,
ISO8859_16 = 18,
Shift_JIS = 20,
Cp1250 = 21,
Cp1251 = 22,
Cp1252 = 23,
Cp1256 = 24,
UTF16BE = 25,
UTF8 = 26,
ASCII = 27,
Big5 = 28,
GB2312 = 29,
EUC_KR = 30,
GB18030 = 32,
UTF16LE = 33,
UTF32BE = 34,
UTF32LE = 35,
ISO646_Inv = 170,
Binary = 899,
}
impl Eci {
pub fn can_encode(self) -> bool {
(self as i32) >= 899
}
}
impl From<u32> for Eci {
fn from(value: u32) -> Self {
(value as i32).into()
}
}
impl From<i32> for Eci {
fn from(value: i32) -> Self {
match value {
0 | 2 => Eci::Cp437,
1 | 3 => Eci::ISO8859_1,
4 => Eci::ISO8859_2,
5 => Eci::ISO8859_3,
6 => Eci::ISO8859_4,
7 => Eci::ISO8859_5,
8 => Eci::ISO8859_6,
9 => Eci::ISO8859_7,
10 => Eci::ISO8859_8,
11 => Eci::ISO8859_9,
12 => Eci::ISO8859_10,
13 => Eci::ISO8859_11,
15 => Eci::ISO8859_13,
16 => Eci::ISO8859_14,
17 => Eci::ISO8859_15,
18 => Eci::ISO8859_16,
20 => Eci::Shift_JIS,
21 => Eci::Cp1250,
22 => Eci::Cp1251,
23 => Eci::Cp1252,
24 => Eci::Cp1256,
25 => Eci::UTF16BE,
26 => Eci::UTF8,
27 => Eci::ASCII,
28 => Eci::Big5,
29 => Eci::GB18030,
30 => Eci::EUC_KR,
32 => Eci::GB18030,
33 => Eci::UTF16LE,
34 => Eci::UTF32BE,
35 => Eci::UTF32LE,
170 => Eci::ASCII,
898 => Eci::Binary,
_ => Eci::Unknown,
}
}
}
impl From<CharacterSet> for Eci {
fn from(value: CharacterSet) -> Self {
match value {
CharacterSet::Cp437 => Eci::Cp437,
CharacterSet::ISO8859_1 => Eci::ISO8859_1,
CharacterSet::ISO8859_2 => Eci::ISO8859_2,
CharacterSet::ISO8859_3 => Eci::ISO8859_3,
CharacterSet::ISO8859_4 => Eci::ISO8859_4,
CharacterSet::ISO8859_5 => Eci::ISO8859_5,
CharacterSet::ISO8859_7 => Eci::ISO8859_7,
CharacterSet::ISO8859_9 => Eci::ISO8859_9,
CharacterSet::ISO8859_13 => Eci::ISO8859_13,
CharacterSet::ISO8859_15 => Eci::ISO8859_15,
CharacterSet::ISO8859_16 => Eci::ISO8859_16,
CharacterSet::Shift_JIS => Eci::Shift_JIS,
CharacterSet::Cp1250 => Eci::Cp1250,
CharacterSet::Cp1251 => Eci::Cp1251,
CharacterSet::Cp1252 => Eci::Cp1252,
CharacterSet::Cp1256 => Eci::Cp1256,
CharacterSet::UTF16BE => Eci::UTF16BE,
CharacterSet::UTF8 => Eci::UTF8,
CharacterSet::ASCII => Eci::ASCII,
CharacterSet::Big5 => Eci::Big5,
CharacterSet::GB2312 => Eci::GB2312,
CharacterSet::GB18030 => Eci::GB18030,
CharacterSet::EUC_KR => Eci::EUC_KR,
CharacterSet::UTF16LE => Eci::UTF16LE,
CharacterSet::UTF32BE => Eci::UTF32BE,
CharacterSet::UTF32LE => Eci::UTF32LE,
CharacterSet::Binary => Eci::Binary,
// CharacterSet::ISO8859_6 => Eci::ISO8859_6,
// CharacterSet::ISO8859_8 => Eci::ISO8859_8,
// CharacterSet::ISO8859_10 => Eci::ISO8859_10,
// CharacterSet::ISO8859_11 => Eci::ISO8859_11,
// CharacterSet::ISO8859_14 => Eci::ISO8859_14,
_ => Eci::Unknown,
}
}
}
impl From<Eci> for CharacterSet {
fn from(value: Eci) -> Self {
match value {
Eci::Cp437 => CharacterSet::Cp437,
Eci::ISO8859_1 => CharacterSet::ISO8859_1,
Eci::ISO8859_2 => CharacterSet::ISO8859_2,
Eci::ISO8859_3 => CharacterSet::ISO8859_3,
Eci::ISO8859_4 => CharacterSet::ISO8859_4,
Eci::ISO8859_5 => CharacterSet::ISO8859_5,
// Eci::ISO8859_6 => CharacterSet::ISO8859_6,
Eci::ISO8859_7 => CharacterSet::ISO8859_7,
// Eci::ISO8859_8 => CharacterSet::ISO8859_8,
Eci::ISO8859_9 => CharacterSet::ISO8859_9,
// Eci::ISO8859_10 => CharacterSet::ISO8859_10,
// Eci::ISO8859_11 => CharacterSet::ISO8859_11,
Eci::ISO8859_13 => CharacterSet::ISO8859_13,
// Eci::ISO8859_14 => CharacterSet::ISO8859_14,
Eci::ISO8859_15 => CharacterSet::ISO8859_15,
Eci::ISO8859_16 => CharacterSet::ISO8859_16,
Eci::Shift_JIS => CharacterSet::Shift_JIS,
Eci::Cp1250 => CharacterSet::Cp1250,
Eci::Cp1251 => CharacterSet::Cp1251,
Eci::Cp1252 => CharacterSet::Cp1252,
Eci::Cp1256 => CharacterSet::Cp1256,
Eci::UTF16BE => CharacterSet::UTF16BE,
Eci::UTF8 => CharacterSet::UTF8,
Eci::ASCII => CharacterSet::ASCII,
Eci::Big5 => CharacterSet::Big5,
Eci::GB2312 => CharacterSet::GB2312,
Eci::EUC_KR => CharacterSet::EUC_KR,
Eci::GB18030 => CharacterSet::GB18030,
Eci::UTF16LE => CharacterSet::UTF16LE,
Eci::UTF32BE => CharacterSet::UTF32BE,
Eci::UTF32LE => CharacterSet::UTF32LE,
Eci::ISO646_Inv => CharacterSet::ASCII,
Eci::Binary => CharacterSet::Binary,
_ => CharacterSet::Unknown,
}
}
}
impl Display for Eci {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", *self as i32)
}
}

View File

@@ -14,31 +14,17 @@
* limitations under the License. * limitations under the License.
*/ */
// package com.google.zxing.common;
// import java.nio.charset.Charset;
// import java.nio.charset.CharsetEncoder;
// import java.nio.charset.StandardCharsets;
// import java.nio.charset.UnsupportedCharsetException;
// import java.util.ArrayList;
// import java.util.List;
use encoding::{Encoding, EncodingRef};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use super::CharacterSetECI; use super::{CharacterSet, Eci};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
static ENCODERS: Lazy<Vec<EncodingRef>> = Lazy::new(|| { static ENCODERS: Lazy<Vec<CharacterSet>> = Lazy::new(|| {
let mut enc_vec = Vec::new(); let mut enc_vec = Vec::new();
for name in NAMES { for name in NAMES {
if let Some(enc) = CharacterSetECI::getCharacterSetECIByName(name) { if let Some(enc) = CharacterSet::get_character_set_by_name(name) {
// try { enc_vec.push(enc);
enc_vec.push(CharacterSetECI::getCharset(&enc));
// } catch (UnsupportedCharsetException e) {
// continue
// }
} }
} }
enc_vec enc_vec
@@ -83,7 +69,7 @@ const NAMES: [&str; 20] = [
*/ */
#[derive(Clone)] #[derive(Clone)]
pub struct ECIEncoderSet { pub struct ECIEncoderSet {
encoders: Vec<EncodingRef>, encoders: Vec<CharacterSet>,
priorityEncoderIndex: Option<usize>, priorityEncoderIndex: Option<usize>,
} }
@@ -98,22 +84,23 @@ impl ECIEncoderSet {
*/ */
pub fn new( pub fn new(
stringToEncodeMain: &str, stringToEncodeMain: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
fnc1: Option<&str>, fnc1: Option<&str>,
) -> Self { ) -> Self {
// List of encoders that potentially encode characters not in ISO-8859-1 in one byte. // List of encoders that potentially encode characters not in ISO-8859-1 in one byte.
let mut encoders: Vec<EncodingRef>; let mut encoders: Vec<CharacterSet>;
let mut priorityEncoderIndexValue = None; let mut priorityEncoderIndexValue = None;
let mut neededEncoders: Vec<EncodingRef> = Vec::new(); let mut neededEncoders: Vec<CharacterSet> = Vec::new();
let stringToEncode = stringToEncodeMain.graphemes(true).collect::<Vec<&str>>(); let stringToEncode = stringToEncodeMain.graphemes(true).collect::<Vec<&str>>();
//we always need the ISO-8859-1 encoder. It is the default encoding //we always need the ISO-8859-1 encoder. It is the default encoding
neededEncoders.push(encoding::all::ISO_8859_1); neededEncoders.push(CharacterSet::ISO8859_1);
let mut needUnicodeEncoder = if let Some(pc) = priorityCharset { let mut needUnicodeEncoder = if let Some(pc) = priorityCharset {
pc.name().starts_with("UTF") || pc.name().starts_with("utf") //pc.name().starts_with("UTF") || pc.name().starts_with("utf")
pc == CharacterSet::UTF8 || pc == CharacterSet::UTF16BE
} else { } else {
false false
}; };
@@ -125,9 +112,7 @@ impl ECIEncoderSet {
for encoder in &neededEncoders { for encoder in &neededEncoders {
// for (CharsetEncoder encoder : neededEncoders) { // for (CharsetEncoder encoder : neededEncoders) {
let c = stringToEncode.get(i).unwrap(); let c = stringToEncode.get(i).unwrap();
if (fnc1.is_some() && c == fnc1.as_ref().unwrap()) if (fnc1.is_some() && c == fnc1.as_ref().unwrap()) || encoder.encode(c).is_ok() {
|| encoder.encode(c, encoding::EncoderTrap::Strict).is_ok()
{
canEncode = true; canEncode = true;
break; break;
} }
@@ -138,13 +123,7 @@ impl ECIEncoderSet {
// for encoder in ENCODERS { // for encoder in ENCODERS {
let encoder = ENCODERS.get(i_encoder).unwrap(); let encoder = ENCODERS.get(i_encoder).unwrap();
// for (CharsetEncoder encoder : ENCODERS) { // for (CharsetEncoder encoder : ENCODERS) {
if encoder if encoder.encode(stringToEncode.get(i).unwrap()).is_ok() {
.encode(
stringToEncode.get(i).unwrap(),
encoding::EncoderTrap::Strict,
)
.is_ok()
{
//Good, we found an encoder that can encode the character. We add him to the list and continue scanning //Good, we found an encoder that can encode the character. We add him to the list and continue scanning
//the input //the input
neededEncoders.push(*encoder); neededEncoders.push(*encoder);
@@ -163,7 +142,7 @@ impl ECIEncoderSet {
if neededEncoders.len() == 1 && !needUnicodeEncoder { if neededEncoders.len() == 1 && !needUnicodeEncoder {
//the entire input can be encoded by the ISO-8859-1 encoder //the entire input can be encoded by the ISO-8859-1 encoder
encoders = vec![encoding::all::ISO_8859_1]; encoders = vec![CharacterSet::ISO8859_1];
} else { } else {
// we need more than one single byte encoder or we need a Unicode encoder. // we need more than one single byte encoder or we need a Unicode encoder.
// In this case we append a UTF-8 and UTF-16 encoder to the list // In this case we append a UTF-8 and UTF-16 encoder to the list
@@ -177,8 +156,8 @@ impl ECIEncoderSet {
encoders.push(encoder); encoders.push(encoder);
} }
encoders.push(encoding::all::UTF_8); encoders.push(CharacterSet::UTF8);
encoders.push(encoding::all::UTF_16BE); encoders.push(CharacterSet::UTF16BE);
} }
//Compute priorityEncoderIndex by looking up priorityCharset in encoders //Compute priorityEncoderIndex by looking up priorityCharset in encoders
@@ -187,7 +166,8 @@ impl ECIEncoderSet {
// for i in 0..encoders.len() { // for i in 0..encoders.len() {
for (i, encoder) in encoders.iter().enumerate() { for (i, encoder) in encoders.iter().enumerate() {
// for (int i = 0; i < encoders.length; i++) { // for (int i = 0; i < encoders.length; i++) {
if priorityCharset.as_ref().unwrap().name() == encoder.name() { // if priorityCharset.as_ref().unwrap().name() == encoder.name() {
if priorityCharset.as_ref().unwrap() == encoder {
priorityEncoderIndexValue = Some(i); priorityEncoderIndexValue = Some(i);
break; break;
} }
@@ -195,7 +175,7 @@ impl ECIEncoderSet {
} }
// } // }
//invariants //invariants
assert_eq!(encoders[0].name(), encoding::all::ISO_8859_1.name()); assert_eq!(encoders[0], CharacterSet::ISO8859_1);
Self { Self {
encoders, encoders,
priorityEncoderIndex: priorityEncoderIndexValue, priorityEncoderIndex: priorityEncoderIndexValue,
@@ -212,13 +192,13 @@ impl ECIEncoderSet {
pub fn getCharsetName(&self, index: usize) -> Option<&'static str> { pub fn getCharsetName(&self, index: usize) -> Option<&'static str> {
if index < self.len() { if index < self.len() {
Some(self.encoders[index].name()) Some(self.encoders[index].get_charset_name())
} else { } else {
None None
} }
} }
pub fn getCharset(&self, index: usize) -> Option<EncodingRef> { pub fn getCharset(&self, index: usize) -> Option<CharacterSet> {
if index < self.len() { if index < self.len() {
Some(self.encoders[index]) Some(self.encoders[index])
} else { } else {
@@ -226,10 +206,11 @@ impl ECIEncoderSet {
} }
} }
pub fn getECIValue(&self, encoderIndex: usize) -> u32 { pub fn get_eci(&self, encoderIndex: usize) -> Eci {
CharacterSetECI::getValue( self.encoders[encoderIndex].into()
&CharacterSetECI::getCharacterSetECI(self.encoders[encoderIndex]).unwrap(), // CharacterSetECI::getValue(
) // &CharacterSetECI::getCharacterSetECI(self.encoders[encoderIndex]).unwrap(),
// )
} }
/* /*
@@ -242,7 +223,7 @@ impl ECIEncoderSet {
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> Option<bool> { pub fn canEncode(&self, c: &str, encoderIndex: usize) -> Option<bool> {
if encoderIndex < self.len() { if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict); let enc_data = encoder.encode(c);
Some(enc_data.is_ok()) Some(enc_data.is_ok())
} else { } else {
@@ -253,7 +234,7 @@ impl ECIEncoderSet {
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Option<Vec<u8>> { pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Option<Vec<u8>> {
if encoderIndex < self.len() { if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict); let enc_data = encoder.encode(c);
enc_data.ok() enc_data.ok()
// assert!(enc_data.is_ok()); // assert!(enc_data.is_ok());
// enc_data.unwrap() // enc_data.unwrap()
@@ -265,7 +246,7 @@ impl ECIEncoderSet {
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Option<Vec<u8>> { pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Option<Vec<u8>> {
if encoderIndex < self.len() { if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
encoder.encode(s, encoding::EncoderTrap::Strict).ok() encoder.encode(s).ok()
} else { } else {
None None
} }

View File

@@ -20,6 +20,8 @@ use std::fmt::Display;
use crate::common::Result; use crate::common::Result;
use super::Eci;
/** /**
* Interface to navigate a sequence of ECIs and bytes. * Interface to navigate a sequence of ECIs and bytes.
* *
@@ -105,6 +107,6 @@ pub trait ECIInput: Display {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the value at the {@code index} argument is not an ECI (@see #isECI) * if the value at the {@code index} argument is not an ECI (@see #isECI)
*/ */
fn getECIValue(&self, index: usize) -> Result<i32>; fn getECIValue(&self, index: usize) -> Result<Eci>;
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool>; fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool>;
} }

View File

@@ -23,11 +23,9 @@
use std::fmt; use std::fmt;
use encoding::{Encoding, EncodingRef};
use crate::common::Result; use crate::common::Result;
use super::CharacterSetECI; use super::{CharacterSet, Eci};
/** /**
* Class that converts a sequence of ECIs and bytes into a string * Class that converts a sequence of ECIs and bytes into a string
@@ -37,7 +35,7 @@ use super::CharacterSetECI;
pub struct ECIStringBuilder { pub struct ECIStringBuilder {
current_bytes: Vec<u8>, current_bytes: Vec<u8>,
result: String, result: String,
current_charset: Option<EncodingRef>, //= StandardCharsets.ISO_8859_1; current_charset: CharacterSet, //= StandardCharsets.ISO_8859_1;
} }
impl ECIStringBuilder { impl ECIStringBuilder {
@@ -45,14 +43,14 @@ impl ECIStringBuilder {
Self { Self {
current_bytes: Vec::new(), current_bytes: Vec::new(),
result: String::new(), result: String::new(),
current_charset: Some(encoding::all::ISO_8859_1), current_charset: CharacterSet::ISO8859_1,
} }
} }
pub fn with_capacity(initial_capacity: usize) -> Self { pub fn with_capacity(initial_capacity: usize) -> Self {
Self { Self {
current_bytes: Vec::with_capacity(initial_capacity), current_bytes: Vec::with_capacity(initial_capacity),
result: String::with_capacity(initial_capacity), result: String::with_capacity(initial_capacity),
current_charset: Some(encoding::all::ISO_8859_1), current_charset: CharacterSet::ISO8859_1,
} }
} }
@@ -103,19 +101,21 @@ impl ECIStringBuilder {
* @param value ECI value to append, as an int * @param value ECI value to append, as an int
* @throws FormatException on invalid ECI value * @throws FormatException on invalid ECI value
*/ */
pub fn appendECI(&mut self, value: u32) -> Result<()> { pub fn appendECI(&mut self, eci: Eci) -> Result<()> {
self.encodeCurrentBytesIfAny(); self.encodeCurrentBytesIfAny();
if let Ok(character_set_eci) = CharacterSetECI::getCharacterSetECIByValue(value) { self.current_charset = eci.into(); //CharacterSet::get_character_set_by_eci(value).ok();
// dbg!(
// character_set_eci, // if let Ok(character_set_eci) = CharacterSetECI::getCharacterSetECIByValue(value) {
// CharacterSetECI::getCharset(&character_set_eci).name(), // // dbg!(
// CharacterSetECI::getCharset(&character_set_eci).whatwg_name() // // character_set_eci,
// ); // // CharacterSetECI::getCharset(&character_set_eci).name(),
self.current_charset = Some(CharacterSetECI::getCharset(&character_set_eci)); // // CharacterSetECI::getCharset(&character_set_eci).whatwg_name()
} else { // // );
self.current_charset = None // self.current_charset = Some(character_set_eci);
} // } else {
// self.current_charset = None
// }
// self.current_charset = CharacterSetECI::getCharset(&character_set_eci); // self.current_charset = CharacterSetECI::getCharset(&character_set_eci);
Ok(()) Ok(())
@@ -125,8 +125,8 @@ impl ECIStringBuilder {
/// ///
/// This function can panic /// This function can panic
pub fn encodeCurrentBytesIfAny(&mut self) { pub fn encodeCurrentBytesIfAny(&mut self) {
if let Some(encoder) = self.current_charset { if ![CharacterSet::Binary, CharacterSet::Unknown].contains(&self.current_charset) {
if encoder.name() == encoding::all::UTF_8.name() { if self.current_charset == CharacterSet::UTF8 {
if !self.current_bytes.is_empty() { if !self.current_bytes.is_empty() {
self.result.push_str( self.result.push_str(
&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(), &String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(),
@@ -136,9 +136,7 @@ impl ECIStringBuilder {
} else if !self.current_bytes.is_empty() { } else if !self.current_bytes.is_empty() {
let bytes = std::mem::take(&mut self.current_bytes); let bytes = std::mem::take(&mut self.current_bytes);
self.current_bytes.clear(); self.current_bytes.clear();
let encoded_value = encoder let encoded_value = self.current_charset.decode(&bytes).unwrap();
.decode(&bytes, encoding::DecoderTrap::Strict)
.unwrap();
self.result.push_str(&encoded_value); self.result.push_str(&encoded_value);
} }
} else { } else {

View File

@@ -16,13 +16,12 @@
use std::{fmt, rc::Rc}; use std::{fmt, rc::Rc};
use encoding::EncodingRef;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use crate::common::Result; use crate::common::Result;
use crate::Exceptions; use crate::Exceptions;
use super::{ECIEncoderSet, ECIInput}; use super::{CharacterSet, ECIEncoderSet, ECIInput, Eci};
//* approximated (latch + 2 codewords) //* approximated (latch + 2 codewords)
pub const COST_PER_ECI: usize = 3; pub const COST_PER_ECI: usize = 3;
@@ -155,7 +154,7 @@ impl ECIInput for MinimalECIInput {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the value at the {@code index} argument is not an ECI (@see #isECI) * if the value at the {@code index} argument is not an ECI (@see #isECI)
*/ */
fn getECIValue(&self, index: usize) -> Result<i32> { fn getECIValue(&self, index: usize) -> Result<Eci> {
if index >= self.length() { if index >= self.length() {
return Err(Exceptions::INDEX_OUT_OF_BOUNDS); return Err(Exceptions::INDEX_OUT_OF_BOUNDS);
} }
@@ -164,7 +163,7 @@ impl ECIInput for MinimalECIInput {
"value at {index} is not an ECI but a character" "value at {index} is not an ECI but a character"
))); )));
} }
Ok((self.bytes[index] as u32 - 256) as i32) Ok(Eci::from(self.bytes[index] as u32 - 256))
} }
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> { fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> {
@@ -194,7 +193,7 @@ impl MinimalECIInput {
*/ */
pub fn new( pub fn new(
stringToEncodeInput: &str, stringToEncodeInput: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
fnc1: Option<&str>, fnc1: Option<&str>,
) -> Self { ) -> Self {
let stringToEncode = stringToEncodeInput.graphemes(true).collect::<Vec<&str>>(); let stringToEncode = stringToEncodeInput.graphemes(true).collect::<Vec<&str>>();
@@ -384,7 +383,7 @@ impl MinimalECIInput {
// 0..0, // 0..0,
// [256 as u16 + encoderSet.getECIValue(c.encoderIndex) as u16], // [256 as u16 + encoderSet.getECIValue(c.encoderIndex) as u16],
// ); // );
intsAL.insert(0, 256_u16 + encoderSet.getECIValue(c.encoderIndex) as u16); intsAL.insert(0, 256_u16 + encoderSet.get_eci(c.encoderIndex) as u16);
} }
current = c.previous.clone(); current = c.previous.clone();
} }

View File

@@ -88,8 +88,8 @@ pub use grid_sampler::*;
mod default_grid_sampler; mod default_grid_sampler;
pub use default_grid_sampler::*; pub use default_grid_sampler::*;
mod character_set_eci; mod character_set;
pub use character_set_eci::*; pub use character_set::*;
mod eci_string_builder; mod eci_string_builder;
pub use eci_string_builder::*; pub use eci_string_builder::*;
@@ -106,6 +106,9 @@ pub use global_histogram_binarizer::*;
mod hybrid_binarizer; mod hybrid_binarizer;
pub use hybrid_binarizer::*; pub use hybrid_binarizer::*;
mod eci;
pub use eci::*;
#[cfg(feature = "otsu_level")] #[cfg(feature = "otsu_level")]
mod otsu_level_binarizer; mod otsu_level_binarizer;
#[cfg(feature = "otsu_level")] #[cfg(feature = "otsu_level")]

View File

@@ -14,11 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
use encoding::{Encoding, EncodingRef};
use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary}; use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary};
use once_cell::sync::Lazy; use super::CharacterSet;
/** /**
* Common string-related functions. * Common string-related functions.
@@ -50,8 +48,7 @@ const ASSUME_SHIFT_JIS: bool = false;
// static SHIFT_JIS: &'static str = "SJIS"; // static SHIFT_JIS: &'static str = "SJIS";
// static GB2312: &'static str = "GB2312"; // static GB2312: &'static str = "GB2312";
pub static SHIFT_JIS_CHARSET: Lazy<EncodingRef> = pub static SHIFT_JIS_CHARSET: CharacterSet = CharacterSet::Shift_JIS;
Lazy::new(|| encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
// private static final boolean ASSUME_SHIFT_JIS = // private static final boolean ASSUME_SHIFT_JIS =
// SHIFT_JIS_CHARSET.equals(PLATFORM_DEFAULT_ENCODING) || // SHIFT_JIS_CHARSET.equals(PLATFORM_DEFAULT_ENCODING) ||
@@ -67,14 +64,14 @@ impl StringUtils {
*/ */
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<&'static str> { pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<&'static str> {
let c = StringUtils::guessCharset(bytes, hints)?; let c = StringUtils::guessCharset(bytes, hints)?;
if c.name() == encoding::label::encoding_from_whatwg_label("SJIS")?.name() { if c == CharacterSet::Shift_JIS {
Some("SJIS") Some("SJIS")
} else if c.name() == encoding::all::UTF_8.name() { } else if c == CharacterSet::UTF8 {
Some("UTF8") Some("UTF8")
} else if c.name() == encoding::all::ISO_8859_1.name() { } else if c == CharacterSet::ISO8859_1 {
Some("ISO8859_1") Some("ISO8859_1")
} else { } else {
Some(c.name()) Some(c.get_charset_name())
} }
} }
@@ -87,12 +84,12 @@ impl StringUtils {
* or the platform default encoding if * or the platform default encoding if
* none of these can possibly be correct * none of these can possibly be correct
*/ */
pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<EncodingRef> { pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<CharacterSet> {
if let Some(DecodeHintValue::CharacterSet(cs_name)) = if let Some(DecodeHintValue::CharacterSet(cs_name)) =
hints.get(&DecodeHintType::CHARACTER_SET) hints.get(&DecodeHintType::CHARACTER_SET)
{ {
// if let DecodeHintValue::CharacterSet(cs_name) = hint { // if let DecodeHintValue::CharacterSet(cs_name) = hint {
return encoding::label::encoding_from_whatwg_label(cs_name); return CharacterSet::get_character_set_by_name(cs_name);
// } // }
} }
// if hints.contains_key(&DecodeHintType::CHARACTER_SET) { // if hints.contains_key(&DecodeHintType::CHARACTER_SET) {
@@ -104,9 +101,9 @@ impl StringUtils {
&& ((bytes[0] == 0xFE && bytes[1] == 0xFF) || (bytes[0] == 0xFF && bytes[1] == 0xFE)) && ((bytes[0] == 0xFE && bytes[1] == 0xFF) || (bytes[0] == 0xFF && bytes[1] == 0xFE))
{ {
if bytes[0] == 0xFE && bytes[1] == 0xFF { if bytes[0] == 0xFE && bytes[1] == 0xFF {
return Some(encoding::all::UTF_16BE); return Some(CharacterSet::UTF16BE);
} else { } else {
return Some(encoding::all::UTF_16LE); return Some(CharacterSet::UTF16LE);
} }
} }
@@ -224,7 +221,7 @@ impl StringUtils {
// Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
if can_be_utf8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) { if can_be_utf8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) {
return Some(encoding::all::UTF_8); return Some(CharacterSet::UTF8);
} }
// Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done // Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done
if can_be_shift_jis if can_be_shift_jis
@@ -232,7 +229,7 @@ impl StringUtils {
|| sjis_max_katakana_word_length >= 3 || sjis_max_katakana_word_length >= 3
|| sjis_max_double_bytes_word_length >= 3) || sjis_max_double_bytes_word_length >= 3)
{ {
return encoding::label::encoding_from_whatwg_label("SJIS"); return Some(CharacterSet::Shift_JIS); //encoding::label::encoding_from_whatwg_label("SJIS");
} }
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is: // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
// - If we saw // - If we saw
@@ -243,23 +240,23 @@ impl StringUtils {
return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2)
|| iso_high_other * 10 >= length || iso_high_other * 10 >= length
{ {
encoding::label::encoding_from_whatwg_label("SJIS") Some(CharacterSet::Shift_JIS)
} else { } else {
Some(encoding::all::ISO_8859_1) Some(CharacterSet::ISO8859_1)
}; };
} }
// Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
if can_be_iso88591 { if can_be_iso88591 {
return Some(encoding::all::ISO_8859_1); return Some(CharacterSet::ISO8859_1);
} }
if can_be_shift_jis { if can_be_shift_jis {
return Some(encoding::label::encoding_from_whatwg_label("SJIS").unwrap()); return Some(CharacterSet::Shift_JIS);
} }
if can_be_utf8 { if can_be_utf8 {
return Some(encoding::all::UTF_8); return Some(CharacterSet::UTF8);
} }
// Otherwise, we take a wild guess with platform encoding // Otherwise, we take a wild guess with platform encoding
Some(encoding::all::UTF_8) Some(CharacterSet::UTF8)
} }
} }

View File

@@ -17,10 +17,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use encoding::EncodingRef;
use crate::{ use crate::{
common::{BitMatrix, Result}, common::{BitMatrix, CharacterSet, Result},
qrcode::encoder::ByteMatrix, qrcode::encoder::ByteMatrix,
BarcodeFormat, EncodeHintType, EncodeHintValue, Exceptions, Writer, BarcodeFormat, EncodeHintType, EncodeHintValue, Exceptions, Writer,
}; };
@@ -117,14 +115,15 @@ impl Writer for DataMatrixWriter {
false false
}; };
let mut charset: Option<EncodingRef> = None; let mut charset: Option<CharacterSet> = None;
let hasEncodingHint = hints.contains_key(&EncodeHintType::CHARACTER_SET); let hasEncodingHint = hints.contains_key(&EncodeHintType::CHARACTER_SET);
if hasEncodingHint { if hasEncodingHint {
let Some(EncodeHintValue::CharacterSet(char_set_name)) = let Some(EncodeHintValue::CharacterSet(char_set_name)) =
hints.get(&EncodeHintType::CHARACTER_SET) else { hints.get(&EncodeHintType::CHARACTER_SET) else {
return Err(Exceptions::illegal_argument_with("charset does not exist")) return Err(Exceptions::illegal_argument_with("charset does not exist"))
}; };
charset = encoding::label::encoding_from_whatwg_label(char_set_name); charset = CharacterSet::get_character_set_by_name(char_set_name);
//encoding::label::encoding_from_whatwg_label(char_set_name);
// charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString()); // charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
} }
encoded = minimal_encoder::encodeHighLevelWithDetails( encoded = minimal_encoder::encodeHighLevelWithDetails(

View File

@@ -14,10 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
use encoding::Encoding;
use crate::{ use crate::{
common::{BitSource, DecoderRXingResult, ECIStringBuilder, Result}, common::{BitSource, CharacterSet, DecoderRXingResult, ECIStringBuilder, Eci, Result},
Exceptions, Exceptions,
}; };
@@ -729,11 +727,7 @@ fn decodeBase256Segment(
*byte = unrandomize255State(bits.readBits(8)?, codewordPosition) as u8; *byte = unrandomize255State(bits.readBits(8)?, codewordPosition) as u8;
codewordPosition += 1; codewordPosition += 1;
} }
result.append_string( result.append_string(&CharacterSet::ISO8859_1.decode(&bytes)?);
&encoding::all::ISO_8859_1
.decode(&bytes, encoding::DecoderTrap::Strict)
.map_err(Exceptions::parse_with)?,
);
byteSegments.push(bytes); byteSegments.push(bytes);
Ok(()) Ok(())
@@ -745,19 +739,21 @@ fn decodeBase256Segment(
fn decodeECISegment(bits: &mut BitSource, result: &mut ECIStringBuilder) -> Result<bool> { fn decodeECISegment(bits: &mut BitSource, result: &mut ECIStringBuilder) -> Result<bool> {
let firstByte = bits.readBits(8)?; let firstByte = bits.readBits(8)?;
if firstByte <= 127 { if firstByte <= 127 {
result.appendECI(firstByte - 1)?; result.appendECI(Eci::from(firstByte - 1))?;
return Ok(true); return Ok(true);
} }
let secondByte = bits.readBits(8)?; let secondByte = bits.readBits(8)?;
if firstByte <= 191 { if firstByte <= 191 {
result.appendECI((firstByte - 128) * 254 + 127 + secondByte - 1)?; result.appendECI(Eci::from((firstByte - 128) * 254 + 127 + secondByte - 1))?;
return Ok((firstByte - 128) * 254 + 127 + secondByte - 1 > 900); return Ok((firstByte - 128) * 254 + 127 + secondByte - 1 > 900);
} }
let thirdByte = bits.readBits(8)?; let thirdByte = bits.readBits(8)?;
result.appendECI((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1)?; result.appendECI(Eci::from(
(firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1,
))?;
Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900) Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900)
} }

View File

@@ -16,13 +16,12 @@
use std::rc::Rc; use std::rc::Rc;
use crate::common::Result; use crate::common::{CharacterSet, Result};
use crate::{Dimension, Exceptions}; use crate::{Dimension, Exceptions};
use super::{SymbolInfo, SymbolInfoLookup, SymbolShapeHint}; use super::{SymbolInfo, SymbolInfoLookup, SymbolShapeHint};
use encoding::{self, EncodingRef};
const ISO_8859_1_ENCODER: EncodingRef = encoding::all::ISO_8859_1; const ISO_8859_1_ENCODER: CharacterSet = CharacterSet::ISO8859_1;
pub struct EncoderContext<'a> { pub struct EncoderContext<'a> {
symbol_lookup: Rc<SymbolInfoLookup<'a>>, symbol_lookup: Rc<SymbolInfoLookup<'a>>,
@@ -58,14 +57,10 @@ impl<'a> EncoderContext<'_> {
// } // }
// sb.append(ch); // sb.append(ch);
// } // }
let sb = if let Ok(encoded_bytes) = let sb = if let Ok(encoded_bytes) = ISO_8859_1_ENCODER.encode(msg) {
ISO_8859_1_ENCODER.encode(msg, encoding::EncoderTrap::Strict) ISO_8859_1_ENCODER.decode(&encoded_bytes).map_err(|e| {
{ Exceptions::parse_with(format!("round trip decode should always work: {e}"))
ISO_8859_1_ENCODER })?
.decode(&encoded_bytes, encoding::DecoderTrap::Strict)
.map_err(|e| {
Exceptions::parse_with(format!("round trip decode should always work: {e}"))
})?
} else { } else {
return Err(Exceptions::illegal_argument_with( return Err(Exceptions::illegal_argument_with(
"Message contains characters outside ISO-8859-1 encoding.", "Message contains characters outside ISO-8859-1 encoding.",

View File

@@ -18,7 +18,10 @@ use std::rc::Rc;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::datamatrix::encoder::{SymbolInfo, SymbolShapeHint}; use crate::{
common::CharacterSet,
datamatrix::encoder::{SymbolInfo, SymbolShapeHint},
};
use super::{high_level_encoder, minimal_encoder, symbol_info, SymbolInfoLookup}; use super::{high_level_encoder, minimal_encoder, symbol_info, SymbolInfoLookup};
@@ -534,7 +537,7 @@ fn testECIs() {
assert_eq!("239 209 151 206 214 92 122 140 35 158 144 162 52 205 55 171 137 23 67 206 218 175 147 113 15 254 116 33 241 25 231 186 14 212 64 253 151 252 159 33 41 241 27 231 83 171 53 209 35 25 134 6 42 33 35 239 184 31 193 234 7 252 205 101 127 241 209 34 24 5 22 23 221 148 179 239 128 140 92 187 106 204 198 59 19 25 114 248 118 36 254 231 106 196 19 239 101 27 107 69 189 112 236 156 252 16 174 125 24 10 125 116 42 129", assert_eq!("239 209 151 206 214 92 122 140 35 158 144 162 52 205 55 171 137 23 67 206 218 175 147 113 15 254 116 33 241 25 231 186 14 212 64 253 151 252 159 33 41 241 27 231 83 171 53 209 35 25 134 6 42 33 35 239 184 31 193 234 7 252 205 101 127 241 209 34 24 5 22 23 221 148 179 239 128 140 92 187 106 204 198 59 19 25 114 248 118 36 254 231 106 196 19 239 101 27 107 69 189 112 236 156 252 16 174 125 24 10 125 116 42 129",
visualized); visualized);
let visualized = visualize(&minimal_encoder::encodeHighLevelWithDetails("that particularly stands out to me is \u{0625}\u{0650}\u{062C}\u{064E}\u{0651}\u{0627}\u{0635} (\u{02BE}\u{0101}\u{1E63}) \"pear\", suggested to have originated from Hebrew \u{05D0}\u{05B7}\u{05D2}\u{05B8}\u{05BC}\u{05E1} (ag\u{00E1}s)", Some(encoding::all::UTF_8), None , SymbolShapeHint::FORCE_NONE).expect("encode")); let visualized = visualize(&minimal_encoder::encodeHighLevelWithDetails("that particularly stands out to me is \u{0625}\u{0650}\u{062C}\u{064E}\u{0651}\u{0627}\u{0635} (\u{02BE}\u{0101}\u{1E63}) \"pear\", suggested to have originated from Hebrew \u{05D0}\u{05B7}\u{05D2}\u{05B8}\u{05BC}\u{05E1} (ag\u{00E1}s)", Some(CharacterSet::UTF8), None , SymbolShapeHint::FORCE_NONE).expect("encode"));
assert_eq!("241 27 239 209 151 206 214 92 122 140 35 158 144 162 52 205 55 171 137 23 67 206 218 175 147 113 15 254 116 33 231 202 33 131 77 154 119 225 163 238 206 28 249 93 36 150 151 53 108 246 145 228 217 71 199 42 33 35 239 184 31 193 234 7 252 205 101 127 241 209 34 24 5 22 23 221 148 179 239 128 140 92 187 106 204 198 59 19 25 114 248 118 36 254 231 43 133 212 175 38 220 44 6 125 49 172 93 189 209 111 61 217 203 62 116 42 129 1 151 46 196 91 241 137 32 182 77 227 122 18 168 63 213 108 4 154 49 199 94 244 140 35 185 80", assert_eq!("241 27 239 209 151 206 214 92 122 140 35 158 144 162 52 205 55 171 137 23 67 206 218 175 147 113 15 254 116 33 231 202 33 131 77 154 119 225 163 238 206 28 249 93 36 150 151 53 108 246 145 228 217 71 199 42 33 35 239 184 31 193 234 7 252 205 101 127 241 209 34 24 5 22 23 221 148 179 239 128 140 92 187 106 204 198 59 19 25 114 248 118 36 254 231 43 133 212 175 38 220 44 6 125 49 172 93 189 209 111 61 217 203 62 116 42 129 1 151 46 196 91 241 137 32 182 77 227 122 18 168 63 213 108 4 154 49 199 94 244 140 35 185 80",
visualized); visualized);
} }

View File

@@ -16,9 +16,7 @@
use std::rc::Rc; use std::rc::Rc;
use encoding::{self, EncodingRef}; use crate::common::{CharacterSet, Result};
use crate::common::Result;
use crate::{Dimension, Exceptions}; use crate::{Dimension, Exceptions};
use super::{ use super::{
@@ -26,7 +24,7 @@ use super::{
SymbolInfoLookup, SymbolShapeHint, TextEncoder, X12Encoder, SymbolInfoLookup, SymbolShapeHint, TextEncoder, X12Encoder,
}; };
#[allow(dead_code)] #[allow(dead_code)]
const DEFAULT_ENCODING: EncodingRef = encoding::all::ISO_8859_1; const DEFAULT_ENCODING: CharacterSet = CharacterSet::ISO8859_1;
/** /**
* DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in * DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in

View File

@@ -16,16 +16,14 @@
use std::{fmt, rc::Rc}; use std::{fmt, rc::Rc};
use encoding::{self, EncodingRef};
use crate::{ use crate::{
common::{ECIInput, MinimalECIInput, Result}, common::{CharacterSet, ECIInput, Eci, MinimalECIInput, Result},
Exceptions, Exceptions,
}; };
use super::{high_level_encoder, SymbolShapeHint}; use super::{high_level_encoder, SymbolShapeHint};
const ISO_8859_1_ENCODER: EncodingRef = encoding::all::ISO_8859_1; const ISO_8859_1_ENCODER: CharacterSet = CharacterSet::ISO8859_1;
/** /**
* Encoder that encodes minimally * Encoder that encodes minimally
@@ -153,7 +151,7 @@ pub fn encodeHighLevel(msg: &str) -> Result<String> {
*/ */
pub fn encodeHighLevelWithDetails( pub fn encodeHighLevelWithDetails(
msg: &str, msg: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
fnc1: Option<char>, fnc1: Option<char>,
shape: SymbolShapeHint, shape: SymbolShapeHint,
) -> Result<String> { ) -> Result<String> {
@@ -173,10 +171,7 @@ pub fn encodeHighLevelWithDetails(
msg = &msg[high_level_encoder::MACRO_06_HEADER.chars().count()..(msg.chars().count() - 2)]; msg = &msg[high_level_encoder::MACRO_06_HEADER.chars().count()..(msg.chars().count() - 2)];
} }
Ok(ISO_8859_1_ENCODER Ok(ISO_8859_1_ENCODER
.decode( .decode(&encode(msg, priorityCharset, fnc1, shape, macroId)?)
&encode(msg, priorityCharset, fnc1, shape, macroId)?,
encoding::DecoderTrap::Strict,
)
.expect("should decode")) .expect("should decode"))
// return new String(encode(msg, priorityCharset, fnc1, shape, macroId), StandardCharsets.ISO_8859_1); // return new String(encode(msg, priorityCharset, fnc1, shape, macroId), StandardCharsets.ISO_8859_1);
} }
@@ -197,7 +192,7 @@ pub fn encodeHighLevelWithDetails(
*/ */
fn encode( fn encode(
input: &str, input: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
fnc1: Option<char>, fnc1: Option<char>,
shape: SymbolShapeHint, shape: SymbolShapeHint,
macroId: i32, macroId: i32,
@@ -1398,7 +1393,7 @@ struct Input {
impl Input { impl Input {
pub fn new( pub fn new(
stringToEncode: &str, stringToEncode: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
fnc1: Option<char>, fnc1: Option<char>,
shape: SymbolShapeHint, shape: SymbolShapeHint,
macroId: i32, macroId: i32,
@@ -1446,7 +1441,7 @@ impl Input {
fn isFNC1(&self, index: usize) -> Result<bool> { fn isFNC1(&self, index: usize) -> Result<bool> {
self.internal.isFNC1(index) self.internal.isFNC1(index)
} }
fn getECIValue(&self, index: usize) -> Result<i32> { fn getECIValue(&self, index: usize) -> Result<Eci> {
self.internal.getECIValue(index) self.internal.getECIValue(index)
} }
} }

View File

@@ -19,7 +19,7 @@ use num::{self, bigint::ToBigUint, BigUint};
use std::rc::Rc; use std::rc::Rc;
use crate::{ use crate::{
common::{DecoderRXingResult, ECIStringBuilder, Result}, common::{DecoderRXingResult, ECIStringBuilder, Eci, Result},
pdf417::PDF417RXingResultMetadata, pdf417::PDF417RXingResultMetadata,
Exceptions, Exceptions,
}; };
@@ -128,7 +128,7 @@ pub fn decode(codewords: &[u32], ecLevel: &str) -> Result<DecoderRXingResult> {
codeIndex = numericCompaction(codewords, codeIndex, &mut result)? codeIndex = numericCompaction(codewords, codeIndex, &mut result)?
} }
ECI_CHARSET => { ECI_CHARSET => {
result.appendECI(codewords[codeIndex])?; result.appendECI(Eci::from(codewords[codeIndex]))?;
codeIndex += 1; codeIndex += 1;
} }
ECI_GENERAL_PURPOSE => ECI_GENERAL_PURPOSE =>
@@ -387,7 +387,7 @@ fn textCompaction(
subMode, subMode,
) )
.ok_or(Exceptions::ILLEGAL_STATE)?; .ok_or(Exceptions::ILLEGAL_STATE)?;
result.appendECI(codewords[codeIndex])?; result.appendECI(Eci::from(codewords[codeIndex]))?;
codeIndex += 1; codeIndex += 1;
textCompactionData = vec![0; (codewords[0] as usize - codeIndex) * 2]; textCompactionData = vec![0; (codewords[0] as usize - codeIndex) * 2];
byteCompactionData = vec![0; (codewords[0] as usize - codeIndex) * 2]; byteCompactionData = vec![0; (codewords[0] as usize - codeIndex) * 2];
@@ -616,7 +616,7 @@ fn byteCompaction(
//handle leading ECIs //handle leading ECIs
while codeIndex < codewords[0] as usize && codewords[codeIndex] == ECI_CHARSET { while codeIndex < codewords[0] as usize && codewords[codeIndex] == ECI_CHARSET {
codeIndex += 1; codeIndex += 1;
result.appendECI(codewords[codeIndex])?; result.appendECI(Eci::from(codewords[codeIndex]))?;
codeIndex += 1; codeIndex += 1;
} }
@@ -654,7 +654,7 @@ fn byteCompaction(
if code < TEXT_COMPACTION_MODE_LATCH { if code < TEXT_COMPACTION_MODE_LATCH {
result.append_byte(code as u8); result.append_byte(code as u8);
} else if code == ECI_CHARSET { } else if code == ECI_CHARSET {
result.appendECI(codewords[codeIndex])?; result.appendECI(Eci::from(codewords[codeIndex]))?;
codeIndex += 1; codeIndex += 1;
} else { } else {
codeIndex -= 1; codeIndex -= 1;

View File

@@ -15,9 +15,9 @@
* limitations under the License. * limitations under the License.
*/ */
use encoding::{Encoding, EncodingRef};
use java_rand; use java_rand;
use crate::common::CharacterSet;
use crate::pdf417::decoder::decoded_bit_stream_parser; use crate::pdf417::decoder::decoded_bit_stream_parser;
use crate::pdf417::encoder::{pdf_417_high_level_encoder_test_adapter, Compaction}; use crate::pdf417::encoder::{pdf_417_high_level_encoder_test_adapter, Compaction};
use crate::pdf417::PDF417RXingResultMetadata; use crate::pdf417::PDF417RXingResultMetadata;
@@ -307,8 +307,8 @@ fn testBinaryData() {
random.next_bytes(&mut bytes); random.next_bytes(&mut bytes);
total += encodeDecode( total += encodeDecode(
&encoding::all::ISO_8859_1 &CharacterSet::ISO8859_1
.decode(&bytes, encoding::DecoderTrap::Strict) .decode(&bytes)
.expect("decode bytes"), .expect("decode bytes"),
); );
} }
@@ -437,7 +437,7 @@ fn encodeDecode(input: &str) -> u32 {
fn encodeDecodeWithAll( fn encodeDecodeWithAll(
input: &str, input: &str,
charset: Option<EncodingRef>, charset: Option<CharacterSet>,
autoECI: bool, autoECI: bool,
decode: bool, decode: bool,
) -> u32 { ) -> u32 {
@@ -523,7 +523,7 @@ fn performECITest(
// for (int i = 0; i < 1000; i++) { // for (int i = 0; i < 1000; i++) {
let s = generateText(&mut random, 100, chars, weights); let s = generateText(&mut random, 100, chars, weights);
minLength += encodeDecodeWithAll(&s, None, true, true); minLength += encodeDecodeWithAll(&s, None, true, true);
utfLength += encodeDecodeWithAll(&s, Some(encoding::all::UTF_8), false, true); utfLength += encodeDecodeWithAll(&s, Some(CharacterSet::UTF8), false, true);
} }
assert_eq!(expectedMinLength, minLength); assert_eq!(expectedMinLength, minLength);
assert_eq!(expectedUTFLength, utfLength); assert_eq!(expectedUTFLength, utfLength);

View File

@@ -18,9 +18,7 @@
* This file has been modified from its original form in Barcode4J. * This file has been modified from its original form in Barcode4J.
*/ */
use encoding::EncodingRef; use crate::common::{CharacterSet, Result};
use crate::common::Result;
use crate::Exceptions; use crate::Exceptions;
use super::{ use super::{
@@ -34,7 +32,7 @@ pub struct PDF417 {
barcodeMatrix: Option<BarcodeMatrix>, barcodeMatrix: Option<BarcodeMatrix>,
compact: bool, compact: bool,
compaction: Compaction, compaction: Compaction,
encoding: Option<EncodingRef>, encoding: Option<CharacterSet>,
minCols: u32, minCols: u32,
maxCols: u32, maxCols: u32,
maxRows: u32, maxRows: u32,
@@ -347,7 +345,7 @@ impl PDF417 {
/** /**
* @param encoding sets character encoding to use * @param encoding sets character encoding to use
*/ */
pub fn setEncoding(&mut self, encoding: Option<EncodingRef>) { pub fn setEncoding(&mut self, encoding: Option<CharacterSet>) {
self.encoding = encoding; self.encoding = encoding;
} }
} }

View File

@@ -20,10 +20,8 @@
use std::{any::TypeId, fmt::Display, str::FromStr}; use std::{any::TypeId, fmt::Display, str::FromStr};
use encoding::EncodingRef;
use crate::{ use crate::{
common::{CharacterSetECI, ECIInput, MinimalECIInput, Result}, common::{CharacterSet, ECIInput, Eci, MinimalECIInput, Result},
Exceptions, Exceptions,
}; };
@@ -125,7 +123,7 @@ const TEXT_PUNCTUATION_RAW: [u8; 30] = [
40, 41, 63, 123, 125, 39, 0, 40, 41, 63, 123, 125, 39, 0,
]; ];
const DEFAULT_ENCODING: EncodingRef = encoding::all::ISO_8859_1; //StandardCharsets.ISO_8859_1; const DEFAULT_ENCODING: CharacterSet = CharacterSet::ISO8859_1; //StandardCharsets.ISO_8859_1;
const MIXED: [i8; 128] = { const MIXED: [i8; 128] = {
let mut mixed = [-1_i8; 128]; let mut mixed = [-1_i8; 128];
@@ -174,7 +172,7 @@ const PUNCTUATION: [i8; 128] = {
pub fn encodeHighLevel( pub fn encodeHighLevel(
msg: &str, msg: &str,
compaction: Compaction, compaction: Compaction,
encoding: Option<EncodingRef>, encoding: Option<CharacterSet>,
autoECI: bool, autoECI: bool,
) -> Result<String> { ) -> Result<String> {
let mut encoding = encoding; let mut encoding = encoding;
@@ -199,14 +197,18 @@ pub fn encodeHighLevel(
input = Box::new(NoECIInput::new(msg.to_owned())); input = Box::new(NoECIInput::new(msg.to_owned()));
if encoding.is_none() { if encoding.is_none() {
encoding = Some(DEFAULT_ENCODING); encoding = Some(DEFAULT_ENCODING);
} else if DEFAULT_ENCODING.name() } else if &DEFAULT_ENCODING != encoding.as_ref().ok_or(Exceptions::ILLEGAL_STATE)? {
!= encoding.as_ref().ok_or(Exceptions::ILLEGAL_STATE)?.name() // if let Some(eci) =
{ // CharacterSetECI::getCharacterSetECI(encoding.ok_or(Exceptions::ILLEGAL_STATE)?)
if let Some(eci) = // {
CharacterSetECI::getCharacterSetECI(encoding.ok_or(Exceptions::ILLEGAL_STATE)?) // encodingECI(CharacterSetECI::getValue(&eci) as i32, &mut sb)?;
{ // }
encodingECI(CharacterSetECI::getValue(&eci) as i32, &mut sb)?;
} encodingECI(
Eci::from(encoding.ok_or(Exceptions::ILLEGAL_STATE)?),
//CharacterSet::get_eci_value(&encoding.ok_or(Exceptions::ILLEGAL_STATE)?) as i32,
&mut sb,
)?;
} }
} }
@@ -230,7 +232,7 @@ pub fn encodeHighLevel(
let msgBytes = encoding let msgBytes = encoding
.as_ref() .as_ref()
.ok_or(Exceptions::ILLEGAL_STATE)? .ok_or(Exceptions::ILLEGAL_STATE)?
.encode(&input.to_string(), encoding::EncoderTrap::Strict) .encode(&input.to_string())
.unwrap_or_default(); //input.to_string().getBytes(encoding); .unwrap_or_default(); //input.to_string().getBytes(encoding);
encodeBinary( encodeBinary(
&msgBytes, &msgBytes,
@@ -290,7 +292,7 @@ pub fn encodeHighLevel(
if let Ok(enc_str) = encoding if let Ok(enc_str) = encoding
.as_ref() .as_ref()
.ok_or(Exceptions::ILLEGAL_STATE)? .ok_or(Exceptions::ILLEGAL_STATE)?
.encode(&str, encoding::EncoderTrap::Strict) .encode(&str)
{ {
Some(enc_str) Some(enc_str)
} else { } else {
@@ -757,7 +759,7 @@ fn determineConsecutiveTextCount<T: ECIInput + ?Sized>(input: &T, startpos: u32)
fn determineConsecutiveBinaryCount<T: ECIInput + ?Sized + 'static>( fn determineConsecutiveBinaryCount<T: ECIInput + ?Sized + 'static>(
input: &T, input: &T,
startpos: u32, startpos: u32,
encoding: Option<EncodingRef>, encoding: Option<CharacterSet>,
) -> Result<u32> { ) -> Result<u32> {
let len = input.length(); let len = input.length();
let mut idx = startpos as usize; let mut idx = startpos as usize;
@@ -778,12 +780,7 @@ fn determineConsecutiveBinaryCount<T: ECIInput + ?Sized + 'static>(
} }
if let Some(encoder) = encoding { if let Some(encoder) = encoding {
let can_encode = encoder let can_encode = encoder.encode(&input.charAt(idx)?.to_string()).is_ok();
.encode(
&input.charAt(idx)?.to_string(),
encoding::EncoderTrap::Strict,
)
.is_ok();
if !can_encode { if !can_encode {
if TypeId::of::<T>() != TypeId::of::<NoECIInput>() { if TypeId::of::<T>() != TypeId::of::<NoECIInput>() {
@@ -801,17 +798,17 @@ fn determineConsecutiveBinaryCount<T: ECIInput + ?Sized + 'static>(
Ok(idx as u32 - startpos) Ok(idx as u32 - startpos)
} }
fn encodingECI(eci: i32, sb: &mut String) -> Result<()> { fn encodingECI(eci: Eci, sb: &mut String) -> Result<()> {
if (0..900).contains(&eci) { if (0..900).contains(&(eci as i32)) {
sb.push(char::from_u32(ECI_CHARSET).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(ECI_CHARSET).ok_or(Exceptions::PARSE)?);
sb.push(char::from_u32(eci as u32).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(eci as u32).ok_or(Exceptions::PARSE)?);
} else if eci < 810900 { } else if (eci as i32) < 810900 {
sb.push(char::from_u32(ECI_GENERAL_PURPOSE).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(ECI_GENERAL_PURPOSE).ok_or(Exceptions::PARSE)?);
sb.push(char::from_u32((eci / 900 - 1) as u32).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(((eci as i32) / 900 - 1) as u32).ok_or(Exceptions::PARSE)?);
sb.push(char::from_u32((eci % 900) as u32).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(((eci as i32) % 900) as u32).ok_or(Exceptions::PARSE)?);
} else if eci < 811800 { } else if (eci as i32) < 811800 {
sb.push(char::from_u32(ECI_USER_DEFINED).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32(ECI_USER_DEFINED).ok_or(Exceptions::PARSE)?);
sb.push(char::from_u32((810900 - eci) as u32).ok_or(Exceptions::PARSE)?); sb.push(char::from_u32((810900 - (eci as i32)) as u32).ok_or(Exceptions::PARSE)?);
} else { } else {
return Err(Exceptions::writer_with(format!( return Err(Exceptions::writer_with(format!(
"ECI number not in valid range from 0..811799, but was {eci}" "ECI number not in valid range from 0..811799, but was {eci}"
@@ -842,8 +839,8 @@ impl ECIInput for NoECIInput {
Ok(false) Ok(false)
} }
fn getECIValue(&self, _index: usize) -> Result<i32> { fn getECIValue(&self, _index: usize) -> Result<Eci> {
Ok(-1) Ok(Eci::Unknown)
} }
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> { fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> {
@@ -866,11 +863,14 @@ impl Display for NoECIInput {
*/ */
#[cfg(test)] #[cfg(test)]
mod PDF417EncoderTestCase { mod PDF417EncoderTestCase {
use crate::pdf417::encoder::{pdf_417_high_level_encoder::encodeHighLevel, Compaction}; use crate::{
common::CharacterSet,
pdf417::encoder::{pdf_417_high_level_encoder::encodeHighLevel, Compaction},
};
#[test] #[test]
fn testEncodeAuto() { fn testEncodeAuto() {
let encoded = encodeHighLevel("ABCD", Compaction::AUTO, Some(encoding::all::UTF_8), false) let encoded = encodeHighLevel("ABCD", Compaction::AUTO, Some(CharacterSet::UTF8), false)
.expect("encode"); .expect("encode");
assert_eq!("\u{039f}\u{001A}\u{0385}ABCD", encoded); assert_eq!("\u{039f}\u{001A}\u{0385}ABCD", encoded);
} }
@@ -881,7 +881,7 @@ mod PDF417EncoderTestCase {
encodeHighLevel( encodeHighLevel(
"1%§s ?aG$", "1%§s ?aG$",
Compaction::AUTO, Compaction::AUTO,
Some(encoding::all::UTF_8), Some(CharacterSet::UTF8),
false, false,
) )
.expect("encode"); .expect("encode");
@@ -893,7 +893,7 @@ mod PDF417EncoderTestCase {
encodeHighLevel( encodeHighLevel(
"asdfg§asd", "asdfg§asd",
Compaction::AUTO, Compaction::AUTO,
Some(encoding::all::ISO_8859_1), Some(CharacterSet::ISO8859_1),
false, false,
) )
.expect("encode"); .expect("encode");
@@ -901,27 +901,22 @@ mod PDF417EncoderTestCase {
#[test] #[test]
fn testEncodeText() { fn testEncodeText() {
let encoded = encodeHighLevel("ABCD", Compaction::TEXT, Some(encoding::all::UTF_8), false) let encoded = encodeHighLevel("ABCD", Compaction::TEXT, Some(CharacterSet::UTF8), false)
.expect("encode"); .expect("encode");
assert_eq!("Ο\u{001A}\u{0001}?", encoded); assert_eq!("Ο\u{001A}\u{0001}?", encoded);
} }
#[test] #[test]
fn testEncodeNumeric() { fn testEncodeNumeric() {
let encoded = encodeHighLevel( let encoded = encodeHighLevel("1234", Compaction::NUMERIC, Some(CharacterSet::UTF8), false)
"1234", .expect("encode");
Compaction::NUMERIC,
Some(encoding::all::UTF_8),
false,
)
.expect("encode");
assert_eq!("\u{039f}\u{001A}\u{0386}\u{C}\u{01b2}", encoded); assert_eq!("\u{039f}\u{001A}\u{0386}\u{C}\u{01b2}", encoded);
// converted \f to \u{0046} // converted \f to \u{0046}
} }
#[test] #[test]
fn testEncodeByte() { fn testEncodeByte() {
let encoded = encodeHighLevel("abcd", Compaction::BYTE, Some(encoding::all::UTF_8), false) let encoded = encodeHighLevel("abcd", Compaction::BYTE, Some(CharacterSet::UTF8), false)
.expect("encode"); .expect("encode");
assert_eq!("\u{039f}\u{001A}\u{0385}abcd", encoded); assert_eq!("\u{039f}\u{001A}\u{0385}abcd", encoded);
} }

View File

@@ -14,9 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use encoding::EncodingRef; use crate::common::{CharacterSet, Result};
use crate::common::Result;
use super::{pdf_417_high_level_encoder, Compaction}; use super::{pdf_417_high_level_encoder, Compaction};
@@ -27,7 +25,7 @@ use super::{pdf_417_high_level_encoder, Compaction};
pub fn encodeHighLevel( pub fn encodeHighLevel(
msg: &str, msg: &str,
compaction: Compaction, compaction: Compaction,
encoding: Option<EncodingRef>, encoding: Option<CharacterSet>,
autoECI: bool, autoECI: bool,
) -> Result<String> { ) -> Result<String> {
pdf_417_high_level_encoder::encodeHighLevel(msg, compaction, encoding, autoECI) pdf_417_high_level_encoder::encodeHighLevel(msg, compaction, encoding, autoECI)

View File

@@ -17,7 +17,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
common::{BitMatrix, Result}, common::{BitMatrix, CharacterSet, Result},
BarcodeFormat, EncodeHintType, EncodeHintValue, Exceptions, Writer, BarcodeFormat, EncodeHintType, EncodeHintValue, Exceptions, Writer,
}; };
@@ -108,7 +108,7 @@ impl Writer for PDF417Writer {
if let Some(EncodeHintValue::CharacterSet(cs)) = if let Some(EncodeHintValue::CharacterSet(cs)) =
hints.get(&EncodeHintType::CHARACTER_SET) hints.get(&EncodeHintType::CHARACTER_SET)
{ {
encoder.setEncoding(encoding::label::encoding_from_whatwg_label(cs)); encoder.setEncoding(CharacterSet::get_character_set_by_name(cs));
} }
if let Some(EncodeHintValue::Pdf417AutoEci(auto_eci_str)) = if let Some(EncodeHintValue::Pdf417AutoEci(auto_eci_str)) =
hints.get(&EncodeHintType::PDF417_AUTO_ECI) hints.get(&EncodeHintType::PDF417_AUTO_ECI)

View File

@@ -15,7 +15,7 @@
*/ */
use crate::{ use crate::{
common::{BitSource, CharacterSetECI, DecoderRXingResult, Result, StringUtils}, common::{BitSource, CharacterSet, DecoderRXingResult, Eci, Result, StringUtils},
DecodingHintDictionary, Exceptions, DecodingHintDictionary, Exceptions,
}; };
@@ -91,7 +91,7 @@ pub fn decode(
Mode::ECI => { Mode::ECI => {
// Count doesn't apply to ECI // Count doesn't apply to ECI
let value = parseECIValue(&mut bits)?; let value = parseECIValue(&mut bits)?;
currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value).ok(); currentCharacterSetECI = CharacterSet::from(Eci::from(value)).into(); //CharacterSet::get_character_set_by_eci(value).ok();
if currentCharacterSetECI.is_none() { if currentCharacterSetECI.is_none() {
return Err(Exceptions::format_with(format!( return Err(Exceptions::format_with(format!(
"Value of {value} not valid" "Value of {value} not valid"
@@ -203,10 +203,9 @@ fn decodeHanziSegment(bits: &mut BitSource, result: &mut String, count: usize) -
count -= 1; count -= 1;
} }
let gb_encoder = let gb_encoder = CharacterSet::GB18030;
encoding::label::encoding_from_whatwg_label("GBK").ok_or(Exceptions::ILLEGAL_STATE)?;
let encode_string = gb_encoder 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}")))?; .map_err(|e| Exceptions::parse_with(format!("unable to decode buffer {buffer:?}: {e}")))?;
result.push_str(&encode_string); result.push_str(&encode_string);
Ok(()) Ok(())
@@ -216,7 +215,7 @@ fn decodeKanjiSegment(
bits: &mut BitSource, bits: &mut BitSource,
result: &mut String, result: &mut String,
count: usize, count: usize,
currentCharacterSetECI: Option<CharacterSetECI>, currentCharacterSetECI: Option<CharacterSet>,
hints: &DecodingHintDictionary, hints: &DecodingHintDictionary,
) -> Result<()> { ) -> Result<()> {
// Don't crash trying to read more bits than we have available. // Don't crash trying to read more bits than we have available.
@@ -250,7 +249,7 @@ fn decodeKanjiSegment(
let encoder = { let encoder = {
let _ = currentCharacterSetECI; let _ = currentCharacterSetECI;
let _ = hints; let _ = hints;
encoding::label::encoding_from_whatwg_label("SJIS").ok_or(Exceptions::FORMAT)? CharacterSet::Shift_JIS
}; };
#[cfg(feature = "allow_forced_iso_ied_18004_compliance")] #[cfg(feature = "allow_forced_iso_ied_18004_compliance")]
@@ -258,16 +257,16 @@ fn decodeKanjiSegment(
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT) hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
{ {
if let Some(ccse) = &currentCharacterSetECI { if let Some(ccse) = &currentCharacterSetECI {
CharacterSetECI::getCharset(ccse) CharacterSet::getCharacterSetECIByName(ccse)
} else { } else {
encoding::all::ISO_8859_1 CharacterSet::ISO8859_1
} }
} else { } else {
encoding::label::encoding_from_whatwg_label("SJIS").ok_or(Exceptions::FORMAT)? CharacterSet::Shift_JIS
}; };
let encode_string = encoder let encode_string = encoder
.decode(&buffer, encoding::DecoderTrap::Strict) .decode(&buffer)
.map_err(|e| Exceptions::parse_with(format!("unable to decode buffer {buffer:?}: {e}")))?; .map_err(|e| Exceptions::parse_with(format!("unable to decode buffer {buffer:?}: {e}")))?;
result.push_str(&encode_string); result.push_str(&encode_string);
@@ -279,7 +278,7 @@ fn decodeByteSegment(
bits: &mut BitSource, bits: &mut BitSource,
result: &mut String, result: &mut String,
count: usize, count: usize,
currentCharacterSetECI: Option<CharacterSetECI>, currentCharacterSetECI: Option<CharacterSet>,
byteSegments: &mut Vec<Vec<u8>>, byteSegments: &mut Vec<Vec<u8>>,
hints: &DecodingHintDictionary, hints: &DecodingHintDictionary,
) -> Result<()> { ) -> Result<()> {
@@ -308,37 +307,22 @@ fn decodeByteSegment(
if let Some(DecodeHintValue::QrAssumeSpecConformInput(true)) = if let Some(DecodeHintValue::QrAssumeSpecConformInput(true)) =
hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT) hints.get(&DecodeHintType::QR_ASSUME_SPEC_CONFORM_INPUT)
{ {
encoding::all::ISO_8859_1 CharacterSet::ISO8859_1
} else { } else {
StringUtils::guessCharset(&readBytes, hints).ok_or(Exceptions::ILLEGAL_STATE)? StringUtils::guessCharset(&readBytes, hints).ok_or(Exceptions::ILLEGAL_STATE)?
} }
} else { } else {
CharacterSetECI::getCharset( currentCharacterSetECI.ok_or(Exceptions::ILLEGAL_STATE)?
currentCharacterSetECI // CharacterSetECI::getCharset(
.as_ref() // currentCharacterSetECI
.ok_or(Exceptions::ILLEGAL_STATE)?, // .as_ref()
) // .ok_or(Exceptions::ILLEGAL_STATE)?,
// )
}; };
let encode_string = if currentCharacterSetECI.is_some() let encode_string = encoding.decode(&readBytes).map_err(|e| {
&& currentCharacterSetECI Exceptions::parse_with(format!("unable to decode buffer {readBytes:?}: {e}"))
.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 {
encoding
.decode(&readBytes, encoding::DecoderTrap::Strict)
.map_err(|e| {
Exceptions::parse_with(format!("unable to decode buffer {readBytes:?}: {e}"))
})?
};
result.push_str(&encode_string); result.push_str(&encode_string);
byteSegments.push(readBytes); byteSegments.push(readBytes);

View File

@@ -17,20 +17,18 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
common::BitArray, common::{BitArray, CharacterSet},
qrcode::{ qrcode::{
decoder::{ErrorCorrectionLevel, Mode, Version}, decoder::{ErrorCorrectionLevel, Mode, Version},
encoder::{qrcode_encoder, MinimalEncoder}, encoder::{qrcode_encoder, MinimalEncoder},
}, },
EncodeHintType, EncodeHintValue, EncodeHintType, EncodeHintValue,
}; };
use encoding::EncodingRef;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use super::QRCode; use super::QRCode;
static SHIFT_JIS_CHARSET: Lazy<EncodingRef> = static SHIFT_JIS_CHARSET: Lazy<CharacterSet> = Lazy::new(|| CharacterSet::Shift_JIS);
Lazy::new(|| encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
/** /**
* @author satorux@google.com (Satoru Takabayashi) - creator * @author satorux@google.com (Satoru Takabayashi) - creator
@@ -1075,10 +1073,9 @@ fn testMinimalEncoder41() {
#[test] #[test]
fn testMinimalEncoder42() { fn testMinimalEncoder42() {
// test halfwidth Katakana character (they are single byte encoded in Shift_JIS) // 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( verifyMinimalEncoding(
"Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}", "Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}",
"ECI(windows-31j),BYTE(Katakana:......)", "ECI(shift_jis),BYTE(Katakana:......)",
None, None,
false, false,
); );
@@ -1100,10 +1097,9 @@ fn testMinimalEncoder44() {
// The character \u30A2 encodes as double byte in Shift_JIS but KANJI is not more compact in this case because // 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 // 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 // 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( verifyMinimalEncoding(
"Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}", "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, None,
false, false,
); );
@@ -1112,7 +1108,7 @@ fn testMinimalEncoder44() {
fn verifyMinimalEncoding( fn verifyMinimalEncoding(
input: &str, input: &str,
expectedRXingResult: &str, expectedRXingResult: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
isGS1: bool, isGS1: bool,
) { ) {
let result = MinimalEncoder::encode_with_details( let result = MinimalEncoder::encode_with_details(
@@ -1198,7 +1194,7 @@ fn verifyNotGS1EncodedData(qrCode: &QRCode) {
fn shiftJISString(bytes: &[u8]) -> String { fn shiftJISString(bytes: &[u8]) -> String {
SHIFT_JIS_CHARSET SHIFT_JIS_CHARSET
.decode(bytes, encoding::DecoderTrap::Strict) .decode(bytes)
.expect("decode should be ok") .expect("decode should be ok")
// return new String(bytes, StringUtils.SHIFT_JIS_CHARSET); // return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
} }

View File

@@ -16,10 +16,8 @@
use std::{fmt, rc::Rc}; use std::{fmt, rc::Rc};
use encoding::EncodingRef;
use crate::{ use crate::{
common::{BitArray, ECIEncoderSet, Result}, common::{BitArray, CharacterSet, ECIEncoderSet, Result},
qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef}, qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef},
Exceptions, Exceptions,
}; };
@@ -107,7 +105,7 @@ impl MinimalEncoder {
*/ */
pub fn new( pub fn new(
stringToEncode: &str, stringToEncode: &str,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
isGS1: bool, isGS1: bool,
ecLevel: ErrorCorrectionLevel, ecLevel: ErrorCorrectionLevel,
) -> Self { ) -> Self {
@@ -142,7 +140,7 @@ impl MinimalEncoder {
pub fn encode_with_details( pub fn encode_with_details(
stringToEncode: &str, stringToEncode: &str,
version: Option<VersionRef>, version: Option<VersionRef>,
priorityCharset: Option<EncodingRef>, priorityCharset: Option<CharacterSet>,
isGS1: bool, isGS1: bool,
ecLevel: ErrorCorrectionLevel, ecLevel: ErrorCorrectionLevel,
) -> Result<RXingResultList> { ) -> Result<RXingResultList> {
@@ -1003,7 +1001,7 @@ impl RXingResultNode {
)?; )?;
} }
if self.mode == Mode::ECI { if self.mode == Mode::ECI {
bits.appendBits(self.encoders.getECIValue(self.charsetEncoderIndex), 8)?; bits.appendBits(self.encoders.get_eci(self.charsetEncoderIndex) as u32, 8)?;
} else if self.characterLength > 0 { } else if self.characterLength > 0 {
// append data // append data
qrcode_encoder::appendBytes( qrcode_encoder::appendBytes(
@@ -1047,7 +1045,7 @@ impl fmt::Display for RXingResultNode {
self.encoders self.encoders
.getCharset(self.charsetEncoderIndex) .getCharset(self.charsetEncoderIndex)
.ok_or(fmt::Error)? .ok_or(fmt::Error)?
.name(), .get_charset_name(),
); );
} else { } else {
let sub_string: String = self let sub_string: String = self

View File

@@ -19,15 +19,12 @@
*/ */
use std::collections::HashMap; use std::collections::HashMap;
use encoding::EncodingRef;
use once_cell::sync::Lazy;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use crate::{ use crate::{
common::{ common::{
reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder}, reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder},
BitArray, CharacterSetECI, Result, BitArray, CharacterSet, Eci, Result,
}, },
qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef}, qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef},
EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions, EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions,
@@ -35,8 +32,7 @@ use crate::{
use super::{mask_util, matrix_util, BlockPair, ByteMatrix, MinimalEncoder, QRCode}; use super::{mask_util, matrix_util, BlockPair, ByteMatrix, MinimalEncoder, QRCode};
static SHIFT_JIS_CHARSET: Lazy<EncodingRef> = static SHIFT_JIS_CHARSET: CharacterSet = CharacterSet::Shift_JIS;
Lazy::new(|| encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
// The original table is defined in the table 5 of JISX0510:2004 (p.19). // The original table is defined in the table 5 of JISX0510:2004 (p.19).
const ALPHANUMERIC_TABLE: [i8; 96] = [ const ALPHANUMERIC_TABLE: [i8; 96] = [
@@ -48,7 +44,7 @@ const ALPHANUMERIC_TABLE: [i8; 96] = [
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f 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: CharacterSet = CharacterSet::ISO8859_1;
// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. // 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. // Basically it applies four rules and summate all penalties.
@@ -100,8 +96,7 @@ pub fn encode_with_hints(
let mut has_encoding_hint = hints.contains_key(&EncodeHintType::CHARACTER_SET); let mut has_encoding_hint = hints.contains_key(&EncodeHintType::CHARACTER_SET);
if has_encoding_hint { if has_encoding_hint {
if let Some(EncodeHintValue::CharacterSet(v)) = hints.get(&EncodeHintType::CHARACTER_SET) { if let Some(EncodeHintValue::CharacterSet(v)) = hints.get(&EncodeHintType::CHARACTER_SET) {
encoding = encoding = Some(CharacterSet::get_character_set_by_name(v).ok_or(Exceptions::WRITER)?)
Some(encoding::label::encoding_from_whatwg_label(v).ok_or(Exceptions::WRITER)?)
} }
} }
@@ -125,13 +120,11 @@ pub fn encode_with_hints(
//Switch to default encoding //Switch to default encoding
let encoding = if let Some(encoding) = encoding { let encoding = if let Some(encoding) = encoding {
encoding encoding
} else if let Ok(_encs) = } else if let Ok(_encs) = DEFAULT_BYTE_MODE_ENCODING.encode(content) {
DEFAULT_BYTE_MODE_ENCODING.encode(content, encoding::EncoderTrap::Strict)
{
DEFAULT_BYTE_MODE_ENCODING DEFAULT_BYTE_MODE_ENCODING
} else { } else {
has_encoding_hint = true; has_encoding_hint = true;
encoding::all::UTF_8 CharacterSet::UTF8
}; };
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use // Pick an encoding mode appropriate for the content. Note that this will not attempt to use
@@ -144,9 +137,7 @@ pub fn encode_with_hints(
// Append ECI segment if applicable // Append ECI segment if applicable
if mode == Mode::BYTE && has_encoding_hint { if mode == Mode::BYTE && has_encoding_hint {
if let Some(eci) = CharacterSetECI::getCharacterSetECI(encoding) { appendECI(encoding.into(), &mut header_bits)?;
appendECI(&eci, &mut header_bits)?;
}
} }
// Append the FNC1 mode header for GS1 formatted data if applicable // Append the FNC1 mode header for GS1 formatted data if applicable
@@ -304,15 +295,15 @@ pub fn getAlphanumericCode(code: u32) -> i8 {
} }
pub fn chooseMode(content: &str) -> Mode { pub fn chooseMode(content: &str) -> Mode {
chooseModeWithEncoding(content, encoding::all::ISO_8859_1) chooseModeWithEncoding(content, CharacterSet::ISO8859_1)
} }
/** /**
* Choose the best mode by examining the content. Note that 'encoding' is used as a hint; * 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}. * 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 { fn chooseModeWithEncoding(content: &str, encoding: CharacterSet) -> Mode {
if SHIFT_JIS_CHARSET.name() == encoding.name() && isOnlyDoubleByteKanji(content) { if SHIFT_JIS_CHARSET == encoding && isOnlyDoubleByteKanji(content) {
// Choose Kanji mode if all input are double-byte characters // Choose Kanji mode if all input are double-byte characters
return Mode::KANJI; return Mode::KANJI;
} }
@@ -337,7 +328,7 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
} }
pub fn isOnlyDoubleByteKanji(content: &str) -> bool { 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 byt
} else { } else {
return false; return false;
@@ -638,7 +629,7 @@ pub fn appendBytes(
content: &str, content: &str,
mode: Mode, mode: Mode,
bits: &mut BitArray, bits: &mut BitArray,
encoding: EncodingRef, encoding: CharacterSet,
) -> Result<()> { ) -> Result<()> {
match mode { match mode {
Mode::NUMERIC => appendNumericBytes(content, bits), Mode::NUMERIC => appendNumericBytes(content, bits),
@@ -725,9 +716,9 @@ pub fn appendAlphanumericBytes(content: &str, bits: &mut BitArray) -> Result<()>
Ok(()) Ok(())
} }
pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) -> Result<()> { pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: CharacterSet) -> Result<()> {
let bytes = encoding let bytes = encoding
.encode(content, encoding::EncoderTrap::Strict) .encode(content)
.map_err(|e| Exceptions::writer_with(format!("error {e}")))?; .map_err(|e| Exceptions::writer_with(format!("error {e}")))?;
for b in bytes { for b in bytes {
bits.appendBits(b as u32, 8)?; bits.appendBits(b as u32, 8)?;
@@ -739,7 +730,7 @@ pub fn appendKanjiBytes(content: &str, bits: &mut BitArray) -> Result<()> {
let sjis = &SHIFT_JIS_CHARSET; let sjis = &SHIFT_JIS_CHARSET;
let bytes = sjis let bytes = sjis
.encode(content, encoding::EncoderTrap::Strict) .encode(content)
.map_err(|e| Exceptions::writer_with(format!("error {e}")))?; .map_err(|e| Exceptions::writer_with(format!("error {e}")))?;
if bytes.len() % 2 != 0 { if bytes.len() % 2 != 0 {
return Err(Exceptions::writer_with("Kanji byte size not even")); return Err(Exceptions::writer_with("Kanji byte size not even"));
@@ -767,8 +758,8 @@ pub fn appendKanjiBytes(content: &str, bits: &mut BitArray) -> Result<()> {
Ok(()) Ok(())
} }
fn appendECI(eci: &CharacterSetECI, bits: &mut BitArray) -> Result<()> { fn appendECI(eci: Eci, bits: &mut BitArray) -> Result<()> {
bits.appendBits(Mode::ECI.getBits() as u32, 4)?; bits.appendBits(Mode::ECI.getBits() as u32, 4)?;
// This is correct for values up to 127, which is all we need now. // This is correct for values up to 127, which is all we need now.
bits.appendBits(eci.getValueSelf(), 8) bits.appendBits(eci as u32, 8)
} }

View File

@@ -23,9 +23,8 @@ use std::{
rc::Rc, rc::Rc,
}; };
use encoding::Encoding;
use rxing::{ use rxing::{
common::{HybridBinarizer, Result}, common::{CharacterSet, HybridBinarizer, Result},
multi::MultipleBarcodeReader, multi::MultipleBarcodeReader,
pdf417::PDF417RXingResultMetadata, pdf417::PDF417RXingResultMetadata,
BarcodeFormat, Binarizer, BinaryBitmap, BufferedImageLuminanceSource, DecodeHintType, BarcodeFormat, Binarizer, BinaryBitmap, BufferedImageLuminanceSource, DecodeHintType,
@@ -645,8 +644,8 @@ impl<T: MultipleBarcodeReader + Reader> PDF417MultiImageSpanAbstractBlackBoxTest
if ext == "bin" { if ext == "bin" {
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
File::open(&file)?.read_to_end(&mut buffer)?; File::open(&file)?.read_to_end(&mut buffer)?;
encoding::all::ISO_8859_1 CharacterSet::ISO8859_1
.decode(&buffer, encoding::DecoderTrap::Replace) .decode_replace(&buffer)
.expect("decode") .expect("decode")
} else { } else {
read_to_string(&file).expect("ok") read_to_string(&file).expect("ok")