use std::collections::HashMap;
use std::collections::VecDeque;
use std::fmt;
use crate::MAX_U56;
use crate::MAX_U64;
use crate::err::MixError;
use super::traits::EncoderDecoder;
#[derive(Debug)]
pub struct CustomEncoder{
base:Vec<char>,
mapping:HashMap<char,u8>
}
impl std::fmt::Display for CustomEncoder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "base:{:?}\nmapping:{:?}", self.base, self.mapping)
}
}
impl CustomEncoder {
pub fn new(base:&str)->Result<Self,MixError>{
let chars = base.chars();
let mut obj = CustomEncoder{
base:Vec::new(),
mapping: HashMap::new()
};
let mut j = 0;
for (i,c) in chars.enumerate(){
if obj.mapping.contains_key(&c){
return Err(MixError{msg: String::from(format!("{}{}", &"进制字符串中不允许有相同的字符:" , c))});
}
obj.base.insert(i, c);
obj.mapping.insert(c,i as u8);
j += 1;
}
if j<2{
return Err(MixError{msg: String::from("进制必须大于2个字符,比如最小的二级制也是0和1两个字符串")});
}
Ok(obj)
}
}
impl EncoderDecoder for CustomEncoder {
fn encode(&self, id:u64)->Result<String,MixError> {
let mut result = VecDeque::new();
let b = self.base.len() as u64;
let mut n = id;
while n > 0 {
let quotient = n / b;
let remainder = n % b;
result.push_front(self.base[remainder as usize] as char);
n = quotient;
}
if result.is_empty() {
result.push_front(self.base[0] as char);
}
let s: String = result.into_iter().collect();
Ok(String::from(s))
}
fn decode(&self, str:String)->Result<u64,MixError> {
let mut result = 0u128;
let base = self.mapping.len() as u128;
let chars: Vec<char> = str.chars().collect();
let length = chars.len();
for (index, char) in chars.iter().enumerate() {
let value = self.mapping.get(char);
if value.is_none() {
return Err(MixError{msg: String::from(format!("无效字符:{}", char))});
}
let value = value.unwrap();
let position = length - index - 1;
result += base.pow(position as u32) * (*value as u128);
}
if result > MAX_U64 as u128 {
return Err(MixError{msg: String::from(format!("字符串[ {} ],转成的整数[ {} ],已超出最大整数范围:[0,{}]", str, result, MAX_U56))});
}
Ok(result as u64)
}
}