use std::collections::HashMap;
use std::io::Read;
use merc_utilities::MercError;
use crate::Ldd;
use crate::Storage;
use crate::Value;
pub struct SylvanReader {
indexed_set: HashMap<u64, Ldd>, last_index: u64, }
impl SylvanReader {
pub fn new() -> Self {
Self {
indexed_set: HashMap::new(),
last_index: 2,
}
}
pub fn read_ldd<R: Read>(&mut self, storage: &mut Storage, stream: &mut R) -> Result<Ldd, MercError> {
let count = read_u64(stream)?;
for _ in 0..count {
let a = read_u64(stream)?;
let b = read_u64(stream)?;
let right = (a & 0x0000ffffffffffff) >> 1;
let down = b >> 17;
let mut bytes: [u8; 4] = Default::default();
bytes[0..2].copy_from_slice(&a.to_le_bytes()[6..8]);
bytes[2..4].copy_from_slice(&b.to_le_bytes()[0..2]);
let value = u32::from_le_bytes(bytes);
let copy = right & 0x10000;
if copy != 0 {
panic!("We do not yet deal with copy nodes.");
}
let down = self.node_from_index(storage, down);
let right = self.node_from_index(storage, right);
let ldd = storage.insert(value as Value, &down, &right);
self.indexed_set.insert(self.last_index, ldd);
self.last_index += 1;
}
let result = read_u64(stream)?;
Ok(self.node_from_index(storage, result))
}
fn node_from_index(&self, storage: &mut Storage, index: u64) -> Ldd {
if index == 0 {
storage.empty_set().clone()
} else if index == 1 {
storage.empty_vector().clone()
} else {
self.indexed_set.get(&index).unwrap().clone()
}
}
}
impl Default for SylvanReader {
fn default() -> Self {
Self::new()
}
}
pub fn read_u32<R: Read>(stream: &mut R) -> Result<u32, MercError> {
let mut buffer: [u8; 4] = Default::default();
stream.read_exact(&mut buffer)?;
Ok(u32::from_le_bytes(buffer))
}
pub fn read_u64<R: Read>(stream: &mut R) -> Result<u64, MercError> {
let mut buffer: [u8; 8] = Default::default();
stream.read_exact(&mut buffer)?;
Ok(u64::from_le_bytes(buffer))
}