pub mod character_sets;
use std::error::Error;
use crate::{
binary::BitVec,
context::{Context, ContextError},
decoder::Decoder,
encoder::{Capacity, Encoder, EncoderResult},
};
use log::trace;
use crate::binary::Bit;
use self::character_sets::{CharacterSetType, GetCharacterSet};
use super::Method;
#[derive(Debug, PartialEq)]
pub struct TrailingUnicodeMethod {
character_set: CharacterSetType,
}
impl Default for TrailingUnicodeMethod {
fn default() -> Self {
Self::new(CharacterSetType::FullUnicodeSet)
}
}
impl TrailingUnicodeMethod {
pub fn new(unicode_set: CharacterSetType) -> Self {
TrailingUnicodeMethod {
character_set: unicode_set,
}
}
}
impl Capacity for TrailingUnicodeMethod {
fn bitrate(&self) -> usize {
let amount_of_bits = std::mem::size_of::<usize>() * 8;
amount_of_bits - self.character_set.size().leading_zeros() as usize
}
}
impl<E> Encoder<E> for TrailingUnicodeMethod
where
E: Context,
{
fn partial_encode(
&self,
context: &mut E,
data: &mut dyn Iterator<Item = Bit>,
) -> Result<EncoderResult, Box<dyn Error>> {
let set_capacity = self.bitrate();
let next_n_bits = data.take(set_capacity).collect::<Vec<Bit>>();
let amount_bits_taken = next_n_bits.len();
let mut number: u32 = BitVec::from(next_n_bits).into();
number <<= set_capacity - amount_bits_taken;
trace!(
"Took {} bits and assembled a number: {}",
set_capacity,
number
);
if let Some(character) = self.character_set.get_character(number) {
trace!(
"Putting unicode character {:?} at the end of the line",
character
);
context.get_current_text_mut()?.push(*character);
}
Ok(EncoderResult::Success)
}
}
impl<D> Decoder<D> for TrailingUnicodeMethod
where
D: Context,
{
fn partial_decode(&self, context: &D) -> Result<Vec<Bit>, ContextError> {
if let Some(character) = context.get_current_text()?.chars().last() {
let decoded_number = self.character_set.character_to_bits(&character);
trace!(
"Found {:?} at the end of the line, decoded into {}",
&character,
decoded_number
);
let data: Vec<Bit> = BitVec::from(decoded_number).into();
let data_length = data.len();
let data_iter = data.into_iter().skip(data_length - self.bitrate());
let decoded_data = data_iter.collect::<Vec<Bit>>();
return Ok(decoded_data);
}
Ok(BitVec::filled_with(0, self.bitrate()).into())
}
}
impl<E, D> Method<E, D> for TrailingUnicodeMethod
where
E: Context,
D: Context,
{
fn method_name(&self) -> String {
"TrailingUnicodeMethod".to_string()
}
}