use crate::*;
use std::marker::PhantomData;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
macro_rules! impl_getters {
($($name:ident => $ty:ty),* $(,)?) => {
$(
#[doc = concat!("Returns the value as `", stringify!($ty), "`. See [`Self::get`].")]
#[inline(always)]
pub fn $name(&self, key: E) -> Option<$ty> {
self.get::<$ty>(key)
}
)*
};
}
pub struct EnumVarMap<E: EnumVarMapKey> {
arena: Arena,
values: Vec<Option<ValueKind>>,
phantom: PhantomData<E>,
}
impl<E: EnumVarMapKey> EnumVarMap<E> {
pub fn new() -> Self {
let mut values = Vec::with_capacity(E::INDEX_COUNT as usize);
values.resize(E::INDEX_COUNT as usize, None);
Self {
arena: Arena::new(),
values,
phantom: PhantomData,
}
}
pub fn clear(&mut self) {
self.arena.clear();
self.values.iter_mut().for_each(|v| *v = None);
}
#[inline(always)]
pub fn set<T: VarMapValue>(&mut self, key: E, value: T) {
let index = key.to_index() as usize;
let mut builder = ValueBuilder::new(&mut self.arena);
let value_kind = *value.to_value(&mut builder).kind();
self.values[index] = Some(value_kind);
}
pub fn update<T: VarMapValue>(&mut self, key: E, f: impl FnOnce(&mut T)) -> bool {
let index = key.to_index() as usize;
if let Some(kind) = &mut self.values[index] {
let mut value = ValueMut::view(kind, &mut self.arena);
T::update(&mut value, f);
true
} else {
false
}
}
#[inline(always)]
pub fn get<'a, V: VarMapValue>(&'a self, key: E) -> Option<V::Decoded<'a>> {
let index = key.to_index() as usize;
let kind = self.values[index].as_ref()?;
let value = Value::view(kind, &self.arena);
V::from_value(&value)
}
#[inline(always)]
pub fn contains(&self, key: E) -> bool {
let index = key.to_index() as usize;
self.values[index].is_some()
}
impl_getters! {
get_bool => bool,
get_u8 => u8,
get_u16 => u16,
get_u32 => u32,
get_u64 => u64,
get_i8 => i8,
get_i16 => i16,
get_i32 => i32,
get_i64 => i64,
get_f32 => f32,
get_f64 => f64,
get_str => &str,
get_bytes => &[u8],
get_char => char,
get_ip => IpAddr,
get_ipv4 => Ipv4Addr,
get_ipv6 => Ipv6Addr,
}
}
impl<E: EnumVarMapKey> Default for EnumVarMap<E> {
fn default() -> Self {
Self::new()
}
}