use std::fmt;
use std::iter::FusedIterator;
use fnv::FnvBuildHasher;
use indexmap::IndexMap;
use super::TraverserValue;
use crate::graph::GraphStorage;
pub(crate) type StreamMapInner<S> = IndexMap<TraverserValue<S>, TraverserValue<S>, FnvBuildHasher>;
#[repr(transparent)]
pub struct StreamMap<S: GraphStorage>(pub(crate) StreamMapInner<S>);
impl<S: GraphStorage> Clone for StreamMap<S> {
#[inline(always)]
fn clone(&self) -> Self {
Self(self.0.clone())
}
#[inline(always)]
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0);
}
}
impl<S: GraphStorage> PartialEq for StreamMap<S> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<S: GraphStorage> Eq for StreamMap<S> {}
impl<S: GraphStorage> Default for StreamMap<S> {
#[inline]
fn default() -> Self {
Self(StreamMapInner::default())
}
}
impl<S: GraphStorage> StreamMap<S> {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self(StreamMapInner::with_capacity_and_hasher(
capacity,
FnvBuildHasher::default(),
))
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn get(&self, key: &TraverserValue<S>) -> Option<&TraverserValue<S>> {
self.0.get(key)
}
#[inline]
pub fn get_mut(&mut self, key: &TraverserValue<S>) -> Option<&mut TraverserValue<S>> {
self.0.get_mut(key)
}
#[inline]
pub fn contains_key(&self, key: &TraverserValue<S>) -> bool {
self.0.contains_key(key)
}
#[inline]
pub fn insert(
&mut self,
key: TraverserValue<S>,
value: TraverserValue<S>,
) -> Option<TraverserValue<S>> {
self.0.insert(key, value)
}
#[inline]
pub fn shift_remove(&mut self, key: &TraverserValue<S>) -> Option<TraverserValue<S>> {
self.0.shift_remove(key)
}
#[inline]
pub fn iter(&self) -> Iter<'_, S> {
Iter(self.0.iter())
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, S> {
IterMut(self.0.iter_mut())
}
#[inline]
pub fn keys(&self) -> Keys<'_, S> {
Keys(self.0.keys())
}
#[inline]
pub fn values(&self) -> Values<'_, S> {
Values(self.0.values())
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, S> {
ValuesMut(self.0.values_mut())
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
}
impl<S: GraphStorage> fmt::Debug for StreamMap<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<S: GraphStorage> FromIterator<(TraverserValue<S>, TraverserValue<S>)> for StreamMap<S> {
#[inline]
fn from_iter<I: IntoIterator<Item = (TraverserValue<S>, TraverserValue<S>)>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<S: GraphStorage> Extend<(TraverserValue<S>, TraverserValue<S>)> for StreamMap<S> {
#[inline]
fn extend<I: IntoIterator<Item = (TraverserValue<S>, TraverserValue<S>)>>(&mut self, iter: I) {
self.0.extend(iter);
}
}
impl<S: GraphStorage, const N: usize> From<[(TraverserValue<S>, TraverserValue<S>); N]>
for StreamMap<S>
{
#[inline]
fn from(entries: [(TraverserValue<S>, TraverserValue<S>); N]) -> Self {
entries.into_iter().collect()
}
}
impl<S: GraphStorage> IntoIterator for StreamMap<S> {
type Item = (TraverserValue<S>, TraverserValue<S>);
type IntoIter = IntoIter<S>;
#[inline]
fn into_iter(self) -> IntoIter<S> {
IntoIter(self.0.into_iter())
}
}
impl<'a, S: GraphStorage> IntoIterator for &'a StreamMap<S> {
type Item = (&'a TraverserValue<S>, &'a TraverserValue<S>);
type IntoIter = Iter<'a, S>;
#[inline]
fn into_iter(self) -> Iter<'a, S> {
self.iter()
}
}
impl<'a, S: GraphStorage> IntoIterator for &'a mut StreamMap<S> {
type Item = (&'a TraverserValue<S>, &'a mut TraverserValue<S>);
type IntoIter = IterMut<'a, S>;
#[inline]
fn into_iter(self) -> IterMut<'a, S> {
self.iter_mut()
}
}
macro_rules! wrap_iter {
($name:ident<$($lt:lifetime,)? S>, $item:ty) => {
impl<$($lt,)? S: GraphStorage> Iterator for $name<$($lt,)? S> {
type Item = $item;
#[inline]
fn next(&mut self) -> Option<$item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<$($lt,)? S: GraphStorage> DoubleEndedIterator for $name<$($lt,)? S> {
#[inline]
fn next_back(&mut self) -> Option<$item> {
self.0.next_back()
}
}
impl<$($lt,)? S: GraphStorage> ExactSizeIterator for $name<$($lt,)? S> {}
impl<$($lt,)? S: GraphStorage> FusedIterator for $name<$($lt,)? S> {}
impl<$($lt,)? S: GraphStorage> fmt::Debug for $name<$($lt,)? S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(stringify!($name))
.field("remaining", &self.0.len())
.finish()
}
}
};
}
pub struct Iter<'a, S: GraphStorage>(indexmap::map::Iter<'a, TraverserValue<S>, TraverserValue<S>>);
wrap_iter!(Iter<'a, S>, (&'a TraverserValue<S>, &'a TraverserValue<S>));
impl<S: GraphStorage> Clone for Iter<'_, S> {
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
pub struct IterMut<'a, S: GraphStorage>(
indexmap::map::IterMut<'a, TraverserValue<S>, TraverserValue<S>>,
);
wrap_iter!(
IterMut<'a, S>,
(&'a TraverserValue<S>, &'a mut TraverserValue<S>)
);
pub struct Keys<'a, S: GraphStorage>(indexmap::map::Keys<'a, TraverserValue<S>, TraverserValue<S>>);
wrap_iter!(Keys<'a, S>, &'a TraverserValue<S>);
impl<S: GraphStorage> Clone for Keys<'_, S> {
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
pub struct Values<'a, S: GraphStorage>(
indexmap::map::Values<'a, TraverserValue<S>, TraverserValue<S>>,
);
wrap_iter!(Values<'a, S>, &'a TraverserValue<S>);
impl<S: GraphStorage> Clone for Values<'_, S> {
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
pub struct ValuesMut<'a, S: GraphStorage>(
indexmap::map::ValuesMut<'a, TraverserValue<S>, TraverserValue<S>>,
);
wrap_iter!(ValuesMut<'a, S>, &'a mut TraverserValue<S>);
pub struct IntoIter<S: GraphStorage>(indexmap::map::IntoIter<TraverserValue<S>, TraverserValue<S>>);
wrap_iter!(IntoIter<S>, (TraverserValue<S>, TraverserValue<S>));
#[cfg(test)]
mod tests {
use super::{StreamMap, StreamMapInner};
use crate::graph::TraversalGraph;
use crate::value::{ElementProperty, TraverserValue};
type V = TraverserValue<TraversalGraph>;
fn n(i: i64) -> V {
V::from(ElementProperty::from(i))
}
#[test]
fn the_newtype_costs_nothing() {
assert_eq!(
size_of::<StreamMap<TraversalGraph>>(),
size_of::<StreamMapInner<TraversalGraph>>()
);
assert_eq!(
align_of::<StreamMap<TraversalGraph>>(),
align_of::<StreamMapInner<TraversalGraph>>()
);
assert_eq!(size_of::<V>(), 64);
}
#[test]
fn keeps_insertion_order_and_compares_unordered() {
let mut a: StreamMap<TraversalGraph> = StreamMap::with_capacity(2);
a.insert(V::from("b"), n(1));
a.insert(V::from("a"), n(2));
a.insert(V::from("b"), n(3));
assert_eq!(
a.keys().cloned().collect::<Vec<_>>(),
[V::from("b"), V::from("a")]
);
assert_eq!(a.get(&V::from("b")), Some(&n(3)));
let b: StreamMap<TraversalGraph> =
StreamMap::from([(V::from("a"), n(2)), (V::from("b"), n(3))]);
assert_eq!(a, b);
assert_eq!(a.shift_remove(&V::from("b")), Some(n(3)));
assert!(!a.contains_key(&V::from("b")));
a.extend([(V::from("c"), n(4))]);
for value in a.values_mut() {
*value = n(0);
}
if let Some(v) = a.get_mut(&V::from("c")) {
*v = n(5);
}
assert_eq!(a.values().next_back(), Some(&n(5)));
let owned: Vec<_> = a.clone().into_iter().collect();
assert_eq!(owned.len(), 2);
assert_eq!((&a).into_iter().len(), 2);
assert_eq!(a.iter_mut().len(), 2);
a.clear();
assert!(a.is_empty());
assert!(StreamMap::<TraversalGraph>::new().is_empty());
}
}