use super::errors::CodecError; use serde::Serialize; use std::num::ParseIntError; use std::ops::Deref; use std::{collections::HashMap, u64}; /// A number encoded as a sequence of words #[derive(Debug, Clone, Serialize)] pub struct EncodedPart { pub value: u64, pub words: Vec, } /// A way (variant) to split input number pub type EncodedSplit = Vec; /// A number encoded as words, split in multiple ways #[derive(Debug, Clone, Serialize)] pub struct EncodedValue(Vec); impl EncodedValue { pub fn new(data: Vec) -> Self { EncodedValue(data) } } impl Deref for EncodedValue { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } /// The number value can be encoded as many word sets, /// but decoded as one number. For partial values /// and dictionary words (reasonable length), we can use /// u64 (20-digit number), but the whole input text can /// be longer than 20 digits, so we operate on String (<= 255). #[derive(Debug, Clone, PartialEq, Eq)] pub struct DecodedValue(String); impl DecodedValue { pub fn new(value: String) -> Result { if value.len() > u8::MAX as usize { Err(CodecError::TextTooLong(value.len())) } else { Ok(Self(value)) } } pub fn as_str(&self) -> &str { &self.0 } pub fn parse(&self) -> Result { self.0.parse() } pub fn len(&self) -> usize { self.0.len() } pub fn is_empty(&self) -> bool { self.0.is_empty() } pub fn value_len(&self) -> Result { if self.len() == 0 { return Err(CodecError::EmptyValue); } DecodedLength::try_from(self.len()) } } impl PartialEq<&str> for DecodedValue { fn eq(&self, other: &&str) -> bool { &self.0 == *other } } impl PartialEq for &str { fn eq(&self, other: &DecodedValue) -> bool { *self == &other.0 } } #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct DecodedLength(u8); impl DecodedLength { pub const fn from(value: u8) -> Self { Self(value) } } impl TryFrom for DecodedLength { type Error = CodecError; fn try_from(value: usize) -> Result { if value > u8::MAX as usize { Err(CodecError::ValueLimitExceeded(value)) } else { Ok(Self(value as u8)) } } } // --- Dictionary --- pub type DictEntryId = u64; #[derive(Debug, Clone, PartialEq)] pub struct DictEntry { pub id: Option, pub text: String, pub metadata: HashMap, } impl DictEntry { pub fn new(id: Option, text: String) -> Self { DictEntry { id, text, metadata: HashMap::new(), } } } #[derive(Debug, Clone)] pub struct Dict { pub name: String, pub entries: HashMap, } impl Dict { pub fn new(name: String) -> Self { Dict { name, entries: HashMap::new(), } } pub fn add_entry(&mut self, entry: DictEntry) { self.entries.insert(entry.id.unwrap(), entry); } }