use std::collections::{HashMap};
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash};
use crate::util::{CommaSeparated};
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Use(
std::num::NonZeroUsize
) {
debug_name: "Use",
UInt: usize,
}
}
pub struct Usage<I: Debug, V: Debug + Clone + Hash + Eq> {
instructions: Vec<(I, usize)>,
heads: HashMap<V, Use>,
nexts: Vec<(V, Option<Use>)>,
}
impl<I: Debug, V: Debug + Clone + Hash + Eq> Usage<I, V> {
pub fn first(&self, value: V) -> Option<impl Ord> {
self.heads.get(&value).cloned()
}
pub fn push(&mut self, instruction: I, values: impl IntoIterator<Item=V>) {
self.instructions.push((instruction, self.nexts.len()));
for v in values {
let next = self.heads.insert(v.clone(), Use::new(self.nexts.len()).expect("Overflow"));
self.nexts.push((v, next));
}
}
pub fn pop<'a>(&'a mut self) -> Option<I> {
self.instructions.pop().map(|(instruction, length)| {
let to_remove = length..self.nexts.len();
for i in to_remove.clone().rev() {
let (ref v, next) = self.nexts[i];
let head = if let Some(mut next) = next {
std::mem::swap(&mut next, self.heads.get_mut(v).expect("Missing head"));
next
} else {
self.heads.remove(v).expect("Missing head")
};
assert_eq!(head, Use::new(i).expect("Overflow"));
}
self.nexts.drain(to_remove);
instruction
})
}
}
impl<I: Debug, V: Debug + Clone + Hash + Eq> Default for Usage<I, V> {
fn default() -> Self {
Usage {instructions: Vec::new(), heads: HashMap::new(), nexts: Vec::new()}
}
}
impl<I: Debug, V: Debug + Clone + Hash + Eq> Debug for Usage<I, V> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str("Usage")?;
let mut dm = f.debug_map();
let mut next = self.nexts.len();
for &(ref instruction, length) in self.instructions.iter().rev() {
dm.entry(instruction, &CommaSeparated(|| &self.nexts[length..next]));
next = length;
}
dm.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::util::{AsUsize};
fn all_uses<I: Debug, V: Debug + Clone + Hash + Eq>(
usage: &Usage<I, V>,
value: &V,
) -> Vec<usize> {
let mut ret = Vec::new();
let mut head: Option<Use> = unsafe { std::mem::transmute(usage.first(value.clone())) };
while let Some(next) = head {
ret.push(next.as_usize());
head = usage.nexts[next.as_usize()].1;
}
ret
}
fn pop_with_values<I: Debug, V: Debug + Clone + Hash + Eq>(
usage: &mut Usage<I, V>,
) -> (I, Vec<V>) {
let &(_, length) = usage.instructions.last().unwrap();
let slice = &usage.nexts[length..usage.nexts.len()];
let top_values = slice.iter().map(|(v, _)| v.clone()).collect();
(usage.pop().unwrap(), top_values)
}
#[test]
pub fn test() {
let mut usage: Usage<char, usize> = Default::default();
usage.push('D', vec![4]);
usage.push('C', vec![2, 3]);
usage.push('B', vec![0, 2]);
usage.push('A', vec![0, 1]);
assert_eq!(all_uses(&usage, &0), vec![5, 3]);
assert_eq!(all_uses(&usage, &1), vec![6]);
let (i, vs) = pop_with_values(&mut usage);
assert_eq!(i, 'A');
assert_eq!(vs, vec![0, 1]);
assert_eq!(all_uses(&usage, &0), vec![3]);
assert_eq!(all_uses(&usage, &1), vec![]);
assert_eq!(all_uses(&usage, &2), vec![4, 1]);
let (i, vs) = pop_with_values(&mut usage);
assert_eq!(i, 'B');
assert_eq!(vs, vec![0, 2]);
assert_eq!(all_uses(&usage, &0), vec![]);
assert_eq!(all_uses(&usage, &2), vec![1]);
assert_eq!(all_uses(&usage, &3), vec![2]);
let (i, vs) = pop_with_values(&mut usage);
assert_eq!(i, 'C');
assert_eq!(vs, vec![2, 3]);
assert_eq!(all_uses(&usage, &2), vec![]);
assert_eq!(all_uses(&usage, &3), vec![]);
assert_eq!(all_uses(&usage, &4), vec![0]);
let (i, vs) = pop_with_values(&mut usage);
assert_eq!(i, 'D');
assert_eq!(vs, vec![4]);
assert_eq!(all_uses(&usage, &3), vec![]);
assert_eq!(all_uses(&usage, &4), vec![]);
assert!(usage.pop().is_none());
}
}