use std::{fs::File, io::Read, ops::Range}; use arithmetic_coding::Model; mod common; const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 .,\n\r-':()[]#*;\"!?*&é/àâè%@$"; #[derive(Debug, Clone)] pub struct StringModel; #[derive(Debug, thiserror::Error)] #[error("invalid character: {0}")] pub struct Error(char); impl Model for StringModel { type B = usize; type Symbol = char; type ValueError = Error; #[allow(clippy::range_plus_one)] fn probability(&self, symbol: Option<&Self::Symbol>) -> Result, Error> { symbol.map_or_else( || Ok(ALPHABET.len()..(ALPHABET.len() + 1)), |char| { ALPHABET .chars() .position(|x| &x == char) .ok_or(Error(*char)) .map(|index| index..(index + 1)) }, ) } fn symbol(&self, value: Self::B) -> Option { ALPHABET.chars().nth(value) } fn max_denominator(&self) -> Self::B { ALPHABET.len() + 1 } } #[test] fn round_trip() { let mut file = File::open("./resources/sherlock.txt").unwrap(); let mut string = String::new(); file.read_to_string(&mut string).unwrap(); let input: Vec<_> = string.chars().collect(); common::round_trip(StringModel, &input); }