use crate::{Rewrite, RewritePlan};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct DenseNatMap<K, V> {
values: Vec<V>,
_key: PhantomData<K>,
}
impl<K, V> DenseNatMap<K, V> {
pub fn new() -> Self {
Self::from(Vec::new())
}
pub fn get(&self, key: K) -> Option<&V> where usize: From<K> {
let index = usize::from(key);
self.values.get(index)
}
pub fn insert(&mut self, key: K, mut value: V) -> Option<V>
where usize: From<K>,
K: From<usize>,
{
let index = usize::from(key);
if index > self.values.len() {
panic!("Out of bounds. index={}, len={}", index, self.values.len());
}
if index == self.values.len() {
self.values.push(value);
return None;
}
std::mem::swap(&mut self.values[index], &mut value);
Some(value)
}
pub fn iter(&self) -> impl Iterator<Item=(K, &V)>
where K: From<usize>,
{
self.values.iter()
.enumerate()
.map(|(i, v)| (K::from(i), v))
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize { self.values.len() }
pub fn values(&self) -> impl Iterator<Item=&V> {
self.values.iter()
}
}
impl<K, V> Default for DenseNatMap<K, V> {
fn default() -> Self {
Self::new()
}
}
impl<K, V> From<Vec<V>> for DenseNatMap<K, V> {
fn from(values: Vec<V>) -> Self {
Self {
values,
_key: PhantomData,
}
}
}
impl<K, V> FromIterator<(K, V)> for DenseNatMap<K, V> where usize: From<K> {
fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> Self {
Self {
values: {
let mut pairs: Vec<_> = iter.into_iter()
.map(|(k, v)| (usize::from(k), v))
.collect();
pairs.sort_by_key(|(k, _)| *k);
pairs.into_iter()
.enumerate()
.map(|(i_expected, (i, v))| {
if i != i_expected {
panic!("Invalid key at index. index={}, expected_index={}", i, i_expected);
}
v
})
.collect()
},
_key: PhantomData,
}
}
}
impl<K, V> FromIterator<V> for DenseNatMap<K, V> {
fn from_iter<T: IntoIterator<Item=V>>(iter: T) -> Self {
Self {
values: iter.into_iter().collect(),
_key: PhantomData,
}
}
}
impl<K, V> Index<K> for DenseNatMap<K, V>
where usize: From<K>,
{
type Output = V;
fn index(&self, key: K) -> &Self::Output {
self.values.index(usize::from(key))
}
}
impl<K, V> IndexMut<K> for DenseNatMap<K, V>
where usize: From<K>,
{
fn index_mut(&mut self, key: K) -> &mut Self::Output {
self.values.index_mut(usize::from(key))
}
}
impl<K, V> IntoIterator for DenseNatMap<K, V> where K: From<usize> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter(
self.values.into_iter().enumerate(),
PhantomData)
}
}
impl<R, K, V> Rewrite<R> for DenseNatMap<K, V>
where K: From<usize> + Rewrite<R>,
V: Rewrite<R>,
usize: From<K>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter()
.map(|(k, v)| (k.rewrite(plan), v.rewrite(plan)))
.collect()
}
}
pub struct IntoIter<K, V>(
std::iter::Enumerate<std::vec::IntoIter<V>>,
PhantomData<K>);
impl<K, V> Iterator for IntoIter<K, V> where K: From<usize> {
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(i, v)| (K::from(i), v))
}
}
#[cfg(test)]
mod test {
use crate::actor::Id;
use std::collections::{BTreeSet, BTreeMap};
use super::*;
#[test]
pub fn can_construct_and_insert() {
let mut m = DenseNatMap::new();
m.insert(Id::from(0), "first");
m.insert(Id::from(1), "second");
assert_eq!(m.into_iter().collect::<BTreeSet<_>>(), vec![
(Id::from(1), "second"), (Id::from(0), "first"),
].into_iter().collect());
}
#[test]
#[should_panic(expected = "Out of bounds. index=1, len=0")]
pub fn panics_on_out_of_order_insertion() {
let mut m = DenseNatMap::new();
m.insert(Id::from(1), "second");
}
#[test]
pub fn can_rewrite() {
#[derive(Clone, Copy, Debug, PartialEq)]
struct Id2(usize);
impl From<usize> for Id2 {
fn from(input: usize) -> Self { Id2(input) }
}
impl From<Id2> for usize {
fn from(input: Id2) -> Self { input.0 }
}
impl Rewrite<Id2> for Id2 {
fn rewrite<S>(&self, plan: &RewritePlan<Id2, S>) -> Self {
plan.rewrite(self)
}
}
impl Rewrite<Id2> for Id {
fn rewrite<S>(&self, _: &RewritePlan<Id2, S>) -> Self { *self }
}
impl Rewrite<Id> for Id2 {
fn rewrite<S>(&self, _: &RewritePlan<Id, S>) -> Self { *self }
}
let f1 = DenseNatMap::<Id, _>::from_iter(['B', 'C', 'A', 'D']);
let f2 = DenseNatMap::<Id, _>::from_iter(['X', 'Y', 'W', 'Z']);
let f3 = DenseNatMap::<Id2, _>::from_iter(['X', 'Y', 'W', 'Z']);
let f4 = BTreeMap::from_iter([('!', Id::from(0))]);
let f5 = BTreeMap::from_iter([(Id::from(0), '!')]);
let plan = RewritePlan::from(&f1);
assert_eq!(
f1.rewrite(&plan),
DenseNatMap::from_iter(['A', 'B', 'C', 'D']));
assert_eq!(
f2.rewrite(&plan),
DenseNatMap::from_iter(['W', 'X', 'Y', 'Z']));
assert_eq!(
f3.rewrite(&plan),
DenseNatMap::from_iter(['X', 'Y', 'W', 'Z'])); assert_eq!(
f4.rewrite(&plan),
BTreeMap::from_iter([('!', Id::from(1))]));
assert_eq!(
f5.rewrite(&plan),
BTreeMap::from_iter([(Id::from(1), '!')]));
let plan = RewritePlan::from(&f3);
assert_eq!(
f1.rewrite(&plan),
DenseNatMap::from_iter(['B', 'C', 'A', 'D'])); assert_eq!(
f2.rewrite(&plan),
DenseNatMap::from_iter(['X', 'Y', 'W', 'Z'])); assert_eq!(
f3.rewrite(&plan),
DenseNatMap::from_iter(['W', 'X', 'Y', 'Z']));
assert_eq!(
f4.rewrite(&plan),
BTreeMap::from_iter([('!', Id::from(0))])); assert_eq!(
f5.rewrite(&plan),
BTreeMap::from_iter([(Id::from(0), '!')])); }
}