#![forbid(unsafe_code, missing_debug_implementations, missing_docs)]
use elysees::Arc;
use num_traits::{int::PrimInt, AsPrimitive, ToPrimitive};
use ref_cast::RefCast;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
mod inner;
mod map_impls;
mod util;
pub use inner::{IdMapIntoIter, IdMapIter, InnerMap};
pub use util::*;
pub mod map_ctx;
pub mod mutation;
use mutation::*;
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct IdMap<K: RadixKey, V: Clone>(Option<Arc<InnerMap<K, V>>>);
pub type IdSet<K> = IdMap<K, ()>;
impl<K: RadixKey, V: Clone> IdMap<K, V> {
pub const EMPTY: IdMap<K, V> = IdMap(None);
pub fn new() -> IdMap<K, V> {
IdMap(None)
}
pub fn clear(&mut self) -> Option<Arc<InnerMap<K, V>>> {
let mut result = None;
std::mem::swap(&mut self.0, &mut result);
result
}
pub fn singleton_in<C: ConsCtx<K, V>>(key: K, value: V, ctx: &mut C) -> IdMap<K, V> {
IdMap(Some(ctx.cons(InnerMap::singleton(key, value))))
}
pub fn as_ptr(&self) -> *const InnerMap<K, V> {
self.0.as_ref().map(Arc::as_ptr).unwrap_or(std::ptr::null())
}
pub fn ptr_eq(&self, other: &Self) -> bool {
self.as_ptr() == other.as_ptr()
}
pub fn singleton(key: K, value: V) -> IdMap<K, V> {
Self::singleton_in(key, value, &mut ())
}
pub fn is_empty(&self) -> bool {
self.0.is_none()
}
pub fn len(&self) -> usize {
self.0.as_ref().map(|inner| inner.len()).unwrap_or(0)
}
pub fn iter(&self) -> IdMapIter<K, V> {
let mut result = IdMapIter::empty();
if let Some(inner) = &self.0 {
result.root(inner)
}
result
}
pub fn mutate_in<B, M, R, C>(&self, key: B, action: M, ctx: &mut C) -> (Option<IdMap<K, V>>, R)
where
B: Borrow<K>,
M: FnOnce(B, Option<&V>) -> (Mutation<K, V>, R),
C: ConsCtx<K, V>,
{
if let Some(inner) = &self.0 {
let (try_inner, result) = inner.mutate(inner, key, action, ctx);
if let Some(inner) = try_inner {
(Some(inner.into_idmap_in(ctx)), result)
} else {
(None, result)
}
} else {
let (mutation, result) = action(key, None);
let new_map = match mutation {
Mutation::Null => None,
Mutation::Remove => None,
Mutation::Update(_) => None,
Mutation::Insert(key, value) => Some(IdMap::singleton(key, value)),
};
(new_map, result)
}
}
pub fn mutate<B, M, R>(&self, key: B, action: M) -> (Option<IdMap<K, V>>, R)
where
B: Borrow<K>,
M: FnOnce(B, Option<&V>) -> (Mutation<K, V>, R),
{
self.mutate_in(key, action, &mut ())
}
pub fn removed_in<C: ConsCtx<K, V>>(&self, key: &K, ctx: &mut C) -> Option<IdMap<K, V>> {
self.mutate_in(key, |_key, _value| (Mutation::Remove, ()), ctx)
.0
}
pub fn removed(&self, key: &K) -> Option<IdMap<K, V>> {
self.removed_in(key, &mut ())
}
pub fn remove_in<C: ConsCtx<K, V>>(&mut self, key: &K, ctx: &mut C) -> bool {
if let Some(removed) = self.removed_in(key, ctx) {
*self = removed;
true
} else {
false
}
}
pub fn remove(&mut self, key: &K) -> bool {
if let Some(removed) = self.removed(key) {
*self = removed;
true
} else {
false
}
}
pub fn inserted_in<C: ConsCtx<K, V>>(
&self,
key: K,
value: V,
ctx: &mut C,
) -> Option<IdMap<K, V>> {
self.mutate_in(
key,
|key, old_value| {
(
if old_value.is_none() {
Mutation::Insert(key, value)
} else {
Mutation::Update(value)
},
(),
)
},
ctx,
)
.0
}
pub fn inserted(&self, key: K, value: V) -> Option<IdMap<K, V>> {
self.inserted_in(key, value, &mut ())
}
pub fn insert_in<C: ConsCtx<K, V>>(&mut self, key: K, value: V, ctx: &mut C) -> bool {
if let Some(inserted) = self.inserted_in(key, value, ctx) {
*self = inserted;
true
} else {
false
}
}
pub fn insert(&mut self, key: K, value: V) -> bool {
if let Some(inserted) = self.inserted(key, value) {
*self = inserted;
true
} else {
false
}
}
pub fn try_inserted_in<C: ConsCtx<K, V>>(
&self,
key: K,
value: V,
ctx: &mut C,
) -> Option<IdMap<K, V>> {
self.mutate_in(key, |key, _value| (Mutation::Insert(key, value), ()), ctx)
.0
}
pub fn try_inserted(&self, key: K, value: V) -> Option<IdMap<K, V>> {
self.try_inserted_in(key, value, &mut ())
}
pub fn try_insert_in<C: ConsCtx<K, V>>(&mut self, key: K, value: V, ctx: &mut C) -> bool {
if let Some(inserted) = self.try_inserted_in(key, value, ctx) {
*self = inserted;
true
} else {
false
}
}
pub fn try_insert(&mut self, key: K, value: V) -> bool {
if let Some(inserted) = self.try_inserted(key, value) {
*self = inserted;
true
} else {
false
}
}
pub fn get(&self, key: &K) -> Option<&V> {
if let Some(inner) = &self.0 {
inner.get(key)
} else {
None
}
}
pub fn contains(&self, key: &K) -> bool {
self.get(key).is_some()
}
pub fn mutated_vals_in<M, C>(&self, mutator: &mut M, ctx: &mut C) -> Option<IdMap<K, V>>
where
M: UnaryMutator<K, V>,
C: ConsCtx<K, V>,
{
match (mutator.kind(), &self.0) {
(UnaryMutatorKind::Null, _) => None,
(_, None) => None,
(UnaryMutatorKind::Delete, Some(_)) => Some(IdMap::new()),
(UnaryMutatorKind::General, Some(inner)) => {
let inner = inner.mutate_vals_in(mutator, ctx)?;
Some(inner.into_idmap_in(ctx))
}
}
}
#[inline]
pub fn mutated_vals<M>(&self, mutator: &mut M) -> Option<IdMap<K, V>>
where
M: UnaryMutator<K, V>,
{
self.mutated_vals_in(mutator, &mut ())
}
#[inline]
pub fn mutate_vals_in<M, C>(&mut self, mutator: &mut M, ctx: &mut C) -> bool
where
M: UnaryMutator<K, V>,
C: ConsCtx<K, V>,
{
if let Some(mutated) = self.mutated_vals_in(mutator, ctx) {
*self = mutated;
true
} else {
false
}
}
#[inline]
pub fn mutate_vals<M>(&mut self, mutator: &mut M) -> bool
where
M: UnaryMutator<K, V>,
{
if let Some(mutated) = self.mutated_vals_in(mutator, &mut ()) {
*self = mutated;
true
} else {
false
}
}
pub fn join_mutate_in<IM, LM, RM, C>(
&self,
other: &Self,
intersection_mutator: &mut IM,
left_mutator: &mut LM,
right_mutator: &mut RM,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>>
where
IM: BinaryMutator<K, V>,
LM: UnaryMutator<K, V>,
RM: UnaryMutator<K, V>,
C: ConsCtx<K, V>,
{
let (this, other) = match (&self.0, &other.0) {
(_, None) => return BinaryResult::or_left(self.mutated_vals_in(left_mutator, ctx)),
(None, _) => return BinaryResult::or_right(other.mutated_vals_in(right_mutator, ctx)),
(Some(this), Some(other)) => (this, other),
};
this.join_mutate_in(
other,
intersection_mutator,
left_mutator,
right_mutator,
ctx,
)
.map(|inner| inner.into_idmap_in(ctx))
}
pub fn left_union_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut NullMutator,
&mut NullMutator,
ctx,
)
}
pub fn left_intersect_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut DeleteMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn left_union(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut NullMutator,
&mut NullMutator,
&mut (),
)
}
pub fn left_intersect(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut DeleteMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn right_union_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut NullMutator,
&mut NullMutator,
ctx,
)
}
pub fn right_intersect_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut DeleteMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn right_union(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut NullMutator,
&mut NullMutator,
&mut (),
)
}
pub fn right_intersect(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut DeleteMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn union_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut NullMutator,
&mut NullMutator,
ctx,
)
}
pub fn intersect_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut DeleteMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn sym_diff_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut DeleteMutator,
&mut NullMutator,
&mut NullMutator,
ctx,
)
}
pub fn left_complement_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut NullMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn right_complement_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut NullMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn complement_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut NullMutator,
&mut DeleteMutator,
ctx,
)
}
pub fn union(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut NullMutator,
&mut NullMutator,
&mut (),
)
}
pub fn intersect(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut DeleteMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn sym_diff(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut DeleteMutator,
&mut NullMutator,
&mut NullMutator,
&mut (),
)
}
pub fn left_complement(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut LeftMutator,
&mut NullMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn right_complement(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut RightMutator,
&mut NullMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn complement(&self, other: &IdMap<K, V>) -> BinaryResult<IdMap<K, V>> {
self.join_mutate_in(
other,
&mut AmbiMutator,
&mut NullMutator,
&mut DeleteMutator,
&mut (),
)
}
pub fn left_unioned_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.left_union_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn left_intersected_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.left_intersect_in(other, ctx)
.unwrap_or_clone(self, other)
}
pub fn left_unioned(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.left_union(other).unwrap_or_clone(self, other)
}
pub fn left_intersected(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.left_intersect(other).unwrap_or_clone(self, other)
}
pub fn right_unioned_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.right_union_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn right_intersected_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.right_intersect_in(other, ctx)
.unwrap_or_clone(self, other)
}
pub fn right_unioned(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.right_union(other).unwrap_or_clone(self, other)
}
pub fn right_intersected(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.right_intersect(other).unwrap_or_clone(self, other)
}
pub fn unioned_in<C: ConsCtx<K, V>>(&self, other: &IdMap<K, V>, ctx: &mut C) -> IdMap<K, V> {
self.union_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn intersected_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.intersect_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn sym_diffed_in<C: ConsCtx<K, V>>(&self, other: &IdMap<K, V>, ctx: &mut C) -> IdMap<K, V> {
self.sym_diff_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn left_complemented_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.left_complement_in(other, ctx)
.unwrap_or_clone(self, other)
}
pub fn right_complemented_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.right_complement_in(other, ctx)
.unwrap_or_clone(self, other)
}
pub fn complemented_in<C: ConsCtx<K, V>>(
&self,
other: &IdMap<K, V>,
ctx: &mut C,
) -> IdMap<K, V> {
self.complement_in(other, ctx).unwrap_or_clone(self, other)
}
pub fn unioned(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.union(other).unwrap_or_clone(self, other)
}
pub fn intersected(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.intersect(other).unwrap_or_clone(self, other)
}
pub fn sym_diffed(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.sym_diff(other).unwrap_or_clone(self, other)
}
pub fn left_complemented(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.left_complement(other).unwrap_or_clone(self, other)
}
pub fn complemented(&self, other: &IdMap<K, V>) -> IdMap<K, V> {
self.complement(other).unwrap_or_clone(self, other)
}
}
impl<K: RadixKey, V: Clone + Eq> IdMap<K, V> {
pub fn inserted_conservative_in<C: ConsCtx<K, V>>(
&self,
key: K,
value: V,
ctx: &mut C,
) -> Option<IdMap<K, V>> {
self.mutate_in(
key,
|key, entry_value| {
let mutation = match entry_value {
Some(entry_value) if *entry_value != value => Mutation::Update(value),
Some(_) => Mutation::Null,
None => Mutation::Insert(key, value),
};
(mutation, ())
},
ctx,
)
.0
}
pub fn inserted_conservative(&self, key: K, value: V) -> Option<IdMap<K, V>> {
self.inserted_conservative_in(key, value, &mut ())
}
pub fn insert_conservative_in<C: ConsCtx<K, V>>(
&mut self,
key: K,
value: V,
ctx: &mut C,
) -> bool {
if let Some(inserted_conservative) = self.inserted_conservative_in(key, value, ctx) {
*self = inserted_conservative;
true
} else {
false
}
}
pub fn insert_conservative(&mut self, key: K, value: V) -> bool {
if let Some(inserted_conservative) = self.inserted_conservative(key, value) {
*self = inserted_conservative;
true
} else {
false
}
}
pub fn is_submap(&self, other: &IdMap<K, V>, cons: bool) -> bool {
match (&self.0, &other.0) {
(Some(this), Some(other)) => {
if Arc::ptr_eq(this, other) {
true
} else if cons && this.len() == other.len() {
false
} else {
this.is_submap(other, cons)
}
}
(Some(_), None) => false,
(None, Some(_)) => true,
(None, None) => true,
}
}
pub fn domain_is_subset<U: Clone + Eq>(&self, other: &IdMap<K, U>) -> bool {
match (&self.0, &other.0) {
(Some(this), Some(other)) => this.domain_is_subset(other),
(Some(_), None) => false,
(None, Some(_)) => true,
(None, None) => true,
}
}
pub fn domains_intersect<U: Clone + Eq>(&self, other: &IdMap<K, U>) -> bool {
match (&self.0, &other.0) {
(Some(this), Some(other)) => this.domains_intersect(other),
_ => false,
}
}
pub fn domains_disjoint<U: Clone + Eq>(&self, other: &IdMap<K, U>) -> bool {
!self.domains_intersect(other)
}
pub fn map_cmp(&self, other: &IdMap<K, V>, cons: bool) -> Option<Ordering> {
use Ordering::*;
match self.len().cmp(&other.len()) {
Less if self.is_submap(other, cons) => Some(Less),
Equal if !cons && self == other => Some(Equal),
Equal if cons && self.ptr_eq(other) => Some(Equal),
Greater if other.is_submap(self, cons) => Some(Greater),
_ => None,
}
}
pub fn domain_cmp(&self, other: &IdMap<K, V>) -> Option<Ordering> {
use Ordering::*;
match self.len().cmp(&other.len()) {
Greater if other.domain_is_subset(self) => Some(Greater),
ord if self.domain_is_subset(other) => Some(ord),
_ => None,
}
}
}
pub trait ConsCtx<K: RadixKey, V: Clone> {
fn cons_arc(&mut self, inner: &Arc<InnerMap<K, V>>) -> Arc<InnerMap<K, V>>;
fn cons(&mut self, inner: InnerMap<K, V>) -> Arc<InnerMap<K, V>>;
fn cons_recursive(&mut self, inner: &Arc<InnerMap<K, V>>) -> Arc<InnerMap<K, V>> {
self.cons_arc(inner)
}
}
pub trait RadixKey: Eq + Clone {
type PatternType: Pattern<Self::DepthType>;
type DepthType: PrimInt + Hash + AsPrimitive<usize>;
fn pattern(&self, depth: Self::DepthType) -> Self::PatternType;
fn pattern_no(depth: Self::DepthType) -> usize {
let depth: usize = depth.as_();
depth / Self::PatternType::MAX_BITS
}
}
pub trait Pattern<D>: Eq + Hash + Copy + Clone + Default {
const MAX_BITS: usize;
fn max_bits() -> D;
fn byte(self, n: D) -> u8;
fn diff(self, other: Self) -> D;
}
#[cfg(test)]
mod test {
use super::*;
use map_ctx::*;
fn ordered_map_construction_in_ctx<C: ConsCtx<u64, u64>>(
n: u64,
ctx: &mut C,
) -> IdMap<u64, u64> {
let mut x = IdMap::new();
let mut v = Vec::with_capacity(n as usize);
for i in 0..n {
assert_eq!(
x.get(&i),
None,
"{} has not already been inserted into {:#?}",
i,
x
);
assert!(
x.try_insert_in(i, 2 * i, ctx),
"{} has not already been inserted into {:#?}",
i,
x
);
assert_eq!(
x.get(&i),
Some(&(2 * i)),
"{} has already been inserted into {:#?}",
i,
x
);
assert!(
!x.try_insert_in(i, 3 * i, ctx),
"{} has already had a value set in {:#?}",
i,
x
);
assert_eq!(
x.get(&i),
Some(&(2 * i)),
"{} has already been inserted into {:#?}",
i,
x
);
assert!(
x.insert_conservative_in(i, 3 * i, ctx) || i == 0,
"{} can be inserted_conservative in {:#?}",
i,
x
);
assert_eq!(
x.get(&i),
Some(&(3 * i)),
"{} has already been inserted into {:#?}",
i,
x
);
v.push((i, 3 * i));
}
let mut xv: Vec<_> = x.iter().map(|(k, v)| (*k, *v)).collect();
xv.sort_unstable();
assert_eq!(xv, v);
xv = x.clone().into_iter().collect();
xv.sort_unstable();
assert_eq!(xv, v);
x
}
#[test]
fn medium_map_construction() {
let x = ordered_map_construction_in_ctx(1000, &mut ());
let y = ordered_map_construction_in_ctx(1000, &mut ());
assert_ne!(x.as_ptr(), y.as_ptr());
assert_eq!(x, y);
}
#[test]
fn medium_map_construction_in_ctx() {
let mut ctx = MapCtx::new();
let x = ordered_map_construction_in_ctx(1000, &mut ctx);
let y = ordered_map_construction_in_ctx(1000, &mut ctx);
assert_eq!(x, y);
assert_eq!(x.as_ptr(), y.as_ptr());
}
#[test]
fn small_non_consed_map_set_ops() {
let mut x = IdMap::new();
x.try_insert(3, 6);
x.try_insert(5, 7);
x.try_insert(9, 2);
let mut y = IdMap::new();
y.try_insert(3, 5);
y.try_insert(2, 42);
y.try_insert(134, 23);
let z = match x.left_union(&y) {
BinaryResult::New(z) => z,
r => panic!("New map not returned, got result {:?}", r),
};
assert_eq!(z, x.left_unioned(&y));
assert_eq!(z.get(&2), Some(&42));
assert_eq!(z.get(&3), Some(&6));
assert_eq!(z.get(&4), None);
assert_eq!(z.get(&5), Some(&7));
assert_eq!(z.get(&134), Some(&23));
assert_eq!(z.len(), 5);
let w = match x.left_intersect(&y) {
BinaryResult::New(w) => w,
r => panic!("New map not returned, got result {:?}", r),
};
assert_eq!(w.get(&3), Some(&6));
assert_eq!(w.len(), 1);
}
#[test]
fn small_consed_set_ops() {
let mut ctx = MapCtx::new();
let mut x = IdMap::new();
x.try_insert_in(3, 6, &mut ctx);
x.try_insert_in(5, 7, &mut ctx);
x.try_insert_in(9, 2, &mut ctx);
let mut y = IdMap::new();
y.try_insert_in(3, 5, &mut ctx);
y.try_insert_in(2, 42, &mut ctx);
y.try_insert_in(134, 23, &mut ctx);
let z = match x.left_union_in(&y, &mut ctx) {
BinaryResult::New(z) => z,
r => panic!("New map not returned, got result {:?}", r),
};
assert_eq!(z.as_ptr(), x.left_unioned_in(&y, &mut ctx).as_ptr());
assert_eq!(z, x.left_unioned(&y));
assert_eq!(z.get(&2), Some(&42));
assert_eq!(z.get(&3), Some(&6));
assert_eq!(z.get(&4), None);
assert_eq!(z.get(&5), Some(&7));
assert_eq!(z.get(&134), Some(&23));
assert_eq!(z.len(), 5);
let w = match x.left_intersect_in(&y, &mut ctx) {
BinaryResult::New(w) => w,
r => panic!("New map not returned, got result {:?}", r),
};
assert_eq!(w.get(&3), Some(&6));
assert_eq!(w.len(), 1);
}
#[test]
fn mapping_set_op() {
let mut x = IdMap::new();
x.try_insert(3, 4);
x.try_insert(4, 2);
x.try_insert(6, 31);
x.try_insert(9, 2);
let mut y = IdMap::new();
y.try_insert(1, 24);
y.try_insert(3, 1);
y.try_insert(7, 2);
y.try_insert(8, 31);
y.try_insert(9, 3);
let j = x
.join_mutate_in(
&y,
&mut LeftMutator,
&mut FilterMap::new(|_key, value| {
if value % 2 == 0 {
Some(7 * value)
} else {
None
}
}),
&mut NullMutator,
&mut (),
)
.unwrap();
let mut jr = IdMap::new();
jr.try_insert(1, 24);
jr.try_insert(3, 4);
jr.try_insert(4, 2 * 7);
jr.try_insert(7, 2);
jr.try_insert(8, 31);
jr.try_insert(9, 2);
assert_eq!(j, jr);
}
#[test]
fn small_usize_insert() {
let mut map = IdMap::<usize, String>::new();
let ix = 3;
map.insert(ix, "Hello".to_string());
assert_eq!(map.get(&ix).unwrap(), "Hello");
eprintln!("Inner = {:#?}", map.0);
map.insert(ix, "Goodbye".to_string());
eprintln!("Inner = {:#?}", map.0);
assert_eq!(map.get(&ix).unwrap(), "Goodbye");
}
#[test]
fn big_usize_insert() {
let mut map = IdMap::<usize, String>::new();
let ix = 140220213234856;
map.insert(ix, "Hello".to_string());
assert_eq!(map.get(&ix).unwrap(), "Hello");
eprintln!("Inner = {:#?}", map.0);
map.insert(ix, "Goodbye".to_string());
eprintln!("Inner = {:#?}", map.0);
assert_eq!(map.get(&ix).unwrap(), "Goodbye");
}
}