use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::ops::Index;
type InternalIndex = usize;
type ExternalIndex = usize;
type Direction = u8;
type Balance = i8;
const NO_INDEX: InternalIndex = usize::MAX;
const HEAD_INDEX: InternalIndex = 0;
#[derive(Default, Clone)]
pub struct AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
lookup: HashMap<ValueType, InternalIndex>,
data: Vec<AVLNode<ValueType>>,
}
#[derive(Clone)]
struct AVLNode<ValueType> {
child: [InternalIndex; 2],
value: ValueType,
balance: Balance,
direction: Direction,
rank: ExternalIndex,
parent: InternalIndex,
}
impl<ValueType> Index<usize> for AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
type Output = ValueType;
fn index(&self, index: usize) -> &Self::Output {
return self.get(index).unwrap();
}
}
impl<ValueType> PartialEq for AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
let mut it1 = self.iter();
let mut it2 = other.iter();
loop {
match (it1.next(), it2.next()) {
(None, None) => {
return true; }
(Some(x), Some(y)) => {
if x != y {
return false; }
}
_ => {
return false; }
}
}
}
}
impl<ValueType> Debug for AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone + Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
return f.debug_list().entries(self.iter()).finish();
}
}
impl<ValueType> FromIterator<ValueType> for AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
fn from_iter<I: IntoIterator<Item = ValueType>>(
iter: I,
) -> AssociativePositionalList<ValueType> {
let mut p: AssociativePositionalList<ValueType> = AssociativePositionalList::new();
for (i, x) in iter.into_iter().enumerate() {
p.insert(i, x.clone());
}
p
}
}
struct IterStackItem {
index: InternalIndex,
direction: Direction,
}
pub struct Iter<'a, ValueType: 'a>
where
ValueType: std::hash::Hash + Eq + Clone,
{
stack: Vec<IterStackItem>,
parent: &'a AssociativePositionalList<ValueType>,
}
impl<'a, ValueType> Iterator for Iter<'a, ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
type Item = ValueType;
fn next(&mut self) -> Option<Self::Item> {
if self.stack.is_empty() {
return None;
}
let mut c = self.stack.last().unwrap().index;
c = self.parent.iget(c).child[1];
if c != NO_INDEX {
self.stack.push(IterStackItem {
index: c,
direction: 1,
});
loop {
c = self.parent.iget(c).child[0];
if c == NO_INDEX {
break;
}
self.stack.push(IterStackItem {
index: c,
direction: 0,
});
}
} else {
loop {
let direction = self.stack.last().unwrap().direction;
self.stack.pop();
if direction == 0 {
break;
}
if self.stack.is_empty() {
return None;
}
}
}
let n: &AVLNode<ValueType> = self.parent.iget(self.stack.last().unwrap().index);
Some(n.value.clone())
}
}
impl<ValueType> AssociativePositionalList<ValueType>
where
ValueType: std::hash::Hash + Eq + Clone,
{
pub fn new() -> Self {
AssociativePositionalList {
data: Vec::new(),
lookup: HashMap::new(),
}
}
fn iget(&self, index: InternalIndex) -> &AVLNode<ValueType> {
return self.data.get(index).unwrap();
}
fn iget_mut(&mut self, index: InternalIndex) -> &mut AVLNode<ValueType> {
return self.data.get_mut(index).unwrap();
}
fn head(&self) -> &AVLNode<ValueType> {
if self.data.is_empty() {
panic!("cannot access head() until one element has been inserted");
}
return self.iget(HEAD_INDEX);
}
fn left_rank(&self, index: InternalIndex) -> ExternalIndex {
let c = self.iget(index).child[0];
if c != NO_INDEX {
return self.iget(c).rank;
}
0
}
pub fn is_empty(&self) -> bool {
self.lookup.is_empty()
}
pub fn len(&self) -> ExternalIndex {
self.lookup.len()
}
pub fn find(&self, value: &ValueType) -> Option<ExternalIndex> {
let mut p: InternalIndex = *self.lookup.get(value)?;
if self.iget(p).value != *value {
return None; }
let mut ext_index: ExternalIndex = self.left_rank(p);
let end: InternalIndex = self.head().child[1];
while p != end {
if self.iget(p).direction == 1 {
p = self.iget(p).parent;
ext_index += self.left_rank(p) + 1;
} else {
p = self.iget(p).parent;
}
}
Some(ext_index)
}
pub fn get(&self, index: ExternalIndex) -> Option<&ValueType> {
if self.data.is_empty() {
return None;
}
let mut p: InternalIndex = self.head().child[1];
let mut ext_index_copy = index;
loop {
if p == NO_INDEX {
return None; } else if ext_index_copy < self.left_rank(p) {
p = self.iget(p).child[0];
} else if ext_index_copy == self.left_rank(p) {
return Some(&self.iget(p).value); } else {
ext_index_copy -= self.left_rank(p) + 1;
p = self.iget(p).child[1];
}
}
}
pub fn iter(&self) -> Iter<ValueType> {
let mut stack: Vec<IterStackItem> = Vec::new();
if !self.is_empty() {
stack.push(IterStackItem {
index: HEAD_INDEX,
direction: 1,
});
}
Iter {
parent: self,
stack: stack,
}
}
pub fn clear(&mut self) {
if !self.data.is_empty() {
self.lookup.clear();
self.data.truncate(HEAD_INDEX + 1);
self.iget_mut(HEAD_INDEX).child = [NO_INDEX, NO_INDEX];
}
}
fn new_node(&mut self, value: ValueType) -> InternalIndex {
let n: AVLNode<ValueType> = AVLNode {
child: [NO_INDEX, NO_INDEX],
value: value,
balance: 0,
direction: 0,
rank: 0,
parent: NO_INDEX,
};
self.data.push(n);
self.data.len() - 1
}
fn free_node(&mut self, remove_index: InternalIndex) {
let replacement: AVLNode<ValueType> = self.data.pop().unwrap();
let replacement_index: InternalIndex = self.data.len();
if remove_index >= replacement_index {
return;
}
if let Some(parent) = self.data.get_mut(replacement.parent) {
for i in 0..2 as Direction {
if parent.child[i as usize] == replacement_index {
parent.child[i as usize] = remove_index;
}
}
}
for i in 0..2 as Direction {
if let Some(child) = self.data.get_mut(replacement.child[i as usize]) {
child.parent = remove_index;
}
}
self.lookup.insert(replacement.value.clone(), remove_index);
*self.data.get_mut(remove_index).unwrap() = replacement;
}
pub fn insert(&mut self, index: ExternalIndex, value: ValueType) -> bool {
if self.data.is_empty() {
if self.new_node(value.clone()) != HEAD_INDEX {
panic!("index of head node is not HEAD_INDEX");
}
}
let mut p: InternalIndex = self.head().child[1]; let mut s: InternalIndex = self.head().child[1]; let mut t: InternalIndex = HEAD_INDEX; let mut q: InternalIndex;
let r: InternalIndex;
let mut direction: Direction;
let mut s_index: ExternalIndex = index; let mut c_index: ExternalIndex = index;
if p == NO_INDEX {
let i = self.new_node(value.clone());
self.iget_mut(HEAD_INDEX).child[1] = i;
let mut n = self.iget_mut(i);
n.direction = 1;
n.rank = 1;
n.parent = HEAD_INDEX;
self.lookup.insert(value, i);
return true;
}
if self.lookup.contains_key(&value) {
return false;
}
loop {
if c_index <= self.left_rank(p) {
direction = 0;
} else {
direction = 1;
c_index -= self.left_rank(p) + 1;
}
self.iget_mut(p).rank += 1;
q = self.iget(p).child[direction as usize];
if q != NO_INDEX {
if self.iget(q).balance != 0 {
t = p;
s = q;
s_index = c_index;
}
p = q;
} else {
q = self.new_node(value.clone());
let mut n = self.iget_mut(q);
n.direction = direction;
n.rank = 1;
n.parent = p;
n.balance = 0;
self.iget_mut(p).child[direction as usize] = q;
self.lookup.insert(value, q);
break;
}
}
c_index = s_index;
if c_index <= self.left_rank(s) {
p = self.iget(s).child[0];
r = p;
} else {
c_index -= self.left_rank(s) + 1;
p = self.iget(s).child[1];
r = p;
}
while p != q {
if c_index <= self.left_rank(p) {
self.iget_mut(p).balance = -1;
p = self.iget(p).child[0];
} else {
c_index -= self.left_rank(p) + 1;
self.iget_mut(p).balance = 1;
p = self.iget(p).child[1];
}
}
let a: Balance;
if s_index <= self.left_rank(s) {
a = -1;
direction = 0;
} else {
a = 1;
direction = 1;
}
if self.iget(s).balance == 0 {
self.iget_mut(s).balance = a;
return true;
} else if self.iget(s).balance == -a {
self.iget_mut(s).balance = 0;
return true;
}
if self.iget(r).balance == a {
p = self.single_rotation(r, s, direction);
self.rerank(s);
self.rerank(r);
self.rerank(p);
} else if self.iget(r).balance == -a {
p = self.double_rotation(r, s, direction);
self.rerank(s);
self.rerank(r);
self.rerank(p);
} else {
panic!();
}
if s == self.iget(t).child[1] {
self.iget_mut(t).child[1] = p;
self.iget_mut(p).parent = t;
self.iget_mut(p).direction = 1;
} else {
self.iget_mut(t).child[0] = p;
self.iget_mut(p).parent = t;
self.iget_mut(p).direction = 0;
}
true
}
fn single_rotation(
&mut self,
r: InternalIndex,
s: InternalIndex,
direction: Direction,
) -> InternalIndex {
let p = r;
self.iget_mut(s).child[direction as usize] = self.iget(r).child[1 - direction as usize]; self.iget_mut(r).child[1 - direction as usize] = s; self.iget_mut(s).balance = 0;
self.iget_mut(r).balance = 0;
self.iget_mut(s).direction = 1 - direction;
self.iget_mut(s).parent = r;
if self.iget(s).child[direction as usize] != NO_INDEX {
let c = self.iget(s).child[direction as usize];
self.iget_mut(c).parent = s;
self.iget_mut(c).direction = direction;
}
p
}
fn double_rotation(
&mut self,
r: InternalIndex,
s: InternalIndex,
direction: Direction,
) -> InternalIndex {
let a: Balance = if direction > 0 { 1 } else { -1 };
let p: InternalIndex = self.iget(r).child[1 - direction as usize]; self.iget_mut(r).child[1 - direction as usize] = self.iget(p).child[direction as usize]; self.iget_mut(p).child[direction as usize] = r; self.iget_mut(s).child[direction as usize] = self.iget(p).child[1 - direction as usize]; self.iget_mut(p).child[1 - direction as usize] = s; if self.iget(p).balance == a {
self.iget_mut(s).balance = -a;
self.iget_mut(r).balance = 0;
} else if self.iget(p).balance == 0 {
self.iget_mut(s).balance = 0;
self.iget_mut(r).balance = 0;
} else {
self.iget_mut(s).balance = 0;
self.iget_mut(r).balance = a;
}
self.iget_mut(p).balance = 0;
self.iget_mut(s).parent = p;
self.iget_mut(s).direction = 1 - direction;
let sc = self.iget(s).child[direction as usize];
if sc != NO_INDEX {
self.iget_mut(sc).parent = s;
self.iget_mut(sc).direction = direction;
}
self.iget_mut(r).parent = p;
self.iget_mut(r).direction = direction;
let rc = self.iget(r).child[1 - direction as usize];
if rc != NO_INDEX {
self.iget_mut(rc).parent = r;
self.iget_mut(rc).direction = 1 - direction;
}
p
}
fn rerank(&mut self, node: InternalIndex) {
self.iget_mut(node).rank = 1;
for i in 0..2 {
if self.iget(node).child[i] != NO_INDEX {
self.iget_mut(node).rank += self.iget(self.iget(node).child[i]).rank;
}
}
}
pub fn remove(&mut self, index: ExternalIndex) {
if self.data.is_empty() {
return;
}
let mut p: InternalIndex = self.head().child[1];
let mut adjust_p: InternalIndex = HEAD_INDEX;
let mut adjust_direction: Direction = 1;
let mut c_index: ExternalIndex = index;
if (p == NO_INDEX) || (index >= self.iget(p).rank) {
return;
}
loop {
if p == NO_INDEX {
panic!("unable to find index");
}
self.iget_mut(p).rank -= 1;
match c_index.cmp(&self.left_rank(p)) {
Ordering::Less => {
adjust_p = p;
adjust_direction = 0;
p = self.iget(p).child[0];
}
Ordering::Equal => {
break;
}
Ordering::Greater => {
adjust_p = p;
adjust_direction = 1;
c_index -= self.left_rank(p) + 1;
p = self.iget(p).child[1];
}
}
}
let free_before_returning: InternalIndex;
if (self.iget(p).child[0] != NO_INDEX) && (self.iget(p).child[1] != NO_INDEX) {
let q = p;
adjust_p = p;
adjust_direction = 1;
p = self.iget(p).child[1];
while self.iget(p).child[0] != NO_INDEX {
self.iget_mut(p).rank -= 1;
adjust_p = p;
adjust_direction = 0;
p = self.iget(p).child[0];
}
self.iget_mut(p).rank -= 1;
let p_child_1 = self.iget(p).child[1];
self.lookup.remove(&self.iget(q).value.clone());
self.lookup.insert(self.iget(p).value.clone(), q);
self.iget_mut(q).value = self.iget(p).value.clone();
free_before_returning = p;
p = q;
self.iget_mut(adjust_p).child[adjust_direction as usize] = p_child_1;
if p_child_1 != NO_INDEX {
self.iget_mut(p_child_1).parent = adjust_p;
self.iget_mut(p_child_1).direction = adjust_direction;
}
self.iget_mut(self.iget(p).child[0]).parent = p;
self.iget_mut(self.iget(p).child[0]).direction = 0;
if self.iget(p).child[1] != NO_INDEX {
self.iget_mut(self.iget(p).child[1]).parent = p;
self.iget_mut(self.iget(p).child[1]).direction = 1;
}
} else if self.iget(p).child[0] != NO_INDEX {
self.lookup.remove(&self.iget(p).value.clone());
self.iget_mut(adjust_p).child[adjust_direction as usize] = self.iget(p).child[0];
self.iget_mut(self.iget(p).child[0]).parent = adjust_p;
self.iget_mut(self.iget(p).child[0]).direction = adjust_direction;
free_before_returning = p;
} else {
self.lookup.remove(&self.iget(p).value.clone());
self.iget_mut(adjust_p).child[adjust_direction as usize] = self.iget(p).child[1];
let c = self.iget(p).child[1];
if c != NO_INDEX {
self.iget_mut(c).parent = adjust_p;
self.iget_mut(c).direction = adjust_direction;
}
free_before_returning = p;
}
while self.iget(adjust_p).parent != NO_INDEX {
let next_adjust_direction: Direction = self.iget(adjust_p).direction;
let next_adjust_p: InternalIndex = self.iget(adjust_p).parent;
let adjust_a: Balance = if adjust_direction == 1 { 1 } else { -1 };
if self.iget(adjust_p).balance == adjust_a {
self.iget_mut(adjust_p).balance = 0;
} else if self.iget(adjust_p).balance == 0 {
self.iget_mut(adjust_p).balance = -adjust_a;
break;
} else {
let s = adjust_p; let r = self.iget(adjust_p).child[1 - adjust_direction as usize];
if self.iget(r).balance == -adjust_a {
p = self.single_rotation(r, s, 1 - adjust_direction);
self.iget_mut(next_adjust_p).child[next_adjust_direction as usize] = p;
self.iget_mut(p).parent = next_adjust_p;
self.iget_mut(p).direction = next_adjust_direction;
self.rerank(s);
self.rerank(r);
self.rerank(p);
} else if self.iget(r).balance == adjust_a {
p = self.double_rotation(r, s, 1 - adjust_direction);
self.iget_mut(next_adjust_p).child[next_adjust_direction as usize] = p;
self.iget_mut(p).parent = next_adjust_p;
self.iget_mut(p).direction = next_adjust_direction;
self.rerank(s);
self.rerank(r);
self.rerank(p);
} else if self.iget(r).balance == 0 {
p = self.single_rotation(r, s, 1 - adjust_direction);
self.iget_mut(next_adjust_p).child[next_adjust_direction as usize] = p;
self.iget_mut(adjust_p).balance = -adjust_a;
self.iget_mut(p).balance = adjust_a;
self.iget_mut(p).parent = next_adjust_p;
self.iget_mut(p).direction = next_adjust_direction;
self.rerank(s);
self.rerank(r);
self.rerank(p);
break; } else {
panic!();
}
}
adjust_direction = next_adjust_direction;
adjust_p = next_adjust_p;
}
self.free_node(free_before_returning);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_equality() {
let a: AssociativePositionalList<i8> = [1].into_iter().collect();
let b: AssociativePositionalList<i8> = [].into_iter().collect();
let c: AssociativePositionalList<i8> = [1].into_iter().collect();
assert_ne!(a, b);
assert_ne!(b, a);
assert_eq!(a, c);
assert_eq!(c, a);
}
#[test]
fn test_randomly() {
use rand::rngs::StdRng;
use rand::Rng;
use rand::SeedableRng;
type Rank = usize;
type Depth = usize;
type TestValueType = u16;
type TestAssociativePositionalList = AssociativePositionalList<TestValueType>;
fn get_max_depth(test_me: &TestAssociativePositionalList, node: InternalIndex) -> Depth {
let mut d1: Depth = 0;
let mut d2: Depth = 0;
let c1 = test_me.iget(node).child[0];
if c1 != NO_INDEX {
d1 = 1 + get_max_depth(test_me, c1);
}
let c2 = test_me.iget(node).child[1];
if c2 != NO_INDEX {
d2 = 1 + get_max_depth(test_me, c2);
}
Depth::max(d1, d2)
}
fn get_balance(test_me: &TestAssociativePositionalList, node: InternalIndex) -> Balance {
let mut d1: Depth = 0;
let mut d2: Depth = 0;
let c1 = test_me.iget(node).child[0];
if c1 != NO_INDEX {
d1 = 1 + get_max_depth(test_me, c1);
}
let c2 = test_me.iget(node).child[1];
if c2 != NO_INDEX {
d2 = 1 + get_max_depth(test_me, c2);
}
((d2 as isize) - (d1 as isize)) as Balance
}
fn get_rank(test_me: &TestAssociativePositionalList, node: InternalIndex) -> Rank {
let mut rank: Rank = 1;
for i in 0..2 {
let c = test_me.iget(node).child[i];
if c != NO_INDEX {
rank += get_rank(test_me, c);
}
}
rank
}
fn check_consistent_node(
test_me: &TestAssociativePositionalList,
node: InternalIndex,
visited: &mut HashMap<InternalIndex, bool>,
) {
assert!(!visited.contains_key(&node));
visited.insert(node, true);
assert!(node < test_me.data.len());
for i in 0..2 as Direction {
let child = test_me.iget(node).child[i as usize];
if child != NO_INDEX {
check_consistent_node(test_me, child, visited);
assert_eq!(test_me.iget(child).parent, node);
assert_eq!(test_me.iget(child).direction, i);
}
}
let r = get_rank(test_me, node);
assert_eq!(r, test_me.iget(node).rank);
let x = get_balance(test_me, node);
assert!(x >= -1);
assert!(x <= 1);
assert_eq!(x, test_me.iget(node).balance);
}
fn check_consistent(test_me: &TestAssociativePositionalList) {
if test_me.data.is_empty() {
assert!(test_me.lookup.is_empty());
return;
}
if test_me.head().child[1] == NO_INDEX {
return;
}
assert_eq!(test_me.iget(test_me.head().child[1]).parent, HEAD_INDEX);
assert_eq!(test_me.iget(test_me.head().child[1]).direction, 1);
let mut visited: HashMap<InternalIndex, bool> = HashMap::new();
check_consistent_node(test_me, test_me.head().child[1], &mut visited);
assert_eq!(visited.len(), test_me.len());
}
fn check_with_list_node(
test_me: &TestAssociativePositionalList,
node: InternalIndex,
ref_list: &[TestValueType],
) {
let mut size: Rank = 0;
let c1 = test_me.iget(node).child[0];
if c1 != NO_INDEX {
size += test_me.iget(c1).rank;
check_with_list_node(test_me, c1, &ref_list[0..size]);
}
assert_eq!(ref_list[size], test_me.iget(node).value);
let node2 = test_me.lookup.get(&test_me.iget(node).value);
assert!(node2.is_some());
assert_eq!(*node2.unwrap(), node);
size += 1;
let c2 = test_me.iget(node).child[1];
if c2 != NO_INDEX {
check_with_list_node(test_me, c2, &ref_list[size..ref_list.len()]);
size += test_me.iget(c2).rank;
}
assert_eq!(size, ref_list.len());
}
fn check_with_list(test_me: &TestAssociativePositionalList, ref_list: &Vec<TestValueType>) {
if test_me.data.is_empty() {
assert!(test_me.lookup.is_empty());
assert!(ref_list.is_empty());
assert!(Vec::from_iter(test_me.iter()).is_empty());
assert!(test_me.is_empty());
assert_eq!(test_me.len(), 0);
return;
}
assert_eq!(test_me.lookup.len(), ref_list.len());
assert_eq!(test_me.data.len(), ref_list.len() + 1); assert_eq!(test_me.len(), ref_list.len());
assert!(test_me.get(ref_list.len()).is_none());
let c = test_me.head().child[1];
if c == NO_INDEX {
assert!(ref_list.is_empty());
assert!(test_me.is_empty());
} else {
assert!(!ref_list.is_empty()); assert!(!test_me.is_empty());
assert_eq!(test_me.iget(c).rank, test_me.lookup.len());
check_with_list_node(test_me, c, ref_list.as_slice());
}
let mut i: usize = 0;
for value in test_me.iter() {
assert_eq!(*ref_list.get(i).unwrap(), value);
i += 1;
}
assert_eq!(ref_list.len(), i);
for j in 0..ref_list.len() {
assert_eq!(ref_list[j], test_me[j]);
}
}
fn check_all(test_me: &TestAssociativePositionalList, ref_list: &Vec<TestValueType>) {
check_consistent(test_me);
check_with_list(test_me, ref_list);
}
let mut test_me: TestAssociativePositionalList = AssociativePositionalList::new();
let mut ref_list: Vec<TestValueType> = Vec::new();
check_all(&test_me, &ref_list);
let mut rng = StdRng::seed_from_u64(1);
let test_size: TestValueType = 1000;
assert!(test_me.is_empty());
assert!(test_me == test_me);
assert_eq!(test_me, test_me);
for k in 1..test_size + 1 {
let i = rng.gen_range(0..(ref_list.len() + 1) as TestValueType);
let inserted = test_me.insert(i as usize, k);
ref_list.insert(i as usize, k);
assert!(inserted);
check_all(&test_me, &ref_list);
}
assert!(!test_me.is_empty());
for k in 1..test_size + 1 {
let j = test_me.find(&k);
assert!(j.is_some());
assert!(j.unwrap() < ref_list.len());
assert!(ref_list[j.unwrap()] == k);
}
for k in 1..10 {
let i = rng.gen_range(0..(ref_list.len() + 1) as TestValueType);
let inserted = test_me.insert(i as usize, k);
assert!(!inserted);
}
for k in 1..10 {
let i = rng.gen_range(0..(ref_list.len() + 1) as TestValueType);
let inserted = test_me.insert(i as usize, test_size - k);
assert!(!inserted);
}
check_all(&test_me, &ref_list);
assert!(test_me == test_me);
assert_eq!(test_me, test_me);
for _ in 1..(test_size / 2) {
let i = rng.gen_range(0..ref_list.len() as TestValueType);
test_me.remove(i as usize);
ref_list.remove(i as usize);
check_all(&test_me, &ref_list);
}
for k in (test_size + 1)..(test_size * 10) + 1 {
if rng.gen_ratio(1, 2) && !ref_list.is_empty() {
let i: usize = (rng.gen_range(0..ref_list.len() as TestValueType)) as usize;
let v: &TestValueType = ref_list.get(i).unwrap();
assert_eq!(test_me.find(v).unwrap(), i);
ref_list.remove(i);
test_me.remove(i);
} else {
let i: usize = rng.gen_range(0..ref_list.len() + 1);
ref_list.insert(i, k);
let inserted = test_me.insert(i, k);
assert!(inserted);
let j = test_me.find(&k);
assert_eq!(j.unwrap(), i);
}
check_all(&test_me, &ref_list);
}
while !ref_list.is_empty() {
let i: usize = (rng.gen_range(0..ref_list.len() as TestValueType)) as usize;
ref_list.remove(i);
test_me.remove(i);
check_all(&test_me, &ref_list);
}
assert!(test_me.is_empty());
assert!(test_me == test_me);
assert_eq!(test_me, test_me);
for j in 0..3 {
if j == 2 {
test_me = AssociativePositionalList::new();
}
test_me.clear();
ref_list.clear();
assert!(test_me.is_empty());
if j == 2 {
assert_eq!(test_me.data.len(), 0); } else {
assert_eq!(test_me.data.len(), 1); }
for k in 1..10 {
let i = rng.gen_range(0..(ref_list.len() + 1) as TestValueType);
let inserted = test_me.insert(i as usize, k);
ref_list.insert(i as usize, k);
assert!(inserted);
check_all(&test_me, &ref_list);
}
}
{
let mut another: TestAssociativePositionalList = AssociativePositionalList::new();
assert!(test_me != another);
for (i, x) in test_me.iter().enumerate() {
another.insert(i, x);
}
assert!(test_me == another); let v = another[1];
another.remove(1);
assert!(test_me != another); another.insert(1, 0);
assert!(test_me != another); another.insert(1, v);
another.remove(2);
assert!(test_me == another); }
}
#[test]
fn test_interfaces() {
let mut p: AssociativePositionalList<String> = AssociativePositionalList::new();
p.insert(0, "Hello".to_string());
p.insert(1, "World".to_string());
assert_eq!(p.find(&"World".to_string()), Some(1));
assert_eq!(p.len(), 2);
assert_eq!(p[0], "Hello");
assert_eq!(p[1], "World");
assert_eq!(&format!("{:?}", p), "[\"Hello\", \"World\"]"); assert_eq!(p, p);
assert!(!p.is_empty());
for n in p.iter() {
assert!(n == "Hello" || n == "World");
}
let mut p1 = p.clone();
assert_eq!(p, p1);
p.remove(0);
assert_ne!(p, p1);
assert_eq!(p[0], "World");
assert_eq!(p.find(&"Hello".to_string()), None);
assert_eq!(p.find(&"World".to_string()), Some(0));
p.remove(0);
assert!(p.is_empty());
assert_eq!(p1[0], "Hello");
assert_eq!(p1[1], "World");
p1.remove(1);
assert_eq!(p1.len(), 1);
assert_eq!(p1[0], "Hello");
assert_eq!(p1.find(&"Hello".to_string()), Some(0));
p1.remove(0);
assert!(p1.is_empty());
assert_eq!(&format!("{:?}", p), "[]");
let mut p2: AssociativePositionalList<i8> = AssociativePositionalList::new();
for i in 0..5 {
p2.insert(0, i);
}
assert_eq!(&format!("{:?}", p2), "[4, 3, 2, 1, 0]");
assert_eq!(p2.find(&0), Some(4));
p2.remove(1);
assert_eq!(p2.find(&0), Some(3));
assert_eq!(&format!("{:?}", p2), "[4, 2, 1, 0]");
}
}