mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-27 21:02:35 +00:00
only 13 failing encoder tests
This commit is contained in:
@@ -20,6 +20,7 @@ chrono = "0.4"
|
|||||||
chrono-tz = "0.4"
|
chrono-tz = "0.4"
|
||||||
image = {version = "0.24.3", optional = true}
|
image = {version = "0.24.3", optional = true}
|
||||||
imageproc = {version = "0.23.0", optional = true}
|
imageproc = {version = "0.23.0", optional = true}
|
||||||
|
unicode-segmentation = "1.10.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
java-properties = "1.4.1"
|
java-properties = "1.4.1"
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ use encoding::EncodingRef;
|
|||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod StringUtilsTestCase;
|
mod StringUtilsTestCase;
|
||||||
|
|
||||||
@@ -2920,7 +2922,7 @@ impl ECIEncoderSet {
|
|||||||
* @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar
|
* @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar
|
||||||
* code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode().
|
* code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode().
|
||||||
*/
|
*/
|
||||||
pub fn new(stringToEncode: &str, priorityCharset: EncodingRef, fnc1: i16) -> Self {
|
pub fn new(stringToEncodeMain: &str, priorityCharset: EncodingRef, fnc1: Option<&str>) -> 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<EncodingRef>;
|
||||||
@@ -2928,20 +2930,22 @@ impl ECIEncoderSet {
|
|||||||
|
|
||||||
let mut neededEncoders: Vec<EncodingRef> = Vec::new();
|
let mut neededEncoders: Vec<EncodingRef> = Vec::new();
|
||||||
|
|
||||||
|
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(encoding::all::ISO_8859_1);
|
||||||
let mut needUnicodeEncoder = priorityCharset.name().starts_with("UTF");
|
let mut needUnicodeEncoder = priorityCharset.name().starts_with("UTF");
|
||||||
|
|
||||||
//Walk over the input string and see if all characters can be encoded with the list of encoders
|
//Walk over the input string and see if all characters can be encoded with the list of encoders
|
||||||
for i in 0..stringToEncode.chars().count() {
|
for i in 0..stringToEncode.len() {
|
||||||
// for (int i = 0; i < stringToEncode.length(); i++) {
|
// for (int i = 0; i < stringToEncode.length(); i++) {
|
||||||
let mut canEncode = false;
|
let mut canEncode = false;
|
||||||
for encoder in &neededEncoders {
|
for encoder in &neededEncoders {
|
||||||
// for (CharsetEncoder encoder : neededEncoders) {
|
// for (CharsetEncoder encoder : neededEncoders) {
|
||||||
let c = stringToEncode.chars().nth(i).unwrap();
|
let c = stringToEncode.get(i).unwrap();
|
||||||
if c == fnc1 as u8 as char
|
if (fnc1.is_some() && c == fnc1.as_ref().unwrap())
|
||||||
|| encoder
|
|| encoder
|
||||||
.encode(&c.to_string(), encoding::EncoderTrap::Strict)
|
.encode(c, encoding::EncoderTrap::Strict)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
canEncode = true;
|
canEncode = true;
|
||||||
@@ -2950,13 +2954,13 @@ impl ECIEncoderSet {
|
|||||||
}
|
}
|
||||||
if !canEncode {
|
if !canEncode {
|
||||||
//for the character at position i we don't yet have an encoder in the list
|
//for the character at position i we don't yet have an encoder in the list
|
||||||
for i in 0..ENCODERS.len() {
|
for i_encoder in 0..ENCODERS.len() {
|
||||||
// for encoder in ENCODERS {
|
// for encoder in ENCODERS {
|
||||||
let encoder = ENCODERS.get(i).unwrap();
|
let encoder = ENCODERS.get(i_encoder).unwrap();
|
||||||
// for (CharsetEncoder encoder : ENCODERS) {
|
// for (CharsetEncoder encoder : ENCODERS) {
|
||||||
if encoder
|
if encoder
|
||||||
.encode(
|
.encode(
|
||||||
&stringToEncode.chars().nth(i).unwrap().to_string(),
|
&stringToEncode.get(i).unwrap(),
|
||||||
encoding::EncoderTrap::Strict,
|
encoding::EncoderTrap::Strict,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
@@ -3044,15 +3048,15 @@ impl ECIEncoderSet {
|
|||||||
return self.priorityEncoderIndex;
|
return self.priorityEncoderIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canEncode(&self, c: i16, encoderIndex: usize) -> bool {
|
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> bool {
|
||||||
assert!(encoderIndex < self.len());
|
assert!(encoderIndex < self.len());
|
||||||
let encoder = self.encoders[encoderIndex];
|
let encoder = self.encoders[encoderIndex];
|
||||||
let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict);
|
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
|
||||||
|
|
||||||
enc_data.is_ok()
|
enc_data.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_char(&self, c: char, encoderIndex: usize) -> Vec<u8> {
|
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Vec<u8> {
|
||||||
assert!(encoderIndex < self.len());
|
assert!(encoderIndex < self.len());
|
||||||
let encoder = self.encoders[encoderIndex];
|
let encoder = self.encoders[encoderIndex];
|
||||||
let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict);
|
let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict);
|
||||||
@@ -3101,7 +3105,7 @@ static COST_PER_ECI: usize = 3;
|
|||||||
*/
|
*/
|
||||||
pub struct MinimalECIInput {
|
pub struct MinimalECIInput {
|
||||||
bytes: Vec<u16>,
|
bytes: Vec<u16>,
|
||||||
fnc1: i16,
|
fnc1: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ECIInput for MinimalECIInput {
|
impl ECIInput for MinimalECIInput {
|
||||||
@@ -3260,28 +3264,29 @@ impl MinimalECIInput {
|
|||||||
* @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1
|
* @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1
|
||||||
* input.
|
* input.
|
||||||
*/
|
*/
|
||||||
pub fn new(stringToEncode: &str, priorityCharset: EncodingRef, fnc1: i16) -> Self {
|
pub fn new(stringToEncodeInput: &str, priorityCharset: EncodingRef, fnc1: Option<&str>) -> Self {
|
||||||
let encoderSet = ECIEncoderSet::new(stringToEncode, priorityCharset, fnc1);
|
let stringToEncode = stringToEncodeInput.graphemes(true).collect::<Vec<&str>>();
|
||||||
|
let encoderSet = ECIEncoderSet::new(stringToEncodeInput, priorityCharset, fnc1);
|
||||||
let bytes = if encoderSet.len() == 1 {
|
let bytes = if encoderSet.len() == 1 {
|
||||||
//optimization for the case when all can be encoded without ECI in ISO-8859-1
|
//optimization for the case when all can be encoded without ECI in ISO-8859-1
|
||||||
let mut bytes_hld = vec![0; stringToEncode.len()];
|
let mut bytes_hld = vec![0; stringToEncode.len()];
|
||||||
for i in 0..stringToEncode.len() {
|
for i in 0..stringToEncode.len() {
|
||||||
// for (int i = 0; i < bytes.length; i++) {
|
// for (int i = 0; i < bytes.length; i++) {
|
||||||
let c = stringToEncode.chars().nth(i).unwrap();
|
let c = stringToEncode.get(i).unwrap();
|
||||||
bytes_hld[i] = if c as i16 == fnc1 { 1000 } else { c as u16 };
|
bytes_hld[i] = if fnc1.is_some() && c == fnc1.as_ref().unwrap() { 1000 } else { c.chars().nth(0).unwrap() as u16 };
|
||||||
}
|
}
|
||||||
bytes_hld
|
bytes_hld
|
||||||
} else {
|
} else {
|
||||||
Self::encodeMinimally(stringToEncode, &encoderSet, fnc1)
|
Self::encodeMinimally(stringToEncodeInput, &encoderSet, fnc1.as_ref().unwrap().chars().nth(0).unwrap() as u16)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
fnc1: fnc1,
|
fnc1: fnc1.as_ref().unwrap().chars().nth(0).unwrap() as u16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getFNC1Character(&self) -> i16 {
|
pub fn getFNC1Character(&self) -> u16 {
|
||||||
self.fnc1
|
self.fnc1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3321,14 +3326,15 @@ impl MinimalECIInput {
|
|||||||
edges: &mut Vec<Vec<Option<Rc<InputEdge>>>>,
|
edges: &mut Vec<Vec<Option<Rc<InputEdge>>>>,
|
||||||
from: usize,
|
from: usize,
|
||||||
previous: Option<Rc<InputEdge>>,
|
previous: Option<Rc<InputEdge>>,
|
||||||
fnc1: i16,
|
fnc1: u16,
|
||||||
) {
|
) {
|
||||||
let ch = stringToEncode.chars().nth(from).unwrap() as i16;
|
// let ch = stringToEncode.chars().nth(from).unwrap() as i16;
|
||||||
|
let ch = stringToEncode.graphemes(true).nth(from).unwrap();
|
||||||
|
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
let mut end = encoderSet.len();
|
let mut end = encoderSet.len();
|
||||||
if encoderSet.getPriorityEncoderIndex() >= 0
|
if encoderSet.getPriorityEncoderIndex() >= 0
|
||||||
&& (ch as i16 == fnc1 || encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex()))
|
&& (ch.chars().nth(0).unwrap() as u16 == fnc1 || encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex()))
|
||||||
{
|
{
|
||||||
start = encoderSet.getPriorityEncoderIndex();
|
start = encoderSet.getPriorityEncoderIndex();
|
||||||
end = start + 1;
|
end = start + 1;
|
||||||
@@ -3336,7 +3342,7 @@ impl MinimalECIInput {
|
|||||||
|
|
||||||
for i in start..end {
|
for i in start..end {
|
||||||
// for (int i = start; i < end; i++) {
|
// for (int i = start; i < end; i++) {
|
||||||
if ch as i16 == fnc1 || encoderSet.canEncode(ch, i) {
|
if ch.chars().nth(0).unwrap() as u16 == fnc1 || encoderSet.canEncode(ch, i) {
|
||||||
Self::addEdge(
|
Self::addEdge(
|
||||||
edges,
|
edges,
|
||||||
from + 1,
|
from + 1,
|
||||||
@@ -3349,7 +3355,7 @@ impl MinimalECIInput {
|
|||||||
pub fn encodeMinimally(
|
pub fn encodeMinimally(
|
||||||
stringToEncode: &str,
|
stringToEncode: &str,
|
||||||
encoderSet: &ECIEncoderSet,
|
encoderSet: &ECIEncoderSet,
|
||||||
fnc1: i16,
|
fnc1: u16,
|
||||||
) -> Vec<u16> {
|
) -> Vec<u16> {
|
||||||
let inputLength = stringToEncode.len();
|
let inputLength = stringToEncode.len();
|
||||||
|
|
||||||
@@ -3395,7 +3401,7 @@ impl MinimalECIInput {
|
|||||||
intsAL.splice(0..0, [1000]);
|
intsAL.splice(0..0, [1000]);
|
||||||
} else {
|
} else {
|
||||||
let bytes: Vec<u16> = encoderSet
|
let bytes: Vec<u16> = encoderSet
|
||||||
.encode_char(c.c as u8 as char, c.encoderIndex)
|
.encode_char(&c.c , c.encoderIndex)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| *x as u16)
|
.map(|x| *x as u16)
|
||||||
.collect();
|
.collect();
|
||||||
@@ -3429,25 +3435,27 @@ impl MinimalECIInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct InputEdge {
|
struct InputEdge {
|
||||||
c: i16,
|
c: String,
|
||||||
encoderIndex: usize, //the encoding of this edge
|
encoderIndex: usize, //the encoding of this edge
|
||||||
previous: Option<Rc<InputEdge>>,
|
previous: Option<Rc<InputEdge>>,
|
||||||
cachedTotalSize: usize,
|
cachedTotalSize: usize,
|
||||||
}
|
}
|
||||||
impl InputEdge {
|
impl InputEdge {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
c: i16,
|
c: &str,
|
||||||
encoderSet: &ECIEncoderSet,
|
encoderSet: &ECIEncoderSet,
|
||||||
encoderIndex: usize,
|
encoderIndex: usize,
|
||||||
previous: Option<Rc<InputEdge>>,
|
previous: Option<Rc<InputEdge>>,
|
||||||
fnc1: i16,
|
fnc1: u16,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut size = if c == 1000 {
|
let mut size = if c == "\u{1000}" {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
encoderSet.encode_char(c as u8 as char, encoderIndex).len()
|
encoderSet.encode_char(c, encoderIndex).len()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fnc1Str = String::from_utf16(&[fnc1]).unwrap();
|
||||||
|
|
||||||
if let Some(prev) = previous {
|
if let Some(prev) = previous {
|
||||||
let previousEncoderIndex = prev.encoderIndex;
|
let previousEncoderIndex = prev.encoderIndex;
|
||||||
if previousEncoderIndex != encoderIndex {
|
if previousEncoderIndex != encoderIndex {
|
||||||
@@ -3456,7 +3464,7 @@ impl InputEdge {
|
|||||||
size += prev.cachedTotalSize;
|
size += prev.cachedTotalSize;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
c: if c as i16 == fnc1 { 1000 } else { c as i16 },
|
c: if c == fnc1Str { String::from("\u{1000}") } else { String::from(c) },
|
||||||
encoderIndex,
|
encoderIndex,
|
||||||
previous: Some(prev.clone()),
|
previous: Some(prev.clone()),
|
||||||
cachedTotalSize: size,
|
cachedTotalSize: size,
|
||||||
@@ -3468,7 +3476,7 @@ impl InputEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
c: if c as i16 == fnc1 { 1000 } else { c as i16 },
|
c: if c == fnc1Str { String::from("\u{1000}") } else { String::from(c) },
|
||||||
encoderIndex,
|
encoderIndex,
|
||||||
previous: None,
|
previous: None,
|
||||||
cachedTotalSize: size,
|
cachedTotalSize: size,
|
||||||
@@ -3502,7 +3510,7 @@ impl InputEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn isFNC1(&self) -> bool {
|
pub fn isFNC1(&self) -> bool {
|
||||||
self.c == 1000
|
self.c == "\u{1000}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,14 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{qrcode::{encoder::{encoder, MinimalEncoder}, decoder::{Mode, ErrorCorrectionLevel, Version}}, EncodeHintType, EncodeHintValue, common::BitArray};
|
use crate::{
|
||||||
|
common::BitArray,
|
||||||
|
qrcode::{
|
||||||
|
decoder::{ErrorCorrectionLevel, Mode, Version},
|
||||||
|
encoder::{encoder, MinimalEncoder},
|
||||||
|
},
|
||||||
|
EncodeHintType, EncodeHintValue,
|
||||||
|
};
|
||||||
use encoding::EncodingRef;
|
use encoding::EncodingRef;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
@@ -43,7 +50,10 @@ lazy_static! {
|
|||||||
// The next 26 code points are capital alphabet letters.
|
// The next 26 code points are capital alphabet letters.
|
||||||
for i in 10..36 {
|
for i in 10..36 {
|
||||||
// for (int i = 10; i < 36; ++i) {
|
// for (int i = 10; i < 36; ++i) {
|
||||||
assert_eq!(i as i8, encoder::getAlphanumericCode((b'A' + i - 10) as u32));
|
assert_eq!(
|
||||||
|
i as i8,
|
||||||
|
encoder::getAlphanumericCode((b'A' + i - 10) as u32)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Others are symbol letters
|
// Others are symbol letters
|
||||||
@@ -70,8 +80,10 @@ lazy_static! {
|
|||||||
assert_eq!(Mode::NUMERIC, encoder::chooseMode("0123456789"));
|
assert_eq!(Mode::NUMERIC, encoder::chooseMode("0123456789"));
|
||||||
// Alphanumeric Mode::
|
// Alphanumeric Mode::
|
||||||
assert_eq!(Mode::ALPHANUMERIC, encoder::chooseMode("A"));
|
assert_eq!(Mode::ALPHANUMERIC, encoder::chooseMode("A"));
|
||||||
assert_eq!(Mode::ALPHANUMERIC,
|
assert_eq!(
|
||||||
encoder::chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"));
|
Mode::ALPHANUMERIC,
|
||||||
|
encoder::chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")
|
||||||
|
);
|
||||||
// 8-bit byte Mode::
|
// 8-bit byte Mode::
|
||||||
assert_eq!(Mode::BYTE, encoder::chooseMode("a"));
|
assert_eq!(Mode::BYTE, encoder::chooseMode("a"));
|
||||||
assert_eq!(Mode::BYTE, encoder::chooseMode("#"));
|
assert_eq!(Mode::BYTE, encoder::chooseMode("#"));
|
||||||
@@ -81,21 +93,28 @@ lazy_static! {
|
|||||||
// from data bytes alone. See also comments in qrcode_encoder::h.
|
// from data bytes alone. See also comments in qrcode_encoder::h.
|
||||||
|
|
||||||
// AIUE in Hiragana in Shift_JIS
|
// AIUE in Hiragana in Shift_JIS
|
||||||
assert_eq!(Mode::BYTE,
|
assert_eq!(
|
||||||
encoder::chooseMode(&shiftJISString(&[0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6])));
|
Mode::BYTE,
|
||||||
|
encoder::chooseMode(&shiftJISString(&[0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6]))
|
||||||
|
);
|
||||||
|
|
||||||
// Nihon in Kanji in Shift_JIS.
|
// Nihon in Kanji in Shift_JIS.
|
||||||
assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(&[0x9, 0xf, 0x9, 0x7b])));
|
assert_eq!(
|
||||||
|
Mode::BYTE,
|
||||||
|
encoder::chooseMode(&shiftJISString(&[0x9, 0xf, 0x9, 0x7b]))
|
||||||
|
);
|
||||||
|
|
||||||
// Sou-Utsu-Byou in Kanji in Shift_JIS.
|
// Sou-Utsu-Byou in Kanji in Shift_JIS.
|
||||||
assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(&[0xe, 0x4, 0x9, 0x5, 0x9, 0x61])));
|
assert_eq!(
|
||||||
|
Mode::BYTE,
|
||||||
|
encoder::chooseMode(&shiftJISString(&[0xe, 0x4, 0x9, 0x5, 0x9, 0x61]))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testEncode() {
|
fn testEncode() {
|
||||||
let qrCode = encoder::encode("ABCDEF", ErrorCorrectionLevel::H).expect("encode");
|
let qrCode = encoder::encode("ABCDEF", ErrorCorrectionLevel::H).expect("encode");
|
||||||
let expected =
|
let expected = r"<<
|
||||||
r"<<
|
|
||||||
mode: ALPHANUMERIC
|
mode: ALPHANUMERIC
|
||||||
ecLevel: H
|
ecLevel: H
|
||||||
version: 1
|
version: 1
|
||||||
@@ -130,8 +149,12 @@ r"<<
|
|||||||
#[test]
|
#[test]
|
||||||
fn testEncodeWithVersion() {
|
fn testEncodeWithVersion() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
hints.insert(EncodeHintType::QR_VERSION, EncodeHintValue::QrVersion("7".to_owned()));
|
hints.insert(
|
||||||
let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::QR_VERSION,
|
||||||
|
EncodeHintValue::QrVersion("7".to_owned()),
|
||||||
|
);
|
||||||
|
let qrCode =
|
||||||
|
encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
||||||
assert!(qrCode.to_string().contains(" version: 7\n"));
|
assert!(qrCode.to_string().contains(" version: 7\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,17 +162,28 @@ r"<<
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn testEncodeWithVersionTooSmall() {
|
fn testEncodeWithVersionTooSmall() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
hints.insert(EncodeHintType::QR_VERSION, EncodeHintValue::QrVersion("3".to_owned()));
|
hints.insert(
|
||||||
encoder::encode_with_hints("THISMESSAGEISTOOLONGFORAQRCODEVERSION3", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::QR_VERSION,
|
||||||
|
EncodeHintValue::QrVersion("3".to_owned()),
|
||||||
|
);
|
||||||
|
encoder::encode_with_hints(
|
||||||
|
"THISMESSAGEISTOOLONGFORAQRCODEVERSION3",
|
||||||
|
ErrorCorrectionLevel::H,
|
||||||
|
&hints,
|
||||||
|
)
|
||||||
|
.expect("encode");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testSimpleUTF8ECI() {
|
fn testSimpleutf8ECI() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("UTF8".to_owned()));
|
hints.insert(
|
||||||
let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::CHARACTER_SET,
|
||||||
let expected =
|
EncodeHintValue::CharacterSet("utf8".to_owned()),
|
||||||
r"<<
|
);
|
||||||
|
let qrCode =
|
||||||
|
encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode");
|
||||||
|
let expected = r"<<
|
||||||
mode: BYTE
|
mode: BYTE
|
||||||
ecLevel: H
|
ecLevel: H
|
||||||
version: 1
|
version: 1
|
||||||
@@ -185,11 +219,14 @@ r"<<
|
|||||||
fn testEncodeKanjiMode() {
|
fn testEncodeKanjiMode() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("Shift_JIS".to_owned()));
|
hints.insert(
|
||||||
|
EncodeHintType::CHARACTER_SET,
|
||||||
|
EncodeHintValue::CharacterSet("Shift_JIS".to_owned()),
|
||||||
|
);
|
||||||
// Nihon in Kanji
|
// Nihon in Kanji
|
||||||
let qrCode = encoder::encode_with_hints("\u{65e5}\u{672c}", ErrorCorrectionLevel::M, &hints).expect("encode");
|
let qrCode = encoder::encode_with_hints("\u{65e5}\u{672c}", ErrorCorrectionLevel::M, &hints)
|
||||||
let expected =
|
.expect("encode");
|
||||||
r"<<
|
let expected = r"<<
|
||||||
mode: KANJI
|
mode: KANJI
|
||||||
ecLevel: M
|
ecLevel: M
|
||||||
version: 1
|
version: 1
|
||||||
@@ -225,11 +262,14 @@ r"<<
|
|||||||
fn testEncodeShiftjisNumeric() {
|
fn testEncodeShiftjisNumeric() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("Shift_JIS".to_owned()));
|
hints.insert(
|
||||||
|
EncodeHintType::CHARACTER_SET,
|
||||||
|
EncodeHintValue::CharacterSet("Shift_JIS".to_owned()),
|
||||||
|
);
|
||||||
|
|
||||||
let qrCode = encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, &hints).expect("encode");
|
let qrCode =
|
||||||
let expected =
|
encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, &hints).expect("encode");
|
||||||
r"<<
|
let expected = r"<<
|
||||||
mode: NUMERIC
|
mode: NUMERIC
|
||||||
ecLevel: M
|
ecLevel: M
|
||||||
version: 1
|
version: 1
|
||||||
@@ -265,8 +305,12 @@ r"<<
|
|||||||
fn testEncodeGS1WithStringTypeHint() {
|
fn testEncodeGS1WithStringTypeHint() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned()));
|
hints.insert(
|
||||||
let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::GS1_FORMAT,
|
||||||
|
EncodeHintValue::Gs1Format("true".to_owned()),
|
||||||
|
);
|
||||||
|
let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints)
|
||||||
|
.expect("encode");
|
||||||
verifyGS1EncodedData(&qrCode);
|
verifyGS1EncodedData(&qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +318,12 @@ r"<<
|
|||||||
fn testEncodeGS1WithBooleanTypeHint() {
|
fn testEncodeGS1WithBooleanTypeHint() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned()));
|
hints.insert(
|
||||||
let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::GS1_FORMAT,
|
||||||
|
EncodeHintValue::Gs1Format("true".to_owned()),
|
||||||
|
);
|
||||||
|
let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints)
|
||||||
|
.expect("encode");
|
||||||
verifyGS1EncodedData(&qrCode);
|
verifyGS1EncodedData(&qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +331,13 @@ r"<<
|
|||||||
fn testDoesNotEncodeGS1WhenBooleanTypeHintExplicitlyFalse() {
|
fn testDoesNotEncodeGS1WhenBooleanTypeHintExplicitlyFalse() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned()));
|
hints.insert(
|
||||||
|
EncodeHintType::GS1_FORMAT,
|
||||||
|
EncodeHintValue::Gs1Format("false".to_owned()),
|
||||||
|
);
|
||||||
|
|
||||||
let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
let qrCode =
|
||||||
|
encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
||||||
verifyNotGS1EncodedData(&qrCode);
|
verifyNotGS1EncodedData(&qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,8 +345,12 @@ r"<<
|
|||||||
fn testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() {
|
fn testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned()));
|
hints.insert(
|
||||||
let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintType::GS1_FORMAT,
|
||||||
|
EncodeHintValue::Gs1Format("false".to_owned()),
|
||||||
|
);
|
||||||
|
let qrCode =
|
||||||
|
encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode");
|
||||||
verifyNotGS1EncodedData(&qrCode);
|
verifyNotGS1EncodedData(&qrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,11 +358,17 @@ r"<<
|
|||||||
fn testGS1ModeHeaderWithECI() {
|
fn testGS1ModeHeaderWithECI() {
|
||||||
let mut hints = HashMap::new();
|
let mut hints = HashMap::new();
|
||||||
|
|
||||||
hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("UTF8".to_owned()));
|
hints.insert(
|
||||||
hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned()));
|
EncodeHintType::CHARACTER_SET,
|
||||||
let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode");
|
EncodeHintValue::CharacterSet("utf8".to_owned()),
|
||||||
let expected =
|
);
|
||||||
r"<<
|
hints.insert(
|
||||||
|
EncodeHintType::GS1_FORMAT,
|
||||||
|
EncodeHintValue::Gs1Format("true".to_owned()),
|
||||||
|
);
|
||||||
|
let qrCode =
|
||||||
|
encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode");
|
||||||
|
let expected = r"<<
|
||||||
mode: BYTE
|
mode: BYTE
|
||||||
ecLevel: H
|
ecLevel: H
|
||||||
version: 1
|
version: 1
|
||||||
@@ -348,28 +410,36 @@ r"<<
|
|||||||
#[test]
|
#[test]
|
||||||
fn testAppendLengthInfo() {
|
fn testAppendLengthInfo() {
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendLengthInfo(1, // 1 letter (1/1).
|
encoder::appendLengthInfo(
|
||||||
|
1, // 1 letter (1/1).
|
||||||
Version::getVersionForNumber(1).unwrap(),
|
Version::getVersionForNumber(1).unwrap(),
|
||||||
Mode::NUMERIC,
|
Mode::NUMERIC,
|
||||||
&mut bits);
|
&mut bits,
|
||||||
|
);
|
||||||
assert_eq!(" ........ .X", bits.to_string()); // 10 bits.
|
assert_eq!(" ........ .X", bits.to_string()); // 10 bits.
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendLengthInfo(2, // 2 letters (2/1).
|
encoder::appendLengthInfo(
|
||||||
|
2, // 2 letters (2/1).
|
||||||
Version::getVersionForNumber(10).unwrap(),
|
Version::getVersionForNumber(10).unwrap(),
|
||||||
Mode::ALPHANUMERIC,
|
Mode::ALPHANUMERIC,
|
||||||
&mut bits);
|
&mut bits,
|
||||||
|
);
|
||||||
assert_eq!(" ........ .X.", bits.to_string()); // 11 bits.
|
assert_eq!(" ........ .X.", bits.to_string()); // 11 bits.
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendLengthInfo(255, // 255 letter (255/1).
|
encoder::appendLengthInfo(
|
||||||
|
255, // 255 letter (255/1).
|
||||||
Version::getVersionForNumber(27).unwrap(),
|
Version::getVersionForNumber(27).unwrap(),
|
||||||
Mode::BYTE,
|
Mode::BYTE,
|
||||||
&mut bits);
|
&mut bits,
|
||||||
|
);
|
||||||
assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits.
|
assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits.
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendLengthInfo(512, // 512 letters (1024/2).
|
encoder::appendLengthInfo(
|
||||||
|
512, // 512 letters (1024/2).
|
||||||
Version::getVersionForNumber(40).unwrap(),
|
Version::getVersionForNumber(40).unwrap(),
|
||||||
Mode::KANJI,
|
Mode::KANJI,
|
||||||
&mut bits);
|
&mut bits,
|
||||||
|
);
|
||||||
assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits.
|
assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,16 +448,33 @@ r"<<
|
|||||||
// Should use appendNumericBytes.
|
// Should use appendNumericBytes.
|
||||||
// 1 = 01 = 0001 in 4 bits.
|
// 1 = 01 = 0001 in 4 bits.
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendBytes("1", Mode::NUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
encoder::appendBytes(
|
||||||
|
"1",
|
||||||
|
Mode::NUMERIC,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
);
|
||||||
assert_eq!(" ...X", bits.to_string());
|
assert_eq!(" ...X", bits.to_string());
|
||||||
// Should use appendAlphanumericBytes.
|
// Should use appendAlphanumericBytes.
|
||||||
// A = 10 = 0xa = 001010 in 6 bits
|
// A = 10 = 0xa = 001010 in 6 bits
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendBytes("A", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
encoder::appendBytes(
|
||||||
|
"A",
|
||||||
|
Mode::ALPHANUMERIC,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
);
|
||||||
assert_eq!(" ..X.X.", bits.to_string());
|
assert_eq!(" ..X.X.", bits.to_string());
|
||||||
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
|
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
|
||||||
//try {
|
//try {
|
||||||
if encoder::appendBytes("a", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).is_ok(){
|
if encoder::appendBytes(
|
||||||
|
"a",
|
||||||
|
Mode::ALPHANUMERIC,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
panic!("should never be ok");
|
panic!("should never be ok");
|
||||||
}
|
}
|
||||||
//} catch (WriterException we) {
|
//} catch (WriterException we) {
|
||||||
@@ -396,15 +483,29 @@ r"<<
|
|||||||
// Should use append8BitBytes.
|
// Should use append8BitBytes.
|
||||||
// 0x61, 0x62, 0x63
|
// 0x61, 0x62, 0x63
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendBytes("abc", Mode::BYTE, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
encoder::appendBytes(
|
||||||
|
"abc",
|
||||||
|
Mode::BYTE,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
);
|
||||||
assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string());
|
assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string());
|
||||||
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
|
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
|
||||||
encoder::appendBytes("\0", Mode::BYTE, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
encoder::appendBytes(
|
||||||
|
"\0",
|
||||||
|
Mode::BYTE,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
);
|
||||||
// Should use appendKanjiBytes.
|
// Should use appendKanjiBytes.
|
||||||
// 0x93, 0x5f
|
// 0x93, 0x5f
|
||||||
let mut bits = BitArray::new();
|
let mut bits = BitArray::new();
|
||||||
encoder::appendBytes(&shiftJISString(&[0x93, 0x5f]), Mode::KANJI, &mut bits,
|
encoder::appendBytes(
|
||||||
encoder::DEFAULT_BYTE_MODE_ENCODING);
|
&shiftJISString(&[0x93, 0x5f]),
|
||||||
|
Mode::KANJI,
|
||||||
|
&mut bits,
|
||||||
|
encoder::DEFAULT_BYTE_MODE_ENCODING,
|
||||||
|
);
|
||||||
assert_eq!(" .XX.XX.. XXXXX", bits.to_string());
|
assert_eq!(" .XX.XX.. XXXXX", bits.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,34 +543,90 @@ r"<<
|
|||||||
let mut numDataBytes = vec![0; 1];
|
let mut numDataBytes = vec![0; 1];
|
||||||
let mut numEcBytes = vec![0; 1];
|
let mut numEcBytes = vec![0; 1];
|
||||||
// Version 1-H.
|
// Version 1-H.
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
26,
|
||||||
|
9,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(9, numDataBytes[0]);
|
assert_eq!(9, numDataBytes[0]);
|
||||||
assert_eq!(17, numEcBytes[0]);
|
assert_eq!(17, numEcBytes[0]);
|
||||||
|
|
||||||
// Version 3-H. 2 blocks.
|
// Version 3-H. 2 blocks.
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
70,
|
||||||
|
26,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(13, numDataBytes[0]);
|
assert_eq!(13, numDataBytes[0]);
|
||||||
assert_eq!(22, numEcBytes[0]);
|
assert_eq!(22, numEcBytes[0]);
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
70,
|
||||||
|
26,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(13, numDataBytes[0]);
|
assert_eq!(13, numDataBytes[0]);
|
||||||
assert_eq!(22, numEcBytes[0]);
|
assert_eq!(22, numEcBytes[0]);
|
||||||
|
|
||||||
// Version 7-H. (4 + 1) blocks.
|
// Version 7-H. (4 + 1) blocks.
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
196,
|
||||||
|
66,
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(13, numDataBytes[0]);
|
assert_eq!(13, numDataBytes[0]);
|
||||||
assert_eq!(26, numEcBytes[0]);
|
assert_eq!(26, numEcBytes[0]);
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
196,
|
||||||
|
66,
|
||||||
|
5,
|
||||||
|
4,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(14, numDataBytes[0]);
|
assert_eq!(14, numDataBytes[0]);
|
||||||
assert_eq!(26, numEcBytes[0]);
|
assert_eq!(26, numEcBytes[0]);
|
||||||
|
|
||||||
// Version 40-H. (20 + 61) blocks.
|
// Version 40-H. (20 + 61) blocks.
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
3706,
|
||||||
|
1276,
|
||||||
|
81,
|
||||||
|
0,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(15, numDataBytes[0]);
|
assert_eq!(15, numDataBytes[0]);
|
||||||
assert_eq!(30, numEcBytes[0]);
|
assert_eq!(30, numEcBytes[0]);
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
3706,
|
||||||
|
1276,
|
||||||
|
81,
|
||||||
|
20,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(16, numDataBytes[0]);
|
assert_eq!(16, numDataBytes[0]);
|
||||||
assert_eq!(30, numEcBytes[0]);
|
assert_eq!(30, numEcBytes[0]);
|
||||||
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, &mut numDataBytes, &mut numEcBytes);
|
encoder::getNumDataBytesAndNumECBytesForBlockID(
|
||||||
|
3706,
|
||||||
|
1276,
|
||||||
|
81,
|
||||||
|
80,
|
||||||
|
&mut numDataBytes,
|
||||||
|
&mut numEcBytes,
|
||||||
|
);
|
||||||
assert_eq!(16, numDataBytes[0]);
|
assert_eq!(16, numDataBytes[0]);
|
||||||
assert_eq!(30, numEcBytes[0]);
|
assert_eq!(30, numEcBytes[0]);
|
||||||
}
|
}
|
||||||
@@ -485,10 +642,8 @@ r"<<
|
|||||||
let out = encoder::interleaveWithECBytes(&in_, 26, 9, 1).expect("encode");
|
let out = encoder::interleaveWithECBytes(&in_, 26, 9, 1).expect("encode");
|
||||||
let expected = &[
|
let expected = &[
|
||||||
// Data bytes.
|
// Data bytes.
|
||||||
32, 65, 205, 69, 41, 220, 46, 128, 236,
|
32, 65, 205, 69, 41, 220, 46, 128, 236, // Error correction bytes.
|
||||||
// Error correction bytes.
|
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61,
|
||||||
42, 159, 74, 221, 244, 169, 239, 150, 138, 70,
|
|
||||||
237, 85, 224, 96, 74, 219, 61
|
|
||||||
];
|
];
|
||||||
assert_eq!(expected.len(), out.getSizeInBytes());
|
assert_eq!(expected.len(), out.getSizeInBytes());
|
||||||
let mut outArray = vec![0u8; expected.len()];
|
let mut outArray = vec![0u8; expected.len()];
|
||||||
@@ -500,12 +655,10 @@ r"<<
|
|||||||
}
|
}
|
||||||
// Numbers are from http://www.swetake.com/qr/qr8.html
|
// Numbers are from http://www.swetake.com/qr/qr8.html
|
||||||
let dataBytes = &[
|
let dataBytes = &[
|
||||||
67u32, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182,
|
67u32, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 247, 7, 23, 39,
|
||||||
198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135,
|
55, 71, 87, 103, 119, 135, 151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198,
|
||||||
151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166,
|
214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 160, 236, 17, 236, 17, 236, 17,
|
||||||
182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119,
|
236, 17,
|
||||||
135, 151, 160, 236, 17, 236, 17, 236, 17, 236,
|
|
||||||
17
|
|
||||||
];
|
];
|
||||||
in_ = BitArray::new();
|
in_ = BitArray::new();
|
||||||
for dataByte in dataBytes {
|
for dataByte in dataBytes {
|
||||||
@@ -516,20 +669,14 @@ r"<<
|
|||||||
let out = encoder::interleaveWithECBytes(&in_, 134, 62, 4).expect("interleave ok");
|
let out = encoder::interleaveWithECBytes(&in_, 134, 62, 4).expect("interleave ok");
|
||||||
let expected = &[
|
let expected = &[
|
||||||
// Data bytes.
|
// Data bytes.
|
||||||
67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39,
|
67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, 118, 119, 70, 55,
|
||||||
118, 119, 70, 55, 134, 135, 86, 71, 150, 151, 102, 87, 166,
|
134, 135, 86, 71, 150, 151, 102, 87, 166, 160, 118, 103, 182, 236, 134, 119, 198, 17, 150,
|
||||||
160, 118, 103, 182, 236, 134, 119, 198, 17, 150,
|
135, 214, 236, 166, 151, 230, 17, 182, 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39,
|
||||||
135, 214, 236, 166, 151, 230, 17, 182,
|
17, // Error correction bytes.
|
||||||
166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39,
|
175, 155, 245, 236, 80, 146, 56, 74, 155, 165, 133, 142, 64, 183, 132, 13, 178, 54, 132,
|
||||||
17,
|
108, 45, 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, 190, 82, 51, 209, 199, 171,
|
||||||
// Error correction bytes.
|
54, 12, 112, 57, 113, 155, 117, 211, 164, 117, 30, 158, 225, 31, 190, 242, 38, 140, 61,
|
||||||
175, 155, 245, 236, 80, 146, 56, 74, 155, 165,
|
179, 154, 214, 138, 147, 87, 27, 96, 77, 47, 187, 49, 156, 214,
|
||||||
133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45,
|
|
||||||
113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65,
|
|
||||||
190, 82, 51, 209, 199, 171, 54, 12, 112, 57, 113, 155, 117,
|
|
||||||
211, 164, 117, 30, 158, 225, 31, 190, 242, 38,
|
|
||||||
140, 61, 179, 154, 214, 138, 147, 87, 27, 96, 77, 47,
|
|
||||||
187, 49, 156, 214
|
|
||||||
];
|
];
|
||||||
assert_eq!(expected.len(), out.getSizeInBytes());
|
assert_eq!(expected.len(), out.getSizeInBytes());
|
||||||
outArray = vec![0u8; expected.len()];
|
outArray = vec![0u8; expected.len()];
|
||||||
@@ -629,17 +776,19 @@ r"<<
|
|||||||
let dataBytes = &[32, 65, 205, 69, 41, 220, 46, 128, 236];
|
let dataBytes = &[32, 65, 205, 69, 41, 220, 46, 128, 236];
|
||||||
let ecBytes = encoder::generateECBytes(dataBytes, 17);
|
let ecBytes = encoder::generateECBytes(dataBytes, 17);
|
||||||
let expected = [
|
let expected = [
|
||||||
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61
|
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61,
|
||||||
];
|
];
|
||||||
assert_eq!(expected.len(), ecBytes.len());
|
assert_eq!(expected.len(), ecBytes.len());
|
||||||
for x in 0..expected.len() {
|
for x in 0..expected.len() {
|
||||||
// for (int x = 0; x < expected.length; x++) {
|
// for (int x = 0; x < expected.length; x++) {
|
||||||
assert_eq!(expected[x], ecBytes[x] & 0xFF);
|
assert_eq!(expected[x], ecBytes[x] & 0xFF);
|
||||||
}
|
}
|
||||||
let dataBytes = &[67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214];
|
let dataBytes = &[
|
||||||
|
67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214,
|
||||||
|
];
|
||||||
let ecBytes = encoder::generateECBytes(dataBytes, 18);
|
let ecBytes = encoder::generateECBytes(dataBytes, 18);
|
||||||
let expected = &[
|
let expected = &[
|
||||||
175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187
|
175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187,
|
||||||
];
|
];
|
||||||
assert_eq!(expected.len(), ecBytes.len());
|
assert_eq!(expected.len(), ecBytes.len());
|
||||||
for x in 0..expected.len() {
|
for x in 0..expected.len() {
|
||||||
@@ -650,7 +799,7 @@ r"<<
|
|||||||
let dataBytes = &[32, 49, 205, 69, 42, 20, 0, 236, 17];
|
let dataBytes = &[32, 49, 205, 69, 42, 20, 0, 236, 17];
|
||||||
let ecBytes = encoder::generateECBytes(dataBytes, 17);
|
let ecBytes = encoder::generateECBytes(dataBytes, 17);
|
||||||
let expected = &[
|
let expected = &[
|
||||||
0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213
|
0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213,
|
||||||
];
|
];
|
||||||
assert_eq!(expected.len(), ecBytes.len());
|
assert_eq!(expected.len(), ecBytes.len());
|
||||||
for x in 0..expected.len() {
|
for x in 0..expected.len() {
|
||||||
@@ -814,7 +963,12 @@ r"<<
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder24() {
|
fn testMinimalEncoder24() {
|
||||||
verifyMinimalEncoding("A1234567890", "ALPHANUMERIC(A1),NUMERIC(234567890)", None, false);
|
verifyMinimalEncoding(
|
||||||
|
"A1234567890",
|
||||||
|
"ALPHANUMERIC(A1),NUMERIC(234567890)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -854,75 +1008,115 @@ r"<<
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder32() {
|
fn testMinimalEncoder32() {
|
||||||
verifyMinimalEncoding("http://foo.com", "BYTE(http://foo.com)\
|
verifyMinimalEncoding(
|
||||||
", None, false);
|
"http://foo.com",
|
||||||
|
"BYTE(http://foo.com)\
|
||||||
|
",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder33() {
|
fn testMinimalEncoder33() {
|
||||||
verifyMinimalEncoding("HTTP://FOO.COM", "ALPHANUMERIC(HTTP://FOO.COM\
|
verifyMinimalEncoding(
|
||||||
)", None, false);
|
"HTTP://FOO.COM",
|
||||||
|
"ALPHANUMERIC(HTTP://FOO.COM\
|
||||||
|
)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder34() {
|
fn testMinimalEncoder34() {
|
||||||
verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781",
|
verifyMinimalEncoding(
|
||||||
"NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, false);
|
"1001114670010%01201220%107211220%140045003267781",
|
||||||
|
"NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder35() {
|
fn testMinimalEncoder35() {
|
||||||
verifyMinimalEncoding("\u{0150}", "ECI(ISO-8859-2),BYTE(.)", None, false);
|
verifyMinimalEncoding("\u{0150}", "ECI(iso-8859-2),BYTE(.)", None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder36() {
|
fn testMinimalEncoder36() {
|
||||||
verifyMinimalEncoding("\u{015C}", "ECI(ISO-8859-3),BYTE(.)", None, false);
|
verifyMinimalEncoding("\u{015C}", "ECI(iso-8859-3),BYTE(.)", None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder37() {
|
fn testMinimalEncoder37() {
|
||||||
verifyMinimalEncoding("\u{0150}\u{015C}", "ECI(UTF-8),BYTE(..)", None, false);
|
verifyMinimalEncoding("\u{0150}\u{015C}", "ECI(utf-8),BYTE(..)", None, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder38() {
|
fn testMinimalEncoder38() {
|
||||||
verifyMinimalEncoding("\u{0150}\u{0150}\u{015C}\u{015C}", "ECI(ISO-8859-2),BYTE(.\
|
verifyMinimalEncoding(
|
||||||
.),ECI(ISO-8859-3),BYTE(..)", None, false);
|
"\u{0150}\u{0150}\u{015C}\u{015C}",
|
||||||
|
"ECI(iso-8859-2),BYTE(.\
|
||||||
|
.),ECI(iso-8859-3),BYTE(..)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder39() {
|
fn testMinimalEncoder39() {
|
||||||
verifyMinimalEncoding("abcdef\u{0150}ghij", "ECI(ISO-8859-2),BYTE(abcde\
|
verifyMinimalEncoding(
|
||||||
f.ghij)", None, false);
|
"abcdef\u{0150}ghij",
|
||||||
|
"ECI(iso-8859-2),BYTE(abcde\
|
||||||
|
f.ghij)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder40() {
|
fn testMinimalEncoder40() {
|
||||||
verifyMinimalEncoding("2938928329832983\u{0150}2938928329832983\u{015C}2938928329832983",
|
verifyMinimalEncoding(
|
||||||
"NUMERIC(2938928329832983),ECI(ISO-8859-2),BYTE(.),NUMERIC(2938928329832983),ECI(ISO-8\
|
"2938928329832983\u{0150}2938928329832983\u{015C}2938928329832983",
|
||||||
859-3),BYTE(.),NUMERIC(2938928329832983)", None, false);
|
"NUMERIC(2938928329832983),ECI(iso-8859-2),BYTE(.),NUMERIC(2938928329832983),ECI(iso-8\
|
||||||
|
859-3),BYTE(.),NUMERIC(2938928329832983)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder41() {
|
fn testMinimalEncoder41() {
|
||||||
verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", "FNC1_FIRST_POSITION(),NUMERIC(100111\
|
verifyMinimalEncoding(
|
||||||
4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None,
|
"1001114670010%01201220%107211220%140045003267781",
|
||||||
true);
|
"FNC1_FIRST_POSITION(),NUMERIC(100111\
|
||||||
|
4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)",
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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)
|
||||||
verifyMinimalEncoding("Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}", "ECI(Shift_JIS),BYTE(Katakana:......)", None
|
verifyMinimalEncoding(
|
||||||
, false);
|
"Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}",
|
||||||
|
"ECI(Shift_JIS),BYTE(Katakana:......)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testMinimalEncoder43() {
|
fn testMinimalEncoder43() {
|
||||||
// The character \u30A2 encodes as double byte in Shift_JIS so KANJI is more compact in this case
|
// The character \u30A2 encodes as double byte in Shift_JIS so KANJI is more compact in this case
|
||||||
verifyMinimalEncoding("Katakana:\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}", "BYTE(Katakana:),KANJI(......)", None,
|
verifyMinimalEncoding(
|
||||||
false);
|
"Katakana:\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}",
|
||||||
|
"BYTE(Katakana:),KANJI(......)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -930,20 +1124,33 @@ r"<<
|
|||||||
// 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
|
||||||
verifyMinimalEncoding("Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}", "ECI(Shift_JIS),BYTE(Katakana:.a.a.a\
|
verifyMinimalEncoding(
|
||||||
.a.a.)", None, false);
|
"Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}",
|
||||||
|
"ECI(Shift_JIS),BYTE(Katakana:.a.a.a.a.a.)",
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verifyMinimalEncoding( input:&str, expectedRXingResult:&str, priorityCharset:Option<EncodingRef>, isGS1:bool)
|
fn verifyMinimalEncoding(
|
||||||
{
|
input: &str,
|
||||||
let result = MinimalEncoder::encode_with_details(input, None, priorityCharset.unwrap_or(encoding::all::ISO_8859_1), isGS1,
|
expectedRXingResult: &str,
|
||||||
ErrorCorrectionLevel::L).expect("encode");
|
priorityCharset: Option<EncodingRef>,
|
||||||
|
isGS1: bool,
|
||||||
|
) {
|
||||||
|
let result = MinimalEncoder::encode_with_details(
|
||||||
|
input,
|
||||||
|
None,
|
||||||
|
priorityCharset.unwrap_or(encoding::all::ISO_8859_1),
|
||||||
|
isGS1,
|
||||||
|
ErrorCorrectionLevel::L,
|
||||||
|
)
|
||||||
|
.expect("encode");
|
||||||
assert_eq!(result.to_string(), expectedRXingResult);
|
assert_eq!(result.to_string(), expectedRXingResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verifyGS1EncodedData(qrCode: &QRCode) {
|
fn verifyGS1EncodedData(qrCode: &QRCode) {
|
||||||
let expected =
|
let expected = r"<<
|
||||||
r"<<
|
|
||||||
mode: ALPHANUMERIC
|
mode: ALPHANUMERIC
|
||||||
ecLevel: H
|
ecLevel: H
|
||||||
version: 2
|
version: 2
|
||||||
@@ -980,8 +1187,7 @@ r"<<
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn verifyNotGS1EncodedData(qrCode: &QRCode) {
|
fn verifyNotGS1EncodedData(qrCode: &QRCode) {
|
||||||
let expected =
|
let expected = r"<<
|
||||||
r"<<
|
|
||||||
mode: ALPHANUMERIC
|
mode: ALPHANUMERIC
|
||||||
ecLevel: H
|
ecLevel: H
|
||||||
version: 1
|
version: 1
|
||||||
@@ -1014,6 +1220,8 @@ r"<<
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn shiftJISString(bytes: &[u8]) -> String {
|
fn shiftJISString(bytes: &[u8]) -> String {
|
||||||
SHIFT_JIS_CHARSET.decode(bytes,encoding::DecoderTrap::Strict).expect("decode should be ok")
|
SHIFT_JIS_CHARSET
|
||||||
|
.decode(bytes, encoding::DecoderTrap::Strict)
|
||||||
|
.expect("decode should be ok")
|
||||||
// return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
|
// return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,9 +357,12 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
|
pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
|
||||||
let bytes = SHIFT_JIS_CHARSET
|
let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET
|
||||||
.encode(content, encoding::EncoderTrap::Strict)
|
.encode(content, encoding::EncoderTrap::Strict) {
|
||||||
.expect("encode");
|
byt
|
||||||
|
}else {
|
||||||
|
return false
|
||||||
|
};
|
||||||
let length = bytes.len();
|
let length = bytes.len();
|
||||||
if length % 2 != 0 {
|
if length % 2 != 0 {
|
||||||
return false;
|
return false;
|
||||||
@@ -367,7 +370,7 @@ pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < length {
|
while i < length {
|
||||||
// for (int i = 0; i < length; i += 2) {
|
// for (int i = 0; i < length; i += 2) {
|
||||||
let byte1 = bytes[i] & 0xFF;
|
let byte1 = bytes[i];
|
||||||
if (byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB) {
|
if (byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ use crate::{
|
|||||||
Exceptions,
|
Exceptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use unicode_segmentation::{Graphemes, UnicodeSegmentation};
|
||||||
|
|
||||||
use super::encoder;
|
use super::encoder;
|
||||||
|
|
||||||
pub enum VersionSize {
|
pub enum VersionSize {
|
||||||
@@ -84,7 +86,7 @@ impl fmt::Display for VersionSize {
|
|||||||
* @author Alex Geller
|
* @author Alex Geller
|
||||||
*/
|
*/
|
||||||
pub struct MinimalEncoder {
|
pub struct MinimalEncoder {
|
||||||
stringToEncode: String,
|
stringToEncode: Vec<String>,
|
||||||
isGS1: bool,
|
isGS1: bool,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
ecLevel: ErrorCorrectionLevel,
|
ecLevel: ErrorCorrectionLevel,
|
||||||
@@ -110,9 +112,12 @@ impl MinimalEncoder {
|
|||||||
ecLevel: ErrorCorrectionLevel,
|
ecLevel: ErrorCorrectionLevel,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stringToEncode: String::from(stringToEncode),
|
stringToEncode: stringToEncode
|
||||||
|
.graphemes(true)
|
||||||
|
.map(|p| p.to_owned())
|
||||||
|
.collect::<Vec<String>>(),
|
||||||
isGS1,
|
isGS1,
|
||||||
encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, -1),
|
encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, None),
|
||||||
ecLevel,
|
ecLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,23 +227,34 @@ impl MinimalEncoder {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isNumeric(c: char) -> bool {
|
pub fn isNumeric(c: &str) -> bool {
|
||||||
return c >= '0' && c <= '9';
|
if c.len() == 1 {
|
||||||
|
let ch = c.chars().nth(0).unwrap();
|
||||||
|
ch >= '0' && ch <= '9'
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
// return c >= '0' && c <= '9';
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isDoubleByteKanji(c: char) -> bool {
|
pub fn isDoubleByteKanji(c: &str) -> bool {
|
||||||
return encoder::isOnlyDoubleByteKanji(&String::from(c));
|
return encoder::isOnlyDoubleByteKanji(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isAlphanumeric(c: char) -> bool {
|
pub fn isAlphanumeric(c: &str) -> bool {
|
||||||
return encoder::getAlphanumericCode(c as u8 as u32) != -1;
|
if c.len() == 1 {
|
||||||
|
let ch = c.chars().nth(0).unwrap();
|
||||||
|
encoder::getAlphanumericCode(ch as u32) != -1
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
// return encoder::getAlphanumericCode(c as u8 as u32) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canEncode(&self, mode: &Mode, c: char) -> bool {
|
pub fn canEncode(&self, mode: &Mode, c: &str) -> bool {
|
||||||
match mode {
|
match mode {
|
||||||
Mode::NUMERIC => Self::isNumeric(c),
|
Mode::NUMERIC => Self::isNumeric(c),
|
||||||
Mode::ALPHANUMERIC => Self::isAlphanumeric(c),
|
Mode::ALPHANUMERIC => Self::isAlphanumeric(c),
|
||||||
Mode::STRUCTURED_APPEND => todo!(),
|
|
||||||
Mode::BYTE => true,
|
Mode::BYTE => true,
|
||||||
Mode::KANJI => Self::isDoubleByteKanji(c),
|
Mode::KANJI => Self::isDoubleByteKanji(c),
|
||||||
_ => false, // any character can be encoded as byte(s). Up to the caller to manage splitting into
|
_ => false, // any character can be encoded as byte(s). Up to the caller to manage splitting into
|
||||||
@@ -305,7 +321,8 @@ impl MinimalEncoder {
|
|||||||
let priorityEncoderIndex = self.encoders.getPriorityEncoderIndex();
|
let priorityEncoderIndex = self.encoders.getPriorityEncoderIndex();
|
||||||
if priorityEncoderIndex >= 0
|
if priorityEncoderIndex >= 0
|
||||||
&& self.encoders.canEncode(
|
&& self.encoders.canEncode(
|
||||||
self.stringToEncode.chars().nth(from as usize).unwrap() as i16,
|
// self.stringToEncode.chars().nth(from as usize).unwrap() as i16,
|
||||||
|
&self.stringToEncode[from as usize],
|
||||||
priorityEncoderIndex,
|
priorityEncoderIndex,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -317,7 +334,7 @@ impl MinimalEncoder {
|
|||||||
// for (int i = start; i < end; i++) {
|
// for (int i = start; i < end; i++) {
|
||||||
if self
|
if self
|
||||||
.encoders
|
.encoders
|
||||||
.canEncode(self.stringToEncode.chars().nth(from).unwrap() as i16, i)
|
.canEncode(&self.stringToEncode.get(from).unwrap(), i)
|
||||||
{
|
{
|
||||||
self.addEdge(
|
self.addEdge(
|
||||||
edges,
|
edges,
|
||||||
@@ -330,13 +347,13 @@ impl MinimalEncoder {
|
|||||||
previous.clone(),
|
previous.clone(),
|
||||||
version,
|
version,
|
||||||
self.encoders.clone(),
|
self.encoders.clone(),
|
||||||
&self.stringToEncode,
|
self.stringToEncode.clone(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.canEncode(&Mode::KANJI, self.stringToEncode.chars().nth(from).unwrap()) {
|
if self.canEncode(&Mode::KANJI, &self.stringToEncode.get(from).unwrap()) {
|
||||||
self.addEdge(
|
self.addEdge(
|
||||||
edges,
|
edges,
|
||||||
from,
|
from,
|
||||||
@@ -348,16 +365,13 @@ impl MinimalEncoder {
|
|||||||
previous.clone(),
|
previous.clone(),
|
||||||
version,
|
version,
|
||||||
self.encoders.clone(),
|
self.encoders.clone(),
|
||||||
&self.stringToEncode,
|
self.stringToEncode.clone(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputLength = self.stringToEncode.len();
|
let inputLength = self.stringToEncode.len();
|
||||||
if self.canEncode(
|
if self.canEncode(&Mode::ALPHANUMERIC, self.stringToEncode.get(from).unwrap()) {
|
||||||
&Mode::ALPHANUMERIC,
|
|
||||||
self.stringToEncode.chars().nth(from).unwrap(),
|
|
||||||
) {
|
|
||||||
self.addEdge(
|
self.addEdge(
|
||||||
edges,
|
edges,
|
||||||
from,
|
from,
|
||||||
@@ -368,7 +382,7 @@ impl MinimalEncoder {
|
|||||||
if from + 1 >= inputLength
|
if from + 1 >= inputLength
|
||||||
|| !self.canEncode(
|
|| !self.canEncode(
|
||||||
&Mode::ALPHANUMERIC,
|
&Mode::ALPHANUMERIC,
|
||||||
self.stringToEncode.chars().nth(from + 1).unwrap(),
|
self.stringToEncode.get(from + 1).unwrap(),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
1
|
1
|
||||||
@@ -378,15 +392,12 @@ impl MinimalEncoder {
|
|||||||
previous.clone(),
|
previous.clone(),
|
||||||
version,
|
version,
|
||||||
self.encoders.clone(),
|
self.encoders.clone(),
|
||||||
&self.stringToEncode,
|
self.stringToEncode.clone(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.canEncode(
|
if self.canEncode(&Mode::NUMERIC, self.stringToEncode.get(from).unwrap()) {
|
||||||
&Mode::NUMERIC,
|
|
||||||
self.stringToEncode.chars().nth(from).unwrap(),
|
|
||||||
) {
|
|
||||||
self.addEdge(
|
self.addEdge(
|
||||||
edges,
|
edges,
|
||||||
from,
|
from,
|
||||||
@@ -395,17 +406,15 @@ impl MinimalEncoder {
|
|||||||
from,
|
from,
|
||||||
0,
|
0,
|
||||||
if from + 1 >= inputLength
|
if from + 1 >= inputLength
|
||||||
|| !self.canEncode(
|
|| !self
|
||||||
&Mode::NUMERIC,
|
.canEncode(&Mode::NUMERIC, self.stringToEncode.get(from + 1).unwrap())
|
||||||
self.stringToEncode.chars().nth(from + 1).unwrap(),
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
if from + 2 >= inputLength
|
if from + 2 >= inputLength
|
||||||
|| !self.canEncode(
|
|| !self.canEncode(
|
||||||
&Mode::NUMERIC,
|
&Mode::NUMERIC,
|
||||||
self.stringToEncode.chars().nth(from + 2).unwrap(),
|
self.stringToEncode.get(from + 2).unwrap(),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
2
|
2
|
||||||
@@ -416,7 +425,7 @@ impl MinimalEncoder {
|
|||||||
previous.clone(),
|
previous.clone(),
|
||||||
version,
|
version,
|
||||||
self.encoders.clone(),
|
self.encoders.clone(),
|
||||||
&self.stringToEncode,
|
self.stringToEncode.clone(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -535,6 +544,7 @@ impl MinimalEncoder {
|
|||||||
* The encodation ECI(UTF-8),BYTE(XXYY) is longer with a size of 88.
|
* The encodation ECI(UTF-8),BYTE(XXYY) is longer with a size of 88.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// let inputLength = self.stringToEncode.chars().count();
|
||||||
let inputLength = self.stringToEncode.len();
|
let inputLength = self.stringToEncode.len();
|
||||||
|
|
||||||
// Array that represents vertices. There is a vertex for every character, encoding and mode. The vertex contains
|
// Array that represents vertices. There is a vertex for every character, encoding and mode. The vertex contains
|
||||||
@@ -580,6 +590,9 @@ impl MinimalEncoder {
|
|||||||
return Err(Exceptions::WriterException(format!(
|
return Err(Exceptions::WriterException(format!(
|
||||||
r#"Internal error: failed to encode "{}"#,
|
r#"Internal error: failed to encode "{}"#,
|
||||||
self.stringToEncode
|
self.stringToEncode
|
||||||
|
.iter()
|
||||||
|
.map(|x| String::from(x))
|
||||||
|
.collect::<String>() //fold("", |acc,x| [acc,&x].concat())
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Ok(RXingResultList::new(
|
Ok(RXingResultList::new(
|
||||||
@@ -591,7 +604,7 @@ impl MinimalEncoder {
|
|||||||
self.isGS1,
|
self.isGS1,
|
||||||
&self.ecLevel,
|
&self.ecLevel,
|
||||||
self.encoders.clone(),
|
self.encoders.clone(),
|
||||||
&self.stringToEncode,
|
self.stringToEncode.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,7 +617,7 @@ pub struct Edge {
|
|||||||
previous: Option<Rc<Edge>>,
|
previous: Option<Rc<Edge>>,
|
||||||
cachedTotalSize: u32,
|
cachedTotalSize: u32,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
stringToEncode: String,
|
stringToEncode: Vec<String>,
|
||||||
}
|
}
|
||||||
impl Edge {
|
impl Edge {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -615,7 +628,7 @@ impl Edge {
|
|||||||
previous: Option<Rc<Edge>>,
|
previous: Option<Rc<Edge>>,
|
||||||
version: VersionRef,
|
version: VersionRef,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
stringToEncode: &'_ str,
|
stringToEncode: Vec<String>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let nci = if mode == Mode::BYTE || previous.is_none() {
|
let nci = if mode == Mode::BYTE || previous.is_none() {
|
||||||
charsetEncoderIndex
|
charsetEncoderIndex
|
||||||
@@ -628,7 +641,7 @@ impl Edge {
|
|||||||
charsetEncoderIndex: nci,
|
charsetEncoderIndex: nci,
|
||||||
characterLength,
|
characterLength,
|
||||||
previous: previous.clone(),
|
previous: previous.clone(),
|
||||||
stringToEncode: String::from(stringToEncode),
|
stringToEncode: stringToEncode.clone(),
|
||||||
cachedTotalSize: {
|
cachedTotalSize: {
|
||||||
let mut size = if previous.is_some() {
|
let mut size = if previous.is_some() {
|
||||||
previous.as_ref().unwrap().cachedTotalSize
|
previous.as_ref().unwrap().cachedTotalSize
|
||||||
@@ -657,13 +670,22 @@ impl Edge {
|
|||||||
}
|
}
|
||||||
Mode::ALPHANUMERIC => size += if characterLength == 1 { 6 } else { 11 },
|
Mode::ALPHANUMERIC => size += if characterLength == 1 { 6 } else { 11 },
|
||||||
Mode::BYTE => {
|
Mode::BYTE => {
|
||||||
|
let n: String = stringToEncode
|
||||||
|
.iter()
|
||||||
|
.skip(fromPosition as usize)
|
||||||
|
.take(characterLength as usize)
|
||||||
|
.map(|x| String::from(x))
|
||||||
|
.collect();
|
||||||
size += 8 * encoders
|
size += 8 * encoders
|
||||||
.encode_string(
|
.encode_string(&n, charsetEncoderIndex as usize)
|
||||||
&stringToEncode[fromPosition as usize
|
|
||||||
..(fromPosition + characterLength as usize)],
|
|
||||||
charsetEncoderIndex as usize,
|
|
||||||
)
|
|
||||||
.len() as u32;
|
.len() as u32;
|
||||||
|
// size += 8 * encoders
|
||||||
|
// .encode_string(
|
||||||
|
// &stringToEncode[fromPosition as usize
|
||||||
|
// ..(fromPosition + characterLength as usize)],
|
||||||
|
// charsetEncoderIndex as usize,
|
||||||
|
// )
|
||||||
|
// .len() as u32;
|
||||||
if needECI {
|
if needECI {
|
||||||
size += 4 + 8; // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long
|
size += 4 + 8; // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long
|
||||||
}
|
}
|
||||||
@@ -743,7 +765,7 @@ impl RXingResultList {
|
|||||||
isGS1: bool,
|
isGS1: bool,
|
||||||
ecLevel: &ErrorCorrectionLevel,
|
ecLevel: &ErrorCorrectionLevel,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
stringToEncode: &str,
|
stringToEncode: Vec<String>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut length = 0;
|
let mut length = 0;
|
||||||
let mut current = Some(solution);
|
let mut current = Some(solution);
|
||||||
@@ -772,7 +794,7 @@ impl RXingResultList {
|
|||||||
current.as_ref().unwrap().charsetEncoderIndex,
|
current.as_ref().unwrap().charsetEncoderIndex,
|
||||||
length,
|
length,
|
||||||
encoders.clone(),
|
encoders.clone(),
|
||||||
stringToEncode,
|
stringToEncode.clone(),
|
||||||
version,
|
version,
|
||||||
));
|
));
|
||||||
length = 0;
|
length = 0;
|
||||||
@@ -785,7 +807,7 @@ impl RXingResultList {
|
|||||||
current.as_ref().unwrap().charsetEncoderIndex,
|
current.as_ref().unwrap().charsetEncoderIndex,
|
||||||
0,
|
0,
|
||||||
encoders.clone(),
|
encoders.clone(),
|
||||||
stringToEncode,
|
stringToEncode.clone(),
|
||||||
version,
|
version,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -805,23 +827,41 @@ impl RXingResultList {
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
encoders.clone(),
|
encoders.clone(),
|
||||||
stringToEncode,
|
stringToEncode.clone(),
|
||||||
version,
|
version,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let first = list.get(0);
|
let first = list.get(0);
|
||||||
// prepend or insert a FNC1_FIRST_POSITION after the ECI (if any)
|
// prepend or insert a FNC1_FIRST_POSITION after the ECI (if any)
|
||||||
if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI && containsECI {
|
if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI {//&& containsECI {
|
||||||
list.push(RXingResultNode::new(
|
list.insert(
|
||||||
|
if first.as_ref().unwrap().mode != Mode::ECI {
|
||||||
|
//first
|
||||||
|
list.len()
|
||||||
|
} else {
|
||||||
|
//second
|
||||||
|
list.len()-1
|
||||||
|
},
|
||||||
|
RXingResultNode::new(
|
||||||
Mode::FNC1_FIRST_POSITION,
|
Mode::FNC1_FIRST_POSITION,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
encoders.clone(),
|
encoders.clone(),
|
||||||
stringToEncode,
|
stringToEncode.clone(),
|
||||||
version,
|
version,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
|
// list.push(RXingResultNode::new(
|
||||||
|
// Mode::FNC1_FIRST_POSITION,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// encoders.clone(),
|
||||||
|
// stringToEncode.clone(),
|
||||||
|
// version,
|
||||||
|
// ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,7 +977,7 @@ struct RXingResultNode {
|
|||||||
characterLength: u32,
|
characterLength: u32,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
version: VersionRef,
|
version: VersionRef,
|
||||||
stringToEncode: String,
|
stringToEncode: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RXingResultNode {
|
impl RXingResultNode {
|
||||||
@@ -947,7 +987,7 @@ impl RXingResultNode {
|
|||||||
charsetEncoderIndex: usize,
|
charsetEncoderIndex: usize,
|
||||||
characterLength: u32,
|
characterLength: u32,
|
||||||
encoders: ECIEncoderSet,
|
encoders: ECIEncoderSet,
|
||||||
stringToEncode: &str,
|
stringToEncode: Vec<String>,
|
||||||
version: VersionRef,
|
version: VersionRef,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -956,7 +996,7 @@ impl RXingResultNode {
|
|||||||
charsetEncoderIndex,
|
charsetEncoderIndex,
|
||||||
characterLength,
|
characterLength,
|
||||||
encoders,
|
encoders,
|
||||||
stringToEncode: String::from(stringToEncode),
|
stringToEncode,
|
||||||
version,
|
version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1023,8 +1063,9 @@ impl RXingResultNode {
|
|||||||
if self.mode == Mode::BYTE {
|
if self.mode == Mode::BYTE {
|
||||||
self.encoders
|
self.encoders
|
||||||
.encode_string(
|
.encode_string(
|
||||||
&self.stringToEncode[self.fromPosition as usize
|
// &self.stringToEncode[self.fromPosition as usize
|
||||||
..(self.fromPosition + self.characterLength as usize)],
|
// ..(self.fromPosition + self.characterLength as usize)],
|
||||||
|
&self.stringToEncode.get(self.fromPosition as usize).unwrap(),
|
||||||
self.charsetEncoderIndex as usize,
|
self.charsetEncoderIndex as usize,
|
||||||
)
|
)
|
||||||
.len() as u32
|
.len() as u32
|
||||||
@@ -1053,8 +1094,9 @@ impl RXingResultNode {
|
|||||||
} else if self.characterLength > 0 {
|
} else if self.characterLength > 0 {
|
||||||
// append data
|
// append data
|
||||||
encoder::appendBytes(
|
encoder::appendBytes(
|
||||||
&self.stringToEncode[self.fromPosition as usize
|
// &self.stringToEncode[self.fromPosition as usize
|
||||||
..(self.fromPosition + self.characterLength as usize)],
|
// ..(self.fromPosition + self.characterLength as usize)],
|
||||||
|
&self.stringToEncode.get(self.fromPosition).unwrap(),
|
||||||
self.mode,
|
self.mode,
|
||||||
bits,
|
bits,
|
||||||
self.encoders.getCharset(self.charsetEncoderIndex as usize),
|
self.encoders.getCharset(self.charsetEncoderIndex as usize),
|
||||||
@@ -1067,7 +1109,7 @@ impl RXingResultNode {
|
|||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
for i in 0..s.chars().count() {
|
for i in 0..s.chars().count() {
|
||||||
// for (int i = 0; i < s.length(); i++) {
|
// for (int i = 0; i < s.length(); i++) {
|
||||||
if (s.chars().nth(i).unwrap() as u8) < 32 || (s.chars().nth(i).unwrap() as u8) > 126 {
|
if (s.chars().nth(i).unwrap() as u32) < 32 || (s.chars().nth(i).unwrap() as u32) > 126 {
|
||||||
result.push('.');
|
result.push('.');
|
||||||
} else {
|
} else {
|
||||||
result.push(s.chars().nth(i).unwrap());
|
result.push(s.chars().nth(i).unwrap());
|
||||||
@@ -1089,10 +1131,18 @@ impl fmt::Display for RXingResultNode {
|
|||||||
.name(),
|
.name(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
result.push_str(&Self::makePrintable(
|
let sub_string: String = self
|
||||||
&self.stringToEncode[self.fromPosition as usize
|
.stringToEncode
|
||||||
..(self.fromPosition + self.characterLength as usize)],
|
.iter()
|
||||||
));
|
.skip(self.fromPosition as usize)
|
||||||
|
.take(self.characterLength as usize)
|
||||||
|
.map(|x| String::from(x))
|
||||||
|
.collect();
|
||||||
|
// result.push_str(&Self::makePrintable(
|
||||||
|
// &self.stringToEncode[self.fromPosition as usize
|
||||||
|
// ..(self.fromPosition + self.characterLength as usize)],
|
||||||
|
// ));
|
||||||
|
result.push_str(&Self::makePrintable(&sub_string));
|
||||||
}
|
}
|
||||||
result.push(')');
|
result.push(')');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user