use std::rc::Rc;
use crate::common::{CharacterSet, Result};
use crate::{Dimension, Exceptions};
use super::{SymbolInfo, SymbolInfoLookup, SymbolShapeHint};
const ISO_8859_1_ENCODER: CharacterSet = CharacterSet::ISO8859_1;
pub struct EncoderContext<'a> {
symbol_lookup: Rc<SymbolInfoLookup<'a>>,
msg: String,
shape: SymbolShapeHint,
minSize: Option<Dimension>,
maxSize: Option<Dimension>,
codewords: String,
pub(super) pos: u32,
newEncoding: Option<usize>,
symbolInfo: Option<&'a SymbolInfo>,
skipAtEnd: u32,
}
impl<'a> EncoderContext<'_> {
pub fn with_symbol_info_lookup(
msg: &str,
symbol_lookup: Rc<SymbolInfoLookup<'a>>,
) -> Result<EncoderContext<'a>> {
let mut new_self = EncoderContext::new(msg)?;
new_self.symbol_lookup = symbol_lookup.clone();
Ok(new_self)
}
pub fn new(msg: &str) -> Result<Self> {
let sb = if let Ok(encoded_bytes) = ISO_8859_1_ENCODER.encode(msg) {
ISO_8859_1_ENCODER.decode(&encoded_bytes).map_err(|e| {
Exceptions::parse_with(format!("round trip decode should always work: {e}"))
})?
} else {
return Err(Exceptions::illegal_argument_with(
"Message contains characters outside ISO-8859-1 encoding.",
));
};
Ok(Self {
symbol_lookup: Rc::new(SymbolInfoLookup::new()),
msg: sb,
shape: SymbolShapeHint::FORCE_NONE,
codewords: String::with_capacity(msg.chars().count()),
newEncoding: None,
minSize: None,
maxSize: None,
pos: 0,
symbolInfo: None,
skipAtEnd: 0,
})
}
pub fn setSymbolShape(&mut self, shape: SymbolShapeHint) {
self.shape = shape;
}
pub fn setSizeConstraints(&mut self, minSize: Option<Dimension>, maxSize: Option<Dimension>) {
self.minSize = minSize;
self.maxSize = maxSize;
}
pub fn getMessage(&self) -> &str {
&self.msg
}
pub fn setSkipAtEnd(&mut self, count: u32) {
self.skipAtEnd = count;
}
pub fn getCurrentChar(&self) -> char {
self.msg.chars().nth(self.pos as usize).unwrap()
}
pub fn getCurrent(&self) -> char {
self.msg.chars().nth(self.pos as usize).unwrap()
}
pub fn getCodewords(&self) -> &str {
&self.codewords
}
pub fn writeCodewords(&mut self, codewords: &str) {
self.codewords.push_str(codewords);
}
pub fn writeCodeword(&mut self, codeword: u8) {
self.codewords.push(codeword as char);
}
pub fn getCodewordCount(&self) -> usize {
self.codewords.chars().count()
}
pub fn getNewEncoding(&self) -> Option<usize> {
self.newEncoding
}
pub fn signalEncoderChange(&mut self, encoding: usize) {
self.newEncoding = Some(encoding);
}
pub fn resetEncoderSignal(&mut self) {
self.newEncoding = None;
}
pub fn hasMoreCharacters(&self) -> bool {
self.pos < self.getTotalMessageCharCount()
}
fn getTotalMessageCharCount(&self) -> u32 {
self.msg.chars().count() as u32 - self.skipAtEnd
}
pub fn getRemainingCharacters(&self) -> u32 {
self.getTotalMessageCharCount() - self.pos
}
pub fn getSymbolInfo(&self) -> &Option<&SymbolInfo> {
&self.symbolInfo
}
pub fn updateSymbolInfo(&mut self) {
self.updateSymbolInfoWithLength(self.getCodewordCount());
}
pub fn updateSymbolInfoWithLength(&mut self, len: usize) {
if self.symbolInfo.is_none()
|| len > self.symbolInfo.as_ref().unwrap().getDataCapacity() as usize
{
self.symbolInfo = Some(
self.symbol_lookup
.lookup_with_codewords_shape_size_fail(
len as u32,
self.shape,
&self.minSize,
&self.maxSize,
true,
)
.unwrap()
.unwrap(),
);
}
}
pub fn resetSymbolInfo(&mut self) {
self.symbolInfo = None;
}
}