partially passing encoder

This commit is contained in:
Henry Schimke
2022-09-25 16:52:12 -05:00
parent fb08ee0e34
commit b2a460a226
10 changed files with 769 additions and 512 deletions

View File

@@ -34,6 +34,8 @@
// import java.util.Random;
// import java.util.TreeSet;
use rand::Rng;
use crate::{aztec::decoder, common::BitMatrix, exceptions::Exceptions};
use super::{
@@ -69,7 +71,7 @@ fn testErrorInParameterLocatorNotCompact() {
fn testErrorInParameterLocator(data: &str) {
let aztec = encoder::encoder::encode(data, 25, encoder::encoder::DEFAULT_AZTEC_LAYERS)
.expect("encode should create");
let random = rand::thread_rng(); //Random(aztec.getMatrix().hashCode()); // pseudo-random, but deterministic
let mut random = rand::thread_rng(); //Random(aztec.getMatrix().hashCode()); // pseudo-random, but deterministic
let layers = aztec.getLayers();
let compact = aztec.isCompact();
let orientationPoints = getOrientationPoints(&aztec);
@@ -78,24 +80,24 @@ fn testErrorInParameterLocator(data: &str) {
for matrix in getRotations(aztec.getMatrix()) {
// for (BitMatrix matrix : getRotations(aztec.getMatrix())) {
// Systematically try every possible 1- and 2-bit error.
for error1 in 0..orientationPoints.size() {
for error1 in 0..orientationPoints.len() {
// for (int error1 = 0; error1 < orientationPoints.size(); error1++) {
for error2 in error1..orientationPoints.size() {
for error2 in error1..orientationPoints.len() {
// for (int error2 = error1; error2 < orientationPoints.size(); error2++) {
let copy = if isMirror {
let mut copy = if isMirror {
transpose(&matrix)
} else {
clone(&matrix)
};
copy.flip(
orientationPoints.get(error1).getX(),
orientationPoints.get(error1).getY(),
copy.flip_coords(
orientationPoints.get(error1).unwrap().getX() as u32,
orientationPoints.get(error1).unwrap().getY() as u32,
);
if error2 > error1 {
// if error2 == error1, we only test a single error
copy.flip(
orientationPoints.get(error2).getX(),
orientationPoints.get(error2).getY(),
copy.flip_coords(
orientationPoints.get(error2).unwrap().getX() as u32,
orientationPoints.get(error2).unwrap().getY() as u32,
);
}
// The detector doesn't seem to work when matrix bits are only 1x1. So magnify.
@@ -111,17 +113,17 @@ fn testErrorInParameterLocator(data: &str) {
// Try a few random three-bit errors;
for i in 0..5 {
// for (int i = 0; i < 5; i++) {
let copy = clone(&matrix);
let errors = Vec::new();
while errors.size() < 3 {
let mut copy = clone(&matrix);
let mut errors = Vec::new();
while errors.len() < 3 {
// Quick and dirty way of getting three distinct integers between 1 and n.
errors.push(random.nextInt(orientationPoints.size()));
errors.push(random.gen_range(0..=orientationPoints.len()));
}
for error in errors {
// for (int error : errors) {
copy.flip(
orientationPoints.get(error).getX(),
orientationPoints.get(error).getY(),
copy.flip_coords(
orientationPoints.get(error).unwrap().getX() as u32,
orientationPoints.get(error).unwrap().getY() as u32,
);
}
// try {
@@ -147,7 +149,7 @@ fn testErrorInParameterLocator(data: &str) {
// Zooms a bit matrix so that each bit is factor x factor
fn makeLarger(input: &BitMatrix, factor: u32) -> BitMatrix {
let width = input.getWidth();
let output = BitMatrix::with_single_dimension(width * factor);
let mut output = BitMatrix::with_single_dimension(width * factor);
for inputY in 0..width {
// for (int inputY = 0; inputY < width; inputY++) {
for inputX in 0..width {
@@ -165,13 +167,13 @@ fn getRotations(matrix0: &BitMatrix) -> Vec<BitMatrix> {
let matrix90 = rotateRight(matrix0);
let matrix180 = rotateRight(&matrix90);
let matrix270 = rotateRight(&matrix180);
vec![*matrix0, matrix90, matrix180, matrix270]
vec![matrix0.clone(), matrix90, matrix180, matrix270]
}
// Rotates a square BitMatrix to the right by 90 degrees
fn rotateRight(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {
@@ -188,7 +190,7 @@ fn rotateRight(input: &BitMatrix) -> BitMatrix {
// matrix to the right, and then flipping it left-to-right
fn transpose(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {
@@ -203,7 +205,7 @@ fn transpose(input: &BitMatrix) -> BitMatrix {
fn clone(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {
@@ -217,21 +219,21 @@ fn clone(input: &BitMatrix) -> BitMatrix {
}
fn getOrientationPoints(code: &AztecCode) -> Vec<Point> {
let center = code.getMatrix().getWidth() / 2;
let center = code.getMatrix().getWidth() as i32 / 2;
let offset = if code.isCompact() { 5 } else { 7 };
let result = Vec::new();
let mut xSign = -1;
let mut result = Vec::new();
let mut xSign: i32 = -1;
while xSign <= 1 {
// for (int xSign = -1; xSign <= 1; xSign += 2) {
let mut ySign = -1;
let mut ySign: i32 = -1;
while ySign <= 1 {
// for (int ySign = -1; ySign <= 1; ySign += 2) {
result.add(Point::new(center + xSign * offset, center + ySign * offset));
result.add(Point::new(
result.push(Point::new(center + xSign * offset, center + ySign * offset));
result.push(Point::new(
center + xSign * (offset - 1),
center + ySign * offset,
));
result.add(Point::new(
result.push(Point::new(
center + xSign * offset,
center + ySign * (offset - 1),
));

File diff suppressed because it is too large Load Diff

View File

@@ -20,37 +20,37 @@ use crate::common::BitArray;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BinaryShiftToken {
binaryShiftStart: u32,
binaryShiftByteCount: u32,
binary_shift_start: u32,
binary_shift_byte_count: u32,
}
impl BinaryShiftToken {
pub fn new(binaryShiftStart: u32, binaryShiftByteCount: u32) -> Self {
pub fn new(binary_shift_start: u32, binary_shift_byte_count: u32) -> Self {
Self {
binaryShiftStart,
binaryShiftByteCount,
binary_shift_start,
binary_shift_byte_count,
}
}
pub fn appendTo(&self, bitArray: &mut BitArray, text: &[u8]) {
let bsbc = self.binaryShiftByteCount as usize;
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
let bsbc = self.binary_shift_byte_count as usize;
for i in 0..bsbc {
// for (int i = 0; i < bsbc; i++) {
if (i == 0 || (i == 31 && bsbc <= 62)) {
if i == 0 || (i == 31 && bsbc <= 62) {
// We need a header before the first character, and before
// character 31 when the total byte code is <= 62
bitArray.appendBits(31, 5); // BINARY_SHIFT
if (bsbc > 62) {
bitArray.appendBits(bsbc as u32 - 31, 16);
} else if (i == 0) {
bit_array.appendBits(31, 5).unwrap(); // BINARY_SHIFT
if bsbc > 62 {
bit_array.appendBits(bsbc as u32 - 31, 16).unwrap();
} else if i == 0 {
// 1 <= binaryShiftByteCode <= 62
bitArray.appendBits(bsbc.min(31) as u32, 5);
bit_array.appendBits(bsbc.min(31) as u32, 5).unwrap();
} else {
// 32 <= binaryShiftCount <= 62 and i == 31
bitArray.appendBits(bsbc as u32 - 31, 5);
bit_array.appendBits(bsbc as u32 - 31, 5).unwrap();
}
}
bitArray.appendBits(text[self.binaryShiftStart as usize + i].into(), 8);
bit_array.appendBits(text[self.binary_shift_start as usize + i].into(), 8).expect("should never fail to append");
}
}
@@ -65,8 +65,8 @@ impl fmt::Display for BinaryShiftToken {
write!(
f,
"<{}::{}>",
self.binaryShiftStart,
(self.binaryShiftStart + self.binaryShiftByteCount - 1)
self.binary_shift_start,
(self.binary_shift_start + self.binary_shift_byte_count - 1)
)
}
}

View File

@@ -72,8 +72,8 @@ pub fn encode(
userSpecifiedLayers: u32,
) -> Result<AztecCode, Exceptions> {
let bytes = encoding::all::ISO_8859_1
.encode(data, encoding::EncoderTrap::Replace)
.unwrap();
.encode(data, encoding::EncoderTrap::Strict)
.expect("must encode cleanly in ISO_8859_1");
encode_bytes(&bytes, minECCPercent, userSpecifiedLayers)
}
@@ -209,6 +209,7 @@ pub fn encode_bytes_with_charset(
layers = if compact { i + 1 } else { i };
totalBitsInLayerVar = totalBitsInLayer(layers, compact);
if totalSizeBits > totalBitsInLayerVar as u32 {
i += 1;
continue;
}
// [Re]stuff the bits if this is the first opportunity, or if the
@@ -220,6 +221,7 @@ pub fn encode_bytes_with_charset(
let usableBitsInLayers = totalBitsInLayerVar - (totalBitsInLayerVar % wordSize);
if compact && stuffedBits.getSize() as u32 > wordSize * 64 {
// Compact format only allows 64 data words, though C4 can hold more words than that
i += 1;
continue;
}
if stuffedBits.getSize()as u32 + eccBits<= usableBitsInLayers {
@@ -487,32 +489,32 @@ fn getGF(wordSize: usize) -> Result<GenericGF, Exceptions> {
// }
}
pub fn stuffBits(bits: &BitArray, wordSize: usize) -> BitArray {
pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
let mut out = BitArray::new();
let n = bits.getSize();
let mask = (1 << wordSize) - 2;
let mut i = 0;
let n = bits.getSize() as isize;
let mask = (1 << word_size) - 2;
let mut i:isize = 0;
while i < n {
// for (int i = 0; i < n; i += wordSize) {
let mut word = 0;
for j in 0..wordSize {
for j in 0..word_size as isize {
// for (int j = 0; j < wordSize; j++) {
if i + j >= n || bits.get(i + j) {
word |= 1 << (wordSize - 1 - j);
if i + j >= n || bits.get((i + j) as usize) {
word |= 1 << (word_size as isize - 1 - j);
}
}
if (word & mask) == mask {
out.appendBits(word & mask, wordSize);
out.appendBits(word & mask, word_size).unwrap();
i -= 1;
} else if (word & mask) == 0 {
out.appendBits(word | 1, wordSize);
out.appendBits(word | 1, word_size).unwrap();
i -= 1;
} else {
out.appendBits(word, wordSize);
out.appendBits(word, word_size).unwrap();
}
i += wordSize;
i += word_size as isize;
}
return out;
}

View File

@@ -125,27 +125,28 @@ impl HighLevelEncoder {
// }
char_map[Self::MODE_DIGIT][b',' as usize] = 12;
char_map[Self::MODE_DIGIT][b'.' as usize] = 13;
let mixedTable = [
let mixed_table = [
'\0', ' ', '\u{1}', '\u{2}', '\u{3}', '\u{4}', '\u{5}', '\u{6}', '\u{7}', '\u{8}',
'\t', '\n', '\u{13}', '\u{f}', '\r', '\u{33}', '\u{34}', '\u{35}', '\u{36}', '\u{37}',
'@', '\\', '^', '_', '`', '|', '~', '\u{177}',
];
let mut i = 0;
while i < mixedTable.len() {
char_map[Self::MODE_MIXED][mixedTable[i] as u8 as usize] = i as u8;
while i < mixed_table.len() {
char_map[Self::MODE_MIXED][mixed_table[i] as u8 as usize] = i as u8;
i += 1;
}
// for (int i = 0; i < mixedTable.length; i++) {
// CHAR_MAP[MODE_MIXED][mixedTable[i]] = i;
// }
let punctTable = [
'\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*',
'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}',
b'\0', b'\r', b'\0', b'\0', b'\0', b'\0', b'!', b'\'', b'#', b'$', b'%', b'&', b'\'',
b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b':', b';', b'<', b'=', b'>', b'?',
b'[', b']', b'{', b'}',
];
let mut i = 0;
while i < punctTable.len() {
if punctTable[i] as u8 > 0u8 {
char_map[Self::MODE_PUNCT][punctTable[i] as u8 as usize] = i as u8;
if punctTable[i] > 0u8 {
char_map[Self::MODE_PUNCT][punctTable[i] as usize] = i as u8;
}
i += 1;
}
@@ -230,7 +231,7 @@ impl HighLevelEncoder {
pub fn new(text: Vec<u8>) -> Self {
Self {
text,
charset: encoding::all::UTF_8,
charset: encoding::all::ISO_8859_1,
}
}
@@ -242,9 +243,11 @@ impl HighLevelEncoder {
* @return text represented by this encoder encoded as a {@link BitArray}
*/
pub fn encode(&self) -> Result<BitArray, Exceptions> {
let mut initialState = 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) {
initialState = initialState.appendFLGn(CharacterSetECI::getValue(&eci))?;
if eci != CharacterSetECI::ISO8859_1 {
initial_state = initial_state.appendFLGn(CharacterSetECI::getValue(&eci))?;
}
} else {
return Err(Exceptions::IllegalArgumentException(
"No ECI code for character set".to_owned(),
@@ -257,22 +260,22 @@ impl HighLevelEncoder {
// }
// initialState = initialState.appendFLGn(eci.getValue());
// }
let mut states = vec![initialState];
let mut states = vec![initial_state];
let mut index = 0;
while index < self.text.len() {
// for index in 0..self.text.len() {
// for (int index = 0; index < text.length; index++) {
let pairCode;
let nextChar = if index + 1 < self.text.len() {
let pair_code;
let next_char = if index + 1 < self.text.len() {
self.text[index + 1]
} else {
0
};
pairCode = match self.text[index] {
b'\r' if nextChar == b'\n' => 2,
b'.' if nextChar == b' ' => 3,
b',' if nextChar == b' ' => 4,
b':' if nextChar == b' ' => 5,
pair_code = match self.text[index] {
b'\r' if next_char == b'\n' => 2,
b'.' if next_char == b' ' => 3,
b',' if next_char == b' ' => 4,
b':' if next_char == b' ' => 5,
_ => 0,
};
// switch (text[index]) {
@@ -291,19 +294,24 @@ impl HighLevelEncoder {
// default:
// pairCode = 0;
// }
if pairCode > 0 {
if pair_code > 0 {
// We have one of the four special PUNCT pairs. Treat them specially.
// Get a new set of states for the two new characters.
states = Self::updateStateListForPair(states, index as u32, pairCode);
states = Self::update_state_list_for_pair(states, index as u32, pair_code);
index += 1;
} else {
// Get a new set of states for the new character.
states = self.updateStateListForChar(states, index as u32);
states = self.update_state_list_for_char(states, index as u32);
}
index += 1;
}
// for state in &states {
// dbg!(state.clone().toBitArray(&self.text).to_string());
// }
// We are left with a set of states. Find the shortest one.
let minState = states
let min_state = states
.into_iter()
.min_by(|a, b| {
let diff: i64 = a.getBitCount() as i64 - b.getBitCount() as i64;
@@ -324,58 +332,61 @@ impl HighLevelEncoder {
// }
// });
// Convert it to a bit array, and return.
Ok(minState.toBitArray(&self.text))
Ok(min_state.toBitArray(&self.text))
}
// We update a set of states for a new character by updating each state
// for the new character, merging the results, and then removing the
// non-optimal states.
fn updateStateListForChar(&self, states: Vec<State>, index: u32) -> Vec<State> {
fn update_state_list_for_char(&self, states: Vec<State>, index: u32) -> Vec<State> {
let mut result = Vec::new();
for state in states {
// for (State state : states) {
self.updateStateForChar(state, index, &mut result);
self.update_state_for_char(state, index, &mut result);
}
Self::simplifyStates(result)
Self::simplify_states(result)
}
// Return a set of states that represent the possible ways of updating this
// state for the next character. The resulting set of states are added to
// the "result" list.
fn updateStateForChar(&self, state: State, index: u32, result: &mut Vec<State>) {
fn update_state_for_char(&self, state: State, index: u32, result: &mut Vec<State>) {
let ch = self.text[index as usize];
let charInCurrentTable = Self::CHAR_MAP[state.getMode() as usize][ch as usize] > 0;
let mut stateNoBinary = None;
for mode in 0..Self::MODE_PUNCT {
let char_in_current_table = Self::CHAR_MAP[state.getMode() as usize][ch as usize] > 0;
let mut state_no_binary = None;
for mode in 0..=Self::MODE_PUNCT {
// for (int mode = 0; mode <= MODE_PUNCT; mode++) {
let charInMode = Self::CHAR_MAP[mode as usize][ch as usize];
if charInMode > 0 {
if stateNoBinary.is_none() {
let char_in_mode = Self::CHAR_MAP[mode as usize][ch as usize];
if char_in_mode > 0 {
if state_no_binary.is_none() {
// Only create stateNoBinary the first time it's required.
stateNoBinary = Some(state.clone().endBinaryShift(index));
state_no_binary = Some(state.clone().endBinaryShift(index));
}
// Try generating the character by latching to its mode
if !charInCurrentTable || mode as u32 == state.getMode() || mode == Self::MODE_DIGIT
if !char_in_current_table
|| mode as u32 == state.getMode()
|| mode == Self::MODE_DIGIT
{
// If the character is in the current table, we don't want to latch to
// any other mode except possibly digit (which uses only 4 bits). Any
// other latch would be equally successful *after* this character, and
// so wouldn't save any bits.
let latchState = stateNoBinary
let latch_state = state_no_binary
.clone()
.unwrap()
.latchAndAppend(mode as u32, charInMode as u32);
result.push(latchState);
.latchAndAppend(mode as u32, char_in_mode as u32);
result.push(latch_state);
}
// Try generating the character by switching to its mode.
if !charInCurrentTable && Self::SHIFT_TABLE[state.getMode() as usize][mode] >= 0 {
if !char_in_current_table && Self::SHIFT_TABLE[state.getMode() as usize][mode] >= 0
{
// It never makes sense to temporarily shift to another mode if the
// character exists in the current mode. That can never save bits.
let shiftState = stateNoBinary
let shift_state = state_no_binary
.clone()
.unwrap()
.shiftAndAppend(mode as u32, charInMode as u32);
result.push(shiftState);
.shiftAndAppend(mode as u32, char_in_mode as u32);
result.push(shift_state);
}
}
}
@@ -385,56 +396,56 @@ impl HighLevelEncoder {
// It's never worthwhile to go into binary shift mode if you're not already
// in binary shift mode, and the character exists in your current mode.
// That can never save bits over just outputting the char in the current mode.
let binaryState = state.addBinaryShiftChar(index);
result.push(binaryState);
let binary_state = state.addBinaryShiftChar(index);
result.push(binary_state);
}
}
fn updateStateListForPair(states: Vec<State>, index: u32, pairCode: u32) -> Vec<State> {
fn update_state_list_for_pair(states: Vec<State>, index: u32, pairCode: u32) -> Vec<State> {
let mut result = Vec::new();
for state in states {
// for (State state : states) {
Self::updateStateForPair(state, index, pairCode, &mut result);
Self::update_state_for_pair(state, index, pairCode, &mut result);
}
Self::simplifyStates(result)
Self::simplify_states(result)
}
fn updateStateForPair(state: State, index: u32, pairCode: u32, result: &mut Vec<State>) {
let stateNoBinary = state.clone().endBinaryShift(index);
fn update_state_for_pair(state: State, index: u32, pair_code: u32, result: &mut Vec<State>) {
let state_no_binary = state.clone().endBinaryShift(index);
// Possibility 1. Latch to MODE_PUNCT, and then append this code
result.push(
stateNoBinary
state_no_binary
.clone()
.latchAndAppend(Self::MODE_PUNCT as u32, pairCode),
.latchAndAppend(Self::MODE_PUNCT as u32, pair_code),
);
if state.getMode() != Self::MODE_PUNCT as u32 {
// Possibility 2. Shift to MODE_PUNCT, and then append this code.
// Every state except MODE_PUNCT (handled above) can shift
result.push(
stateNoBinary
state_no_binary
.clone()
.shiftAndAppend(Self::MODE_PUNCT as u32, pairCode),
.shiftAndAppend(Self::MODE_PUNCT as u32, pair_code),
);
}
if pairCode == 3 || pairCode == 4 {
if pair_code == 3 || pair_code == 4 {
// both characters are in DIGITS. Sometimes better to just add two digits
let digitState = stateNoBinary
.latchAndAppend(Self::MODE_DIGIT as u32, 16 - pairCode) // period or comma in DIGIT
let digit_state = state_no_binary
.latchAndAppend(Self::MODE_DIGIT as u32, 16 - pair_code) // period or comma in DIGIT
.latchAndAppend(Self::MODE_DIGIT as u32, 1); // space in DIGIT
result.push(digitState);
result.push(digit_state);
}
if state.getBinaryShiftByteCount() > 0 {
// It only makes sense to do the characters as binary if we're already
// in binary mode.
let binaryState = state
let binary_state = state
.addBinaryShiftChar(index)
.addBinaryShiftChar(index + 1);
result.push(binaryState);
result.push(binary_state);
}
}
fn simplifyStates(states: Vec<State>) -> Vec<State> {
fn simplify_states(states: Vec<State>) -> Vec<State> {
let mut result: Vec<State> = Vec::new();
for newState in states {
// for (State newState : states) {
@@ -442,13 +453,14 @@ impl HighLevelEncoder {
for i in 0..result.len() {
// for st in result {
// for (Iterator<State> iterator = result.iterator(); iterator.hasNext();) {
let oldState = result.get(i).unwrap();
if oldState.isBetterThanOrEqualTo(&newState) {
add = false;
break;
}
if newState.isBetterThanOrEqualTo(&oldState) {
result.remove(i);
if let Some(oldState) = result.get(i) {
if oldState.isBetterThanOrEqualTo(&newState) {
add = false;
break;
}
if newState.isBetterThanOrEqualTo(&oldState) {
result.remove(i);
}
}
}
if add {

View File

@@ -22,20 +22,20 @@ use crate::common::BitArray;
pub struct SimpleToken {
// For normal words, indicates value and bitCount
value: u16,
bitCount: u16,
bit_count: u16,
}
impl SimpleToken {
pub fn new(value: i32, bitCount: u32) -> Self {
Self {
value: value as u16,
bitCount: bitCount as u16,
bit_count: bitCount as u16,
}
}
pub fn appendTo(&self, bitArray: &mut BitArray, text: &[u8]) {
bitArray
.appendBits(self.value as u32, self.bitCount as usize)
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
bit_array
.appendBits(self.value as u32, self.bit_count as usize)
.expect("append should never fail");
}
@@ -49,8 +49,8 @@ impl SimpleToken {
impl fmt::Display for SimpleToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut value = self.value & ((1 << self.bitCount) - 1);
value |= 1 << self.bitCount;
write!(f, "<{:#016b}>", value | (1 << self.bitCount))
let mut value = self.value & ((1 << self.bit_count) - 1);
value |= 1 << self.bit_count;
write!(f, "<{:#016b}>", value | (1 << self.bit_count))
}
}

View File

@@ -38,19 +38,19 @@ pub struct State {
token: Token,
// If non-zero, the number of most recent bytes that should be output
// in Binary Shift mode.
binaryShiftByteCount: u32,
binary_shift_byte_count: u32,
// The total number of bits generated (including Binary Shift).
bitCount: u32,
binaryShiftCost: u32,
bit_count: u32,
binary_shift_cost: u32,
}
impl State {
pub fn new(token: Token, mode: u32, binaryBytes: u32, bitCount: u32) -> Self {
pub fn new(token: Token, mode: u32, binary_bytes: u32, bit_count: u32) -> Self {
Self {
mode,
token,
binaryShiftByteCount: binaryBytes,
bitCount,
binaryShiftCost: Self::calculateBinaryShiftCost(binaryBytes),
binary_shift_byte_count: binary_bytes,
bit_count,
binary_shift_cost: Self::calculate_binary_shift_cost(binary_bytes),
}
}
@@ -63,19 +63,19 @@ impl State {
}
pub fn getBinaryShiftByteCount(&self) -> u32 {
self.binaryShiftByteCount
self.binary_shift_byte_count
}
pub fn getBitCount(&self) -> u32 {
self.bitCount
self.bit_count
}
pub fn appendFLGn(self, eci: u32) -> Result<Self, Exceptions> {
let bit_count = self.bitCount;
let bit_count = self.bit_count;
let mode = self.mode;
let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); // 0: FLG(n)
let mut token = result.token;
let mut bitsAdded = 3;
let mut bits_added = 3;
if eci < 0 {
token.add(0, 3); // 0: FNC1
} else if eci > 999999 {
@@ -84,25 +84,25 @@ impl State {
));
// throw new IllegalArgumentException("ECI code must be between 0 and 999999");
} else {
let eciDigits = encoding::all::ISO_8859_1
let eci_digits = encoding::all::ISO_8859_1
.encode(&format!("{}", eci), encoding::EncoderTrap::Replace)
.unwrap();
// let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1);
token.add(eciDigits.len() as i32, 3); // 1-6: number of ECI digits
for eciDigit in &eciDigits {
token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits
for eci_digit in &eci_digits {
// for (byte eciDigit : eciDigits) {
token.add((eciDigit - b'0' + 2) as i32, 4);
token.add((eci_digit - b'0' + 2) as i32, 4);
}
bitsAdded += eciDigits.len() * 4;
bits_added += eci_digits.len() * 4;
}
Ok(State::new(token, mode, 0, bit_count + bitsAdded as u32))
Ok(State::new(token, mode, 0, bit_count + bits_added as u32))
// return new State(token, mode, 0, bitCount + bitsAdded);
}
// Create a new state representing this state with a latch to a (not
// necessary different) mode, and then a code.
pub fn latchAndAppend(self, mode: u32, value: u32) -> State {
let mut bitCount = self.bitCount;
let mut bitCount = self.bit_count;
let mut token = self.token;
if mode != self.mode {
let latch = HighLevelEncoder::LATCH_TABLE[self.mode as usize][mode as usize];
@@ -134,7 +134,7 @@ impl State {
thisModeBitCount,
);
token.add(value as i32, 5);
State::new(token, self.mode, 0, self.bitCount + thisModeBitCount + 5)
State::new(token, self.mode, 0, self.bit_count + thisModeBitCount + 5)
}
// Create a new state representing this state, but an additional character
@@ -142,7 +142,7 @@ impl State {
pub fn addBinaryShiftChar(self, index: u32) -> State {
let mut token = self.token;
let mut mode = self.mode;
let mut bitCount = self.bitCount;
let mut bitCount = self.bit_count;
if self.mode == HighLevelEncoder::MODE_PUNCT as u32
|| self.mode == HighLevelEncoder::MODE_DIGIT as u32
{
@@ -151,10 +151,10 @@ impl State {
bitCount += latch >> 16;
mode = HighLevelEncoder::MODE_UPPER as u32;
}
let deltaBitCount = if self.binaryShiftByteCount == 0 || self.binaryShiftByteCount == 31 {
let deltaBitCount = if self.binary_shift_byte_count == 0 || self.binary_shift_byte_count == 31 {
18
} else {
if self.binaryShiftByteCount == 62 {
if self.binary_shift_byte_count == 62 {
9
} else {
8
@@ -163,10 +163,10 @@ impl State {
let mut result = State::new(
token,
mode,
self.binaryShiftByteCount + 1,
self.binary_shift_byte_count + 1,
bitCount + deltaBitCount,
);
if result.binaryShiftByteCount == 2047 + 31 {
if result.binary_shift_byte_count == 2047 + 31 {
// The string is as long as it's allowed to be. We should end it.
result = result.endBinaryShift(index + 1);
}
@@ -176,30 +176,30 @@ impl State {
// Create the state identical to this one, but we are no longer in
// Binary Shift mode.
pub fn endBinaryShift(self, index: u32) -> State {
if self.binaryShiftByteCount == 0 {
if self.binary_shift_byte_count == 0 {
return self;
}
let mut token = self.token;
token.addBinaryShift(index - self.binaryShiftByteCount, self.binaryShiftByteCount);
token.addBinaryShift(index - self.binary_shift_byte_count, self.binary_shift_byte_count);
State::new(token, self.mode, 0, self.bitCount)
State::new(token, self.mode, 0, self.bit_count)
}
// Returns true if "this" state is better (or equal) to be in than "that"
// state under all possible circumstances.
pub fn isBetterThanOrEqualTo(&self, other: &State) -> bool {
let mut newModeBitCount = self.bitCount
let mut new_mode_bit_count = self.bit_count
+ (HighLevelEncoder::LATCH_TABLE[self.mode as usize][other.mode as usize] >> 16);
if self.binaryShiftByteCount < other.binaryShiftByteCount {
if self.binary_shift_byte_count < other.binary_shift_byte_count {
// add additional B/S encoding cost of other, if any
newModeBitCount += other.binaryShiftCost - self.binaryShiftCost;
} else if self.binaryShiftByteCount > other.binaryShiftByteCount
&& other.binaryShiftByteCount > 0
new_mode_bit_count += other.binary_shift_cost - self.binary_shift_cost;
} else if self.binary_shift_byte_count > other.binary_shift_byte_count
&& other.binary_shift_byte_count > 0
{
// maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it)
newModeBitCount += 10;
new_mode_bit_count += 10;
}
newModeBitCount <= other.bitCount
new_mode_bit_count <= other.bit_count
}
pub fn toBitArray(self, text: &[u8]) -> BitArray {
@@ -215,28 +215,24 @@ impl State {
// symbols.push(tkn);
// tkn = tok.getPrevious();
// }
let mut bitArray = BitArray::new();
let mut bit_array = BitArray::new();
// Add each token to the result in forward order
for i in (0..symbols.len() - 1).rev() {
for symbol in symbols.into_iter().rev() {
// for i in (0..symbols.len()).rev() {
// for (int i = symbols.size() - 1; i >= 0; i--) {
symbols.get(i).unwrap().appendTo(&mut bitArray, text);
symbol.appendTo(&mut bit_array, text);
}
bitArray
bit_array
}
// @Override
// public String toString() {
// return String.format("%s bits=%d bytes=%d", HighLevelEncoder.MODE_NAMES[mode], bitCount, binaryShiftByteCount);
// }
fn calculateBinaryShiftCost(binaryShiftByteCount: u32) -> u32 {
if binaryShiftByteCount > 62 {
fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
if binary_shift_byte_count > 62 {
return 21; // B/S with extended length
}
if binaryShiftByteCount > 31 {
if binary_shift_byte_count > 31 {
return 20; // two B/S
}
if binaryShiftByteCount > 0 {
if binary_shift_byte_count > 0 {
return 10; // one B/S
}
return 0;
@@ -249,8 +245,8 @@ impl fmt::Display for State {
f,
"{} bits={} bytes={}",
HighLevelEncoder::MODE_NAMES[self.mode as usize],
self.bitCount,
self.binaryShiftByteCount
self.bit_count,
self.binary_shift_byte_count
)
}
}

View File

@@ -9,9 +9,9 @@ pub fn toBitArray( bits:&str) -> BitArray{
let mut ba_in = BitArray::new();
let replacer_regex = Regex::new(DOTX).unwrap();
let str = replacer_regex.replace_all(bits, "");
for aStr in str.chars() {
for a_str in str.chars() {
// for (char aStr : str) {
ba_in.appendBit(aStr == 'X');
ba_in.appendBit(a_str == 'X');
}
ba_in