use std::{fmt, sync::Arc};
use crate::{
Exceptions,
common::{CharacterSet, ECIInput, Eci, MinimalECIInput, Result},
};
use super::{SymbolShapeHint, high_level_encoder};
const ISO_8859_1_ENCODER: CharacterSet = CharacterSet::ISO8859_1;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum Mode {
Ascii,
C40,
Text,
X12,
Edf,
B256,
}
impl Mode {
pub fn ordinal(&self) -> usize {
match self {
Mode::Ascii => 0,
Mode::C40 => 1,
Mode::Text => 2,
Mode::X12 => 3,
Mode::Edf => 4,
Mode::B256 => 5,
}
}
}
const C40_SHIFT2_CHARS: [char; 27] = [
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=',
'>', '?', '@', '[', '\\', ']', '^', '_',
];
pub fn isExtendedASCII(ch: char, fnc1: Option<char>) -> bool {
let is_fnc1 = if let Some(fnc1) = fnc1 {
ch != fnc1
} else {
true
};
is_fnc1 && ch as u8 >= 128 }
#[inline]
fn isInC40Shift1Set(ch: char) -> bool {
ch as u8 <= 31
}
fn isInC40Shift2Set(ch: char, fnc1: Option<char>) -> bool {
for c40Shift2Char in C40_SHIFT2_CHARS {
if c40Shift2Char == ch {
return true;
}
}
if let Some(fnc1) = fnc1 {
ch == fnc1
} else {
false
}
}
fn isInTextShift1Set(ch: char) -> bool {
isInC40Shift1Set(ch)
}
fn isInTextShift2Set(ch: char, fnc1: Option<char>) -> bool {
isInC40Shift2Set(ch, fnc1)
}
pub fn encodeHighLevel(msg: &str) -> Result<String> {
encodeHighLevelWithDetails(msg, None, None, SymbolShapeHint::FORCE_NONE)
}
pub fn encodeHighLevelWithDetails(
msg: &str,
priorityCharset: Option<CharacterSet>,
fnc1: Option<char>,
shape: SymbolShapeHint,
) -> Result<String> {
let mut msg = msg;
let mut macroId = 0;
if msg.starts_with(high_level_encoder::MACRO_05_HEADER)
&& msg.ends_with(high_level_encoder::MACRO_TRAILER)
{
macroId = 5;
msg = &msg[high_level_encoder::MACRO_05_HEADER.chars().count()..(msg.chars().count() - 2)];
} else if msg.starts_with(high_level_encoder::MACRO_06_HEADER)
&& msg.ends_with(high_level_encoder::MACRO_TRAILER)
{
macroId = 6;
msg = &msg[high_level_encoder::MACRO_06_HEADER.chars().count()..(msg.chars().count() - 2)];
}
Ok(ISO_8859_1_ENCODER
.decode(&encode(msg, priorityCharset, fnc1, shape, macroId)?)
.expect("should decode"))
}
fn encode(
input: &str,
priorityCharset: Option<CharacterSet>,
fnc1: Option<char>,
shape: SymbolShapeHint,
macroId: i32,
) -> Result<Vec<u8>> {
Ok(encodeMinimally(Arc::new(Input::new(
input,
priorityCharset,
fnc1,
shape,
macroId,
)))?
.getBytes()
.to_vec())
}
fn addEdge(edges: &mut [Vec<Option<Arc<Edge>>>], edge: Arc<Edge>) -> Result<()> {
let vertexIndex = (edge.fromPosition + edge.characterLength) as usize;
if edges[vertexIndex][edge.getEndMode()?.ordinal()].is_none()
|| edges[vertexIndex][edge.getEndMode()?.ordinal()]
.as_ref()
.ok_or(Exceptions::ILLEGAL_STATE)?
.cachedTotalSize
> edge.cachedTotalSize
{
edges[vertexIndex][edge.getEndMode()?.ordinal()] = Some(edge.clone());
}
Ok(())
}
fn getNumberOfC40Words(
input: Arc<Input>,
from: u32,
c40: bool,
characterLength: &mut [u32],
) -> Result<u32> {
let mut thirdsCount = 0;
for i in (from as usize)..input.length() {
if input.isECI(i as u32)? {
characterLength[0] = 0;
return Ok(0);
}
let ci = input.charAt(i)?;
if c40 && high_level_encoder::isNativeC40(ci)
|| !c40 && high_level_encoder::isNativeText(ci)
{
thirdsCount += 1; } else if !isExtendedASCII(ci, input.getFNC1Character()) {
thirdsCount += 2; } else {
let asciiValue = ci as u8;
if asciiValue >= 128
&& (c40 && high_level_encoder::isNativeC40((asciiValue - 128) as char)
|| !c40 && high_level_encoder::isNativeText((asciiValue - 128) as char))
{
thirdsCount += 3; } else {
thirdsCount += 4; }
}
if thirdsCount % 3 == 0 || ((thirdsCount - 2) % 3 == 0 && i + 1 == input.length()) {
characterLength[0] = i as u32 - from + 1;
return Ok(((thirdsCount as f64) / 3.0).ceil() as u32);
}
}
characterLength[0] = 0;
Ok(0)
}
fn addEdges(
input: Arc<Input>,
edges: &mut [Vec<Option<Arc<Edge>>>],
from: u32,
previous: Option<Arc<Edge>>,
) -> Result<()> {
if input.isECI(from)? {
addEdge(
edges,
Arc::new(Edge::new(input, Mode::Ascii, from, 1, previous)?),
)?;
return Ok(());
}
let ch = input.charAt(from as usize)?;
if previous.is_none() || previous.as_ref().unwrap().getEndMode()? != Mode::Edf {
if high_level_encoder::isDigit(ch)
&& input.haveNCharacters(from as usize, 2)?
&& high_level_encoder::isDigit(input.charAt(from as usize + 1)?)
{
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
Mode::Ascii,
from,
2,
previous.clone(),
)?),
)?;
} else {
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
Mode::Ascii,
from,
1,
previous.clone(),
)?),
)?;
}
let modes = [Mode::C40, Mode::Text];
for mode in modes {
let mut characterLength = [0u32; 1];
if getNumberOfC40Words(input.clone(), from, mode == Mode::C40, &mut characterLength)?
> 0
{
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
mode,
from,
characterLength[0],
previous.clone(),
)?),
)?;
}
}
if input.haveNCharacters(from as usize, 3)?
&& high_level_encoder::isNativeX12(input.charAt(from as usize)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?)
{
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
Mode::X12,
from,
3,
previous.clone(),
)?),
)?;
}
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
Mode::B256,
from,
1,
previous.clone(),
)?),
)?;
}
let mut i: u32 = 0;
while i < 3 {
let pos = from + i;
if input.haveNCharacters(pos as usize, 1)?
&& high_level_encoder::isNativeEDIFACT(input.charAt(pos as usize)?)
{
addEdge(
edges,
Arc::new(Edge::new(
input.clone(),
Mode::Edf,
from,
i + 1,
previous.clone(),
)?),
)?;
} else {
break;
}
i += 1;
}
if i == 3
&& input.haveNCharacters(from as usize, 4)?
&& high_level_encoder::isNativeEDIFACT(input.charAt(from as usize + 3)?)
{
addEdge(
edges,
Arc::new(Edge::new(input, Mode::Edf, from, 4, previous)?),
)?;
}
Ok(())
}
fn encodeMinimally(input: Arc<Input>) -> Result<RXingResult> {
let inputLength = input.length();
let mut edges = vec![vec![None; 6]; inputLength + 1];
addEdges(input.clone(), &mut edges, 0, None)?;
for i in 1..=inputLength {
for j in 0..6 {
if edges[i][j].is_some() && i < inputLength {
let edge = edges[i][j].clone();
addEdges(input.clone(), &mut edges, i as u32, edge)?;
}
}
edges[i - 1][..6].fill(None);
}
let mut minimalJ: i32 = -1;
let mut minimalSize = i32::MAX;
for j in 0..6 {
if let Some(edge) = &edges[inputLength][j] {
let size = if (1..=3).contains(&j) {
edge.cachedTotalSize + 1
} else {
edge.cachedTotalSize
}; if (size as i32) < minimalSize {
minimalSize = size as i32;
minimalJ = j as i32;
}
}
}
if minimalJ < 0 {
return Err(Exceptions::illegal_state_with(format!(
"Internal error: failed to encode \"{input}\""
)));
}
RXingResult::new(edges[inputLength][minimalJ as usize].clone())
}
const ALL_CODEWORD_CAPACITIES: [u32; 28] = [
3, 5, 8, 10, 12, 16, 18, 22, 30, 32, 36, 44, 49, 62, 86, 114, 144, 174, 204, 280, 368, 456,
576, 696, 816, 1050, 1304, 1558,
];
const SQUARE_CODEWORD_CAPACITIES: [u32; 24] = [
3, 5, 8, 12, 18, 22, 30, 36, 44, 62, 86, 114, 144, 174, 204, 280, 368, 456, 576, 696, 816,
1050, 1304, 1558,
];
const RECTANGULAR_CODEWORD_CAPACITIES: [u32; 6] = [5, 10, 16, 33, 32, 49];
struct Edge {
input: Arc<Input>,
mode: Mode, fromPosition: u32,
characterLength: u32,
previous: Option<Arc<Edge>>,
cachedTotalSize: u32,
}
impl Edge {
fn new(
input: Arc<Input>,
mode: Mode,
fromPosition: u32,
characterLength: u32,
previous: Option<Arc<Edge>>,
) -> Result<Self> {
if fromPosition + characterLength > input.length() as u32 {
return Err(Exceptions::FORMAT);
}
let mut size = if let Some(previous) = previous.clone() {
previous.cachedTotalSize
} else {
0
};
let previousMode = Self::getPreviousMode(previous.clone())?;
match mode {
Mode::Ascii => {
size += 1;
if input.isECI(fromPosition)?
|| isExtendedASCII(
input.charAt(fromPosition as usize)?,
input.getFNC1Character(),
)
{
size += 1;
}
if previousMode == Mode::C40
|| previousMode == Mode::Text
|| previousMode == Mode::X12
{
size += 1; }
}
Mode::B256 => {
size += 1;
if previousMode != Mode::B256 || Self::getB256Size(mode, previous.clone()) == 250 {
size += 1; }
if previousMode == Mode::Ascii {
size += 1; } else if previousMode == Mode::C40
|| previousMode == Mode::Text
|| previousMode == Mode::X12
{
size += 2; }
}
Mode::C40 | Mode::Text | Mode::X12 => {
if mode == Mode::X12 {
size += 2;
} else {
let mut charLen = [0u32; 1];
size += getNumberOfC40Words(
input.clone(),
fromPosition,
mode == Mode::C40,
&mut charLen,
)? * 2;
}
if previousMode == Mode::Ascii || previousMode == Mode::B256 {
size += 1; } else if previousMode != mode
&& (previousMode == Mode::C40
|| previousMode == Mode::Text
|| previousMode == Mode::X12)
{
size += 2; }
}
Mode::Edf => {
size += 3;
if previousMode == Mode::Ascii || previousMode == Mode::B256 {
size += 1; } else if previousMode == Mode::C40
|| previousMode == Mode::Text
|| previousMode == Mode::X12
{
size += 2; }
}
}
Ok(Self {
input,
mode,
fromPosition,
characterLength,
previous,
cachedTotalSize: size,
})
}
pub fn getB256Size(mode: Mode, previous: Option<Arc<Edge>>) -> u32 {
if mode != Mode::B256 {
return 0;
}
let mut cnt = 1;
let mut current = previous;
while current.is_some() && current.as_ref().unwrap().mode == Mode::B256 && cnt <= 250 {
cnt += 1;
current.clone_from(¤t.clone().as_ref().unwrap().previous);
}
cnt
}
pub fn getPreviousStartMode(previous: Option<Arc<Edge>>) -> Mode {
if let Some(prev) = previous {
prev.mode
} else {
Mode::Ascii
}
}
pub fn getPreviousMode(previous: Option<Arc<Edge>>) -> Result<Mode> {
if let Some(prev) = previous {
prev.getEndMode()
} else {
Ok(Mode::Ascii)
}
}
pub fn getEndMode(&self) -> Result<Mode> {
let mode = self.mode;
if mode == Mode::Edf {
if self.characterLength < 4 {
return Ok(Mode::Ascii);
}
let lastASCII = Self::getLastASCII(self)?; if lastASCII > 0
&& self.getCodewordsRemaining(self.cachedTotalSize + lastASCII) <= 2 - lastASCII
{
return Ok(Mode::Ascii);
}
}
if mode == Mode::C40 || mode == Mode::Text || mode == Mode::X12 {
if self.fromPosition + self.characterLength >= self.input.length() as u32
&& self.getCodewordsRemaining(self.cachedTotalSize) == 0
{
return Ok(Mode::Ascii);
}
let lastASCII = Self::getLastASCII(self)?;
if lastASCII == 1 && self.getCodewordsRemaining(self.cachedTotalSize + 1) == 0 {
return Ok(Mode::Ascii);
}
}
Ok(mode)
}
pub fn getMode(&self) -> Mode {
self.mode
}
pub fn getLastASCII(&self) -> Result<u32> {
let length = self.input.length() as u32;
let from = self.fromPosition + self.characterLength;
if length - from > 4 || from >= length {
return Ok(0);
}
if length - from == 1 {
if isExtendedASCII(
self.input.charAt(from as usize)?,
self.input.getFNC1Character(),
) {
return Ok(0);
}
return Ok(1);
}
if length - from == 2 {
if isExtendedASCII(
self.input.charAt(from as usize)?,
self.input.getFNC1Character(),
) || isExtendedASCII(
self.input.charAt(from as usize + 1)?,
self.input.getFNC1Character(),
) {
return Ok(0);
}
if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
{
return Ok(1);
}
return Ok(2);
}
if length - from == 3 {
if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
&& !isExtendedASCII(
self.input.charAt(from as usize + 2)?,
self.input.getFNC1Character(),
)
{
return Ok(2);
}
if high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 2)?)
&& !isExtendedASCII(
self.input.charAt(from as usize)?,
self.input.getFNC1Character(),
)
{
return Ok(2);
}
return Ok(0);
}
if high_level_encoder::isDigit(self.input.charAt(from as usize)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 1)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 2)?)
&& high_level_encoder::isDigit(self.input.charAt(from as usize + 3)?)
{
return Ok(2);
}
Ok(0)
}
pub fn getMinSymbolSize(&self, minimum: u32) -> u32 {
match self.input.getShapeHint() {
SymbolShapeHint::FORCE_SQUARE => {
for capacity in SQUARE_CODEWORD_CAPACITIES {
if capacity >= minimum {
return capacity;
}
}
}
SymbolShapeHint::FORCE_RECTANGLE => {
for capacity in RECTANGULAR_CODEWORD_CAPACITIES {
if capacity >= minimum {
return capacity;
}
}
}
_ => {}
}
for capacity in ALL_CODEWORD_CAPACITIES {
if capacity >= minimum {
return capacity;
}
}
ALL_CODEWORD_CAPACITIES[ALL_CODEWORD_CAPACITIES.len() - 1]
}
pub fn getCodewordsRemaining(&self, minimum: u32) -> u32 {
Self::getMinSymbolSize(self, minimum) - minimum
}
#[inline]
pub fn getBytes1(c: u32) -> Vec<u8> {
vec![c as u8]
}
#[inline]
pub fn getBytes2(c1: u32, c2: u32) -> Vec<u8> {
vec![c1 as u8, c2 as u8]
}
pub fn setC40Word(bytes: &mut [u8], offset: u32, c1: u32, c2: u32, c3: u32) {
let val16 = (1600 * (c1 & 0xff)) + (40 * (c2 & 0xff)) + (c3 & 0xff) + 1;
bytes[offset as usize] = (val16 / 256) as u8;
bytes[offset as usize + 1] = (val16 % 256) as u8;
}
fn getX12Value(c: char) -> u32 {
let c = c as u32;
if c == 13 {
0
} else if c == 42 {
1
} else if c == 62 {
2
} else if c == 32 {
3
} else if (48..=57).contains(&c) {
c - 44
} else if (65..=90).contains(&c) {
c - 51
} else {
c
}
}
pub fn getX12Words(&self) -> Result<Vec<u8>> {
assert!(self.characterLength % 3 == 0);
let mut result = vec![0u8; self.characterLength as usize / 3 * 2];
let mut i = 0;
while i < result.len() {
Self::setC40Word(
&mut result,
i as u32,
Self::getX12Value(self.input.charAt(self.fromPosition as usize + i / 2 * 3)?),
Self::getX12Value(
self.input
.charAt(self.fromPosition as usize + i / 2 * 3 + 1)?,
),
Self::getX12Value(
self.input
.charAt(self.fromPosition as usize + i / 2 * 3 + 2)?,
),
);
i += 2;
}
Ok(result)
}
pub fn getShiftValue(c: char, c40: bool, fnc1: Option<char>) -> u32 {
if c40 && isInC40Shift1Set(c) || !c40 && isInTextShift1Set(c) {
0
} else if c40 && isInC40Shift2Set(c, fnc1) || !c40 && isInTextShift2Set(c, fnc1) {
1
} else {
2
}
}
fn getC40Value(c40: bool, setIndex: u32, c: char, fnc1: Option<char>) -> u32 {
if let Some(fnc1_char) = fnc1 {
if c == fnc1_char {
assert!(setIndex == 2);
return 27;
}
}
if c40 {
let c = c as u32;
if c <= 31 {
c
} else if c == 32 {
3
} else if c <= 47 {
c - 33
} else if c <= 57 {
c - 44
} else if c <= 64 {
c - 43
} else if c <= 90 {
c - 51
} else if c <= 95 {
c - 69
} else if c <= 127 {
c - 96
} else {
c
}
} else {
let c = c as u32;
if c == 0 {
0
} else if setIndex == 0 && c <= 3 {
c - 1
} else if
setIndex == 1 && c <= 31 {
c
} else if c == 32 {
3
} else if (33..=47).contains(&c) {
c - 33
} else if (48..=57).contains(&c) {
c - 44
} else if (58..=64).contains(&c) {
c - 43
} else if (65..=90).contains(&c) {
c - 64
} else if (91..=95).contains(&c) {
c - 69
} else if c == 96 {
0
} else if (97..=122).contains(&c) {
c - 83
} else if (123..=127).contains(&c) {
c - 96
} else {
c
}
}
}
pub fn getC40Words(&self, c40: bool, fnc1: Option<char>) -> Result<Vec<u8>> {
let mut c40Values: Vec<u8> = Vec::new();
let fromPosition = self.fromPosition as usize;
for i in 0..self.characterLength as usize {
let ci = self.input.charAt(fromPosition + i)?;
if c40 && high_level_encoder::isNativeC40(ci)
|| !c40 && high_level_encoder::isNativeText(ci)
{
c40Values.push(Self::getC40Value(c40, 0, ci, fnc1) as u8);
} else if !isExtendedASCII(ci, fnc1) {
let shiftValue = Self::getShiftValue(ci, c40, fnc1);
c40Values.push(shiftValue as u8); c40Values.push(Self::getC40Value(c40, shiftValue, ci, fnc1) as u8);
} else {
let asciiValue = (ci as u8 - 128) as char;
if c40 && high_level_encoder::isNativeC40(asciiValue)
|| !c40 && high_level_encoder::isNativeText(asciiValue)
{
c40Values.push(1); c40Values.push(30); c40Values.push(Self::getC40Value(c40, 0, asciiValue, fnc1) as u8);
} else {
c40Values.push(1); c40Values.push(30); let shiftValue = Self::getShiftValue(asciiValue, c40, fnc1);
c40Values.push(shiftValue as u8); c40Values.push(Self::getC40Value(c40, shiftValue, asciiValue, fnc1) as u8);
}
}
}
if (c40Values.len() % 3) != 0 {
assert!(
(c40Values.len() - 2) % 3 == 0
&& fromPosition + self.characterLength as usize == self.input.length()
);
c40Values.push(0); }
let mut result = vec![0u8; c40Values.len() / 3 * 2];
let mut byteIndex = 0;
let mut i = 0;
while i < c40Values.len() {
Self::setC40Word(
&mut result,
byteIndex,
c40Values[i] as u32,
c40Values[i + 1] as u32,
c40Values[i + 2] as u32,
);
byteIndex += 2;
i += 3;
}
Ok(result)
}
pub fn getEDFBytes(&self) -> Result<Vec<u8>> {
let numberOfThirds = (self.characterLength as f32 / 4.0).ceil() as usize;
let mut result = vec![0u8; numberOfThirds * 3];
let mut pos = self.fromPosition as usize;
let endPos = (self.fromPosition as usize + self.characterLength as usize - 1)
.min(self.input.length() - 1);
let mut i = 0;
while i < numberOfThirds {
let mut edfValues = [0u32; 4];
for edfValue in &mut edfValues {
if pos <= endPos {
*edfValue = self.input.charAt(pos)? as u32 & 0x3f;
pos += 1;
} else {
*edfValue = if pos == endPos + 1 { 0x1f } else { 0 };
}
}
let mut val24 = edfValues[0] << 18;
val24 |= edfValues[1] << 12;
val24 |= edfValues[2] << 6;
val24 |= edfValues[3];
result[i] = ((val24 >> 16) & 0xff) as u8;
result[i + 1] = ((val24 >> 8) & 0xff) as u8;
result[i + 2] = (val24 & 0xff) as u8;
i += 3;
}
Ok(result)
}
pub fn getLatchBytes(&self) -> Result<Vec<u8>> {
match Self::getPreviousMode(self.previous.clone())? {
Mode::Ascii | Mode::B256 =>
{
match self.mode {
Mode::B256 => return Ok(Self::getBytes1(231)),
Mode::C40 => return Ok(Self::getBytes1(230)),
Mode::Text => return Ok(Self::getBytes1(239)),
Mode::X12 => return Ok(Self::getBytes1(238)),
Mode::Edf => return Ok(Self::getBytes1(240)),
_ => {}
}
}
Mode::C40 | Mode::Text | Mode::X12
if self.mode != Self::getPreviousMode(self.previous.clone())? =>
{
match self.mode {
Mode::Ascii => return Ok(Self::getBytes1(254)),
Mode::B256 => return Ok(Self::getBytes2(254, 231)),
Mode::C40 => return Ok(Self::getBytes2(254, 230)),
Mode::Text => return Ok(Self::getBytes2(254, 239)),
Mode::X12 => return Ok(Self::getBytes2(254, 238)),
Mode::Edf => return Ok(Self::getBytes2(254, 240)),
}
}
Mode::C40 | Mode::Text | Mode::X12 => {}
Mode::Edf => assert!(self.mode == Mode::Edf), }
Ok(Vec::new())
}
pub fn getDataBytes(&self) -> Result<Vec<u8>> {
match self.mode {
Mode::Ascii => {
if self.input.isECI(self.fromPosition)? {
Ok(Self::getBytes2(
241,
self.input.getECIValue(self.fromPosition as usize)? as u32 + 1,
))
} else if isExtendedASCII(
self.input.charAt(self.fromPosition as usize)?,
self.input.getFNC1Character(),
) {
Ok(Self::getBytes2(
235,
self.input.charAt(self.fromPosition as usize)? as u32 - 127,
))
} else if self.characterLength == 2 {
Ok(Self::getBytes1(
(self.input.charAt(self.fromPosition as usize)? as u32 - b'0' as u32) * 10
+ self.input.charAt(self.fromPosition as usize + 1)? as u32
- b'0' as u32
+ 130,
))
} else if self.input.isFNC1(self.fromPosition as usize)? {
Ok(Self::getBytes1(232))
} else {
Ok(Self::getBytes1(
self.input.charAt(self.fromPosition as usize)? as u32 + 1,
))
}
}
Mode::B256 => Ok(Self::getBytes1(
self.input.charAt(self.fromPosition as usize)? as u32,
)),
Mode::C40 => self.getC40Words(true, self.input.getFNC1Character()),
Mode::Text => self.getC40Words(false, self.input.getFNC1Character()),
Mode::X12 => self.getX12Words(),
Mode::Edf => self.getEDFBytes(),
}
}
}
struct RXingResult {
bytes: Vec<u8>,
}
impl RXingResult {
pub fn new(solution: Option<Arc<Edge>>) -> Result<Self> {
let solution = if let Some(edge) = solution {
edge
} else {
return Err(Exceptions::ILLEGAL_ARGUMENT);
};
let input = solution.input.clone();
let mut size = 0;
let mut bytesAL = Vec::new(); let mut randomizePostfixLength = Vec::new(); let mut randomizeLengths = Vec::new(); if (solution.mode == Mode::C40 || solution.mode == Mode::Text || solution.mode == Mode::X12)
&& solution.getEndMode()? != Mode::Ascii
{
size += Self::prepend(&Edge::getBytes1(254), &mut bytesAL);
}
let mut hold_current = Some(solution.clone());
while let Some(current) = hold_current {
size += Self::prepend(¤t.getDataBytes()?, &mut bytesAL);
if current.previous.is_none()
|| Edge::getPreviousStartMode(current.previous.clone()) != current.getMode()
{
if current.getMode() == Mode::B256 {
if size <= 249 {
bytesAL.insert(0, size as u8);
size += 1;
} else {
bytesAL.insert(0, (size % 250) as u8);
bytesAL.insert(0, (size / 250 + 249) as u8);
size += 2;
}
randomizePostfixLength.push(bytesAL.len());
randomizeLengths.push(size);
}
Self::prepend(¤t.getLatchBytes()?, &mut bytesAL);
size = 0;
}
hold_current = current.previous.clone();
}
if input.getMacroId() == 5 {
_ = Self::prepend(&Edge::getBytes1(236), &mut bytesAL);
} else if input.getMacroId() == 6 {
_ = Self::prepend(&Edge::getBytes1(237), &mut bytesAL);
}
if input.getFNC1Character().is_some() {
_ = Self::prepend(&Edge::getBytes1(232), &mut bytesAL);
}
for i in 0..randomizePostfixLength.len() {
let bytes_al_len = bytesAL.len() as u32;
Self::applyRandomPattern(
&mut bytesAL,
bytes_al_len - *randomizePostfixLength.get(i).unwrap() as u32,
*randomizeLengths.get(i).unwrap() as u32,
);
}
let capacity = solution.getMinSymbolSize(bytesAL.len() as u32);
if bytesAL.len() < capacity as usize {
bytesAL.push(129);
}
while bytesAL.len() < capacity as usize {
bytesAL.push(Self::randomize253State(bytesAL.len() as u32 + 1) as u8);
}
let mut bytes = vec![0u8; bytesAL.len()];
bytes[..].copy_from_slice(&bytesAL[..]);
Ok(Self { bytes })
}
pub fn prepend(bytes: &[u8], into: &mut Vec<u8>) -> usize {
for byte in bytes.iter().rev() {
into.insert(0, *byte);
}
bytes.len()
}
#[inline]
fn randomize253State(codewordPosition: u32) -> u32 {
let pseudoRandom = ((149 * codewordPosition) % 253) + 1;
let tempVariable = 129 + pseudoRandom;
if tempVariable <= 254 {
tempVariable
} else {
tempVariable - 254
}
}
pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) {
for i in 0..length as usize {
let Pad_codeword_position = startPosition as usize + i;
let Pad_codeword_value = bytesAL.get(Pad_codeword_position).unwrap_or(&0);
let pseudo_random_number = ((149 * (Pad_codeword_position + 1)) % 255) + 1;
let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16;
bytesAL[Pad_codeword_position] = if temp_variable <= 255 {
temp_variable as u8
} else {
(temp_variable - 256) as u8
};
}
}
pub fn getBytes(&self) -> &[u8] {
&self.bytes
}
}
struct Input {
shape: SymbolShapeHint,
macroId: i32,
internal: MinimalECIInput,
}
impl Input {
pub fn new(
stringToEncode: &str,
priorityCharset: Option<CharacterSet>,
fnc1: Option<char>,
shape: SymbolShapeHint,
macroId: i32,
) -> Self {
let z = fnc1.unwrap_or_default().to_string();
let v = if fnc1.is_some() {
Some(z.as_str())
} else {
None
};
Self {
shape,
macroId,
internal: MinimalECIInput::new(stringToEncode, priorityCharset, v),
}
}
pub fn getMacroId(&self) -> i32 {
self.macroId
}
pub fn getShapeHint(&self) -> SymbolShapeHint {
self.shape
}
pub fn length(&self) -> usize {
self.internal.length()
}
pub fn isECI(&self, index: u32) -> Result<bool> {
self.internal.isECI(index)
}
pub fn charAt(&self, index: usize) -> Result<char> {
self.internal.charAt(index)
}
pub fn getFNC1Character(&self) -> Option<char> {
if self.internal.getFNC1Character() == 1000 {
None
} else {
Some(self.internal.getFNC1Character() as u8 as char)
}
}
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool> {
self.internal.haveNCharacters(index, n)
}
fn isFNC1(&self, index: usize) -> Result<bool> {
self.internal.isFNC1(index)
}
fn getECIValue(&self, index: usize) -> Result<Eci> {
self.internal.getECIValue(index)
}
}
impl fmt::Display for Input {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.internal.fmt(f)
}
}