Files
rxing/src/common/eci_string_builder.rs
Henry Schimke 8a0744e534 move to using Eci enum
Decouples the Eci and CharacterSet concepts within the library. Character sets can now exist independently from Eci encodation schemes.
2023-03-04 14:13:50 -06:00

196 lines
5.8 KiB
Rust

/*
* Copyright 2022 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com.google.zxing.common;
// import com.google.zxing.FormatException;
// import java.nio.charset.Charset;
// import java.nio.charset.StandardCharsets;
use std::fmt;
use crate::common::Result;
use super::{CharacterSet, Eci};
/**
* Class that converts a sequence of ECIs and bytes into a string
*
* @author Alex Geller
*/
pub struct ECIStringBuilder {
current_bytes: Vec<u8>,
result: String,
current_charset: CharacterSet, //= StandardCharsets.ISO_8859_1;
}
impl ECIStringBuilder {
pub fn new() -> Self {
Self {
current_bytes: Vec::new(),
result: String::new(),
current_charset: CharacterSet::ISO8859_1,
}
}
pub fn with_capacity(initial_capacity: usize) -> Self {
Self {
current_bytes: Vec::with_capacity(initial_capacity),
result: String::with_capacity(initial_capacity),
current_charset: CharacterSet::ISO8859_1,
}
}
/**
* Appends {@code value} as a byte value
*
* @param value character whose lowest byte is to be appended
*/
pub fn append_char(&mut self, value: char) {
self.current_bytes.push(value as u8);
}
/**
* Appends {@code value} as a byte value
*
* @param value byte to append
*/
pub fn append_byte(&mut self, value: u8) {
self.current_bytes.push(value);
}
/**
* Appends the characters in {@code value} as bytes values
*
* @param value string to append
*/
pub fn append_string(&mut self, value: &str) {
value
.as_bytes()
.iter()
.map(|b| self.current_bytes.push(*b))
.count();
// self.current_bytes.push(value.as_bytes());
}
/**
* Append the string repesentation of {@code value} (short for {@code append(String.valueOf(value))})
*
* @param value int to append as a string
*/
pub fn append(&mut self, value: i32) {
self.append_string(&format!("{value}"));
}
/**
* Appends ECI value to output.
*
* @param value ECI value to append, as an int
* @throws FormatException on invalid ECI value
*/
pub fn appendECI(&mut self, eci: Eci) -> Result<()> {
self.encodeCurrentBytesIfAny();
self.current_charset = eci.into(); //CharacterSet::get_character_set_by_eci(value).ok();
// if let Ok(character_set_eci) = CharacterSetECI::getCharacterSetECIByValue(value) {
// // dbg!(
// // character_set_eci,
// // CharacterSetECI::getCharset(&character_set_eci).name(),
// // CharacterSetECI::getCharset(&character_set_eci).whatwg_name()
// // );
// self.current_charset = Some(character_set_eci);
// } else {
// self.current_charset = None
// }
// self.current_charset = CharacterSetECI::getCharset(&character_set_eci);
Ok(())
}
/// Finishes encoding anything in the buffer using the current ECI and resets.
///
/// This function can panic
pub fn encodeCurrentBytesIfAny(&mut self) {
if ![CharacterSet::Binary, CharacterSet::Unknown].contains(&self.current_charset) {
if self.current_charset == CharacterSet::UTF8 {
if !self.current_bytes.is_empty() {
self.result.push_str(
&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(),
);
self.current_bytes.clear();
}
} else if !self.current_bytes.is_empty() {
let bytes = std::mem::take(&mut self.current_bytes);
self.current_bytes.clear();
let encoded_value = self.current_charset.decode(&bytes).unwrap();
self.result.push_str(&encoded_value);
}
} else {
for byte in &self.current_bytes {
self.result.push(char::from(*byte))
}
self.current_bytes.clear();
}
}
/**
* Appends the characters from {@code value} (unlike all other append methods of this class who append bytes)
*
* @param value characters to append
*/
pub fn appendCharacters(&mut self, value: &str) {
self.encodeCurrentBytesIfAny();
self.result.push_str(value);
}
/**
* Short for {@code toString().length()} (if possible, use {@link #isEmpty()} instead)
*
* @return length of string representation in characters
*/
pub fn len(&mut self) -> usize {
self.encodeCurrentBytesIfAny(); //return toString().length();
self.result.chars().count()
}
/**
* @return true iff nothing has been appended
*/
pub fn is_empty(&mut self) -> bool {
self.current_bytes.is_empty() && self.result.is_empty()
}
pub fn build_result(mut self) -> Self {
self.encodeCurrentBytesIfAny();
self
}
}
impl fmt::Display for ECIStringBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//self.encodeCurrentBytesIfAny();
write!(f, "{}", self.result)
}
}
impl Default for ECIStringBuilder {
fn default() -> Self {
Self::new()
}
}