use crate::error::TLError;
use crate::tlb_adapters::dict::data_builder::DictDataBuilder;
use crate::tlb_adapters::dict::data_parser::DictDataParser;
use crate::tlb_adapters::{DictKeyAdapter, DictValAdapter};
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use ton_lib_core::cell::CellBuilder;
use ton_lib_core::cell::CellParser;
use ton_lib_core::error::TLCoreError;
pub struct TLBHashMap<KA: DictKeyAdapter<K>, VA: DictValAdapter<V>, K, V> {
key_bits_len: u32,
_phantom: PhantomData<(KA, VA, K, V)>,
}
impl<KA, VA, K, V> TLBHashMap<KA, VA, K, V>
where
KA: DictKeyAdapter<K>,
VA: DictValAdapter<V>,
K: Eq + Hash,
{
pub fn new(key_bits_len: u32) -> Self {
Self {
key_bits_len,
_phantom: PhantomData,
}
}
pub fn read(&self, parser: &mut CellParser) -> Result<HashMap<K, V>, TLCoreError> {
let mut data_parser = DictDataParser::new(self.key_bits_len as usize);
let data_raw = data_parser.read::<V, VA>(parser)?;
let data = data_raw
.into_iter()
.map(|(k, v)| Ok::<_, TLCoreError>((KA::extract_key(&k)?, v)))
.collect::<Result<HashMap<K, V>, _>>()?;
Ok(data)
}
pub fn write(&self, builder: &mut CellBuilder, data: &HashMap<K, V>) -> Result<(), TLCoreError> {
if data.is_empty() {
return Err(TLCoreError::TLBWrongData("empty HashMap can't be written".to_string()));
}
let mut key_value_pairs =
data.iter().map(|(k, v)| Ok::<_, TLError>((KA::make_key(k)?, v))).collect::<Result<Vec<_>, _>>()?;
key_value_pairs.sort_by_key(|(x, _)| x.clone());
let mut keys_sorted = Vec::with_capacity(key_value_pairs.len());
let mut values_sorted = Vec::with_capacity(key_value_pairs.len());
for (key, value) in key_value_pairs {
keys_sorted.push(key);
values_sorted.push(value);
}
let data_builder = DictDataBuilder::<V, VA>::new(self.key_bits_len as usize, keys_sorted, &values_sorted)?;
let dict_data_cell = data_builder.build()?;
builder.write_cell(&dict_data_cell)
}
}