use std::{collections::HashMap, hash::Hash};
use data::LinkReference;
use super::SequenceError;
use crate::{Doublets, Error};
#[derive(Clone, Copy, Debug, Default)]
pub struct AddressToRawNumberConverter;
impl AddressToRawNumberConverter {
#[must_use]
pub const fn new() -> Self {
Self
}
pub fn convert<T: LinkReference>(&self, address: T) -> Result<T, SequenceError<T>> {
let half = T::MAX / T::from_byte(2);
if address > half {
return Err(SequenceError::RawNumberOutOfRange(address));
}
Ok(if address == T::from_byte(0) {
half + T::from_byte(1)
} else {
T::MAX - address + T::from_byte(1)
})
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct RawNumberToAddressConverter;
impl RawNumberToAddressConverter {
#[must_use]
pub const fn new() -> Self {
Self
}
pub fn convert<T: LinkReference>(&self, raw_number: T) -> T {
let external_zero = T::MAX / T::from_byte(2) + T::from_byte(1);
if raw_number == external_zero {
T::from_byte(0)
} else if raw_number > external_zero {
T::MAX - raw_number + T::from_byte(1)
} else {
raw_number
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct BalancedVariantConverter;
impl BalancedVariantConverter {
#[must_use]
pub const fn new() -> Self {
Self
}
pub fn convert<T: LinkReference, L: Doublets<T>>(
&self,
links: &mut L,
elements: &[T],
) -> Result<T, Error<T>> {
if elements.is_empty() {
return Ok(links.constants().null);
}
let mut layer = elements.to_vec();
while layer.len() > 1 {
let length = layer.len();
for i in (0..length - 1).step_by(2) {
layer[i / 2] = links.get_or_create(layer[i], layer[i + 1])?;
}
if length % 2 == 1 {
layer[length / 2] = layer[length - 1];
}
layer.truncate(length.div_ceil(2));
}
Ok(layer[0])
}
}
#[derive(Clone, Debug)]
pub struct CachingConverterDecorator<K, V> {
cache: HashMap<K, V>,
}
impl<K, V> Default for CachingConverterDecorator<K, V> {
fn default() -> Self {
Self {
cache: HashMap::new(),
}
}
}
impl<K: Eq + Hash, V: Clone> CachingConverterDecorator<K, V> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn get(&self, input: &K) -> Option<V> {
self.cache.get(input).cloned()
}
pub fn insert(&mut self, input: K, output: V) -> V {
self.cache.insert(input, output.clone());
output
}
pub fn convert_with<F, E>(&mut self, input: K, convert: F) -> Result<V, E>
where
F: FnOnce(&K) -> Result<V, E>,
{
if let Some(output) = self.get(&input) {
return Ok(output);
}
let output = convert(&input)?;
Ok(self.insert(input, output))
}
pub fn clear(&mut self) {
self.cache.clear();
}
#[must_use]
pub fn len(&self) -> usize {
self.cache.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.cache.is_empty()
}
}