pub trait PackedCollection {
fn len(&self) -> usize;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
fn set(&mut self, index: usize, value: u64);
fn get(&self, index: usize) -> u64;
fn append(&mut self, value: u64);
fn pop(&mut self);
fn clear(&mut self);
}
pub trait PackedElement: Sized + Copy {
fn unpack(v: u64) -> Self;
fn pack(self) -> u64;
}
impl PackedElement for bool {
#[inline]
fn unpack(v: u64) -> bool {
v == 1
}
#[inline]
fn pack(self) -> u64 {
self.into()
}
}
impl PackedElement for u8 {
#[inline]
fn unpack(v: u64) -> u8 {
use std::convert::TryFrom;
if let Ok(u) = u8::try_from(v) {
u
} else {
std::u8::MAX
}
}
#[inline]
fn pack(self) -> u64 {
u64::from(self)
}
}
pub trait Viewable: PackedCollection + Sized {
fn view<T>(&self, index: usize) -> ViewRef<'_, Self, T>
where
T: PackedElement;
#[inline]
fn get_unpack<T>(&self, index: usize) -> T
where
T: PackedElement,
{
T::unpack(self.get(index))
}
}
impl<V> Viewable for V
where
V: PackedCollection + Sized,
{
#[inline]
fn view<T>(&self, index: usize) -> ViewRef<'_, Self, T>
where
T: PackedElement,
{
ViewRef::new(self, index)
}
}
pub trait MutViewable: PackedCollection + Sized {
fn view_mut<T>(&mut self, index: usize) -> ViewMut<'_, Self, T>
where
T: PackedElement;
#[inline]
fn set_pack<T>(&mut self, index: usize, value: T)
where
T: PackedElement,
{
self.set(index, value.pack())
}
}
impl<V> MutViewable for V
where
V: PackedCollection + Sized,
{
#[inline]
fn view_mut<T>(&mut self, index: usize) -> ViewMut<'_, Self, T>
where
T: PackedElement,
{
ViewMut::new(self, index)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ViewRef<'a, V, T>
where
V: PackedCollection + Sized,
T: PackedElement,
{
_collection: &'a V,
_index: usize,
value: T,
}
impl<'a, V, T> ViewRef<'a, V, T>
where
V: PackedCollection + Sized,
T: PackedElement,
{
fn new(collection: &'a V, index: usize) -> Self {
let value = T::unpack(collection.get(index));
Self {
_collection: collection,
_index: index,
value,
}
}
pub fn get(&self) -> T {
self.value
}
}
#[derive(Debug)]
pub struct ViewMut<'a, V, T>
where
V: PackedCollection,
T: PackedElement,
{
collection: &'a mut V,
index: usize,
value: T,
}
impl<'a, V, T> ViewMut<'a, V, T>
where
V: PackedCollection,
T: PackedElement,
{
fn new(collection: &'a mut V, index: usize) -> Self {
let value = T::unpack(collection.get(index));
Self {
collection,
index,
value,
}
}
pub fn get(&self) -> T {
self.value
}
pub fn set(&mut self, value: T) {
self.value = value;
self.collection.set(self.index, value.pack())
}
}
macro_rules! impl_packed_element_as {
($for:ty) => {
impl PackedElement for $for {
#[inline]
fn unpack(v: u64) -> $for {
v as $for
}
#[inline]
fn pack(self) -> u64 {
self as u64
}
}
};
}
#[allow(unused_macros)]
macro_rules! impl_packed_element_from_into {
($for:ty) => {
impl PackedElement for $for {
#[inline]
fn unpack(v: u64) -> $for {
v.into()
}
#[inline]
fn pack(self) -> u64 {
self.into()
}
}
};
}
impl_packed_element_as!(usize);
impl_packed_element_as!(u64);