Skip to content

Commit

Permalink
LinearMap: add LinearMapView, similar to VecView on top of #486
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Jul 1, 2024
1 parent 9abec11 commit aed9e74
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ mod deque;
mod histbuf;
mod indexmap;
mod indexset;
mod linear_map;
pub mod linear_map;
mod slice;
pub mod storage;
pub mod string;
Expand Down
61 changes: 48 additions & 13 deletions src/linear_map.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
//! A fixed capacity map/dictionary that performs lookups via linear search.
//!
//! Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).

use core::{borrow::Borrow, fmt, mem, ops, slice};

use crate::Vec;
use crate::{
storage::{OwnedStorage, Storage, ViewStorage},
vec::VecInner,
Vec,
};

/// Base struct for [`LinearMap`] and [`LinearMapView`]
pub struct LinearMapInner<K, V, S: Storage> {
pub(crate) buffer: VecInner<(K, V), S>,
}

/// A fixed capacity map/dictionary that performs lookups via linear search.
///
/// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).
pub type LinearMap<K, V, const N: usize> = LinearMapInner<K, V, OwnedStorage<N>>;

pub struct LinearMap<K, V, const N: usize> {
pub(crate) buffer: Vec<(K, V), N>,
}
/// A dynamic capacity map/dictionary that performs lookups via linear search.
///
/// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).
pub type LinearMapView<K, V> = LinearMapInner<K, V, ViewStorage>;

impl<K, V, const N: usize> LinearMap<K, V, N> {
/// Creates an empty `LinearMap`.
Expand All @@ -27,9 +42,19 @@ impl<K, V, const N: usize> LinearMap<K, V, N> {
pub const fn new() -> Self {
Self { buffer: Vec::new() }
}

/// Get a reference to the `LinearMap`, erasing the `N` const-generic.
pub fn as_view(&self) -> &LinearMapView<K, V> {
self
}

/// Get a mutable reference to the `LinearMap`, erasing the `N` const-generic.
pub fn as_mut_view(&mut self) -> &mut LinearMapView<K, V> {
self
}
}

impl<K, V, const N: usize> LinearMap<K, V, N>
impl<K, V, S: Storage> LinearMapInner<K, V, S>
where
K: Eq,
{
Expand All @@ -46,7 +71,7 @@ where
/// assert_eq!(map.capacity(), 8);
/// ```
pub fn capacity(&self) -> usize {
N
self.buffer.borrow().capacity()
}

/// Clears the map, removing all key-value pairs.
Expand Down Expand Up @@ -346,7 +371,7 @@ where
}
}

impl<'a, K, V, Q, const N: usize> ops::Index<&'a Q> for LinearMap<K, V, N>
impl<'a, K, V, Q, S: Storage> ops::Index<&'a Q> for LinearMapInner<K, V, S>
where
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
Expand All @@ -358,7 +383,7 @@ where
}
}

impl<'a, K, V, Q, const N: usize> ops::IndexMut<&'a Q> for LinearMap<K, V, N>
impl<'a, K, V, Q, S: Storage> ops::IndexMut<&'a Q> for LinearMapInner<K, V, S>
where
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
Expand Down Expand Up @@ -389,7 +414,7 @@ where
}
}

impl<K, V, const N: usize> fmt::Debug for LinearMap<K, V, N>
impl<K, V, S: Storage> fmt::Debug for LinearMapInner<K, V, S>
where
K: Eq + fmt::Debug,
V: fmt::Debug,
Expand All @@ -413,6 +438,9 @@ where
}
}

/// An iterator that moves out of a [`LinearMap`].
///
/// This struct is created by calling the [`into_iter`](LinearMap::into_iter) method on [`LinearMap`].
pub struct IntoIter<K, V, const N: usize>
where
K: Eq,
Expand Down Expand Up @@ -444,7 +472,7 @@ where
}
}

impl<'a, K, V, const N: usize> IntoIterator for &'a LinearMap<K, V, N>
impl<'a, K, V, S: Storage> IntoIterator for &'a LinearMapInner<K, V, S>
where
K: Eq,
{
Expand All @@ -456,6 +484,9 @@ where
}
}

/// An iterator over the items of a [`LinearMap`]
///
/// This struct is created by calling the [`iter`](LinearMap::iter) method on [`LinearMap`].
#[derive(Clone, Debug)]
pub struct Iter<'a, K, V> {
iter: slice::Iter<'a, (K, V)>,
Expand All @@ -472,6 +503,9 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
}
}

/// An iterator over the items of a [`LinearMap`] that allows modifying the items
///
/// This struct is created by calling the [`iter_mut`](LinearMap::iter_mut) method on [`LinearMap`].
#[derive(Debug)]
pub struct IterMut<'a, K, V> {
iter: slice::IterMut<'a, (K, V)>,
Expand All @@ -485,20 +519,21 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
}
}

impl<K, V, const N: usize, const N2: usize> PartialEq<LinearMap<K, V, N2>> for LinearMap<K, V, N>
impl<K, V, S1: Storage, S2: Storage> PartialEq<LinearMapInner<K, V, S2>>
for LinearMapInner<K, V, S1>
where
K: Eq,
V: PartialEq,
{
fn eq(&self, other: &LinearMap<K, V, N2>) -> bool {
fn eq(&self, other: &LinearMapInner<K, V, S2>) -> bool {
self.len() == other.len()
&& self
.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
}
}

impl<K, V, const N: usize> Eq for LinearMap<K, V, N>
impl<K, V, S: Storage> Eq for LinearMapInner<K, V, S>
where
K: Eq,
V: PartialEq,
Expand Down

0 comments on commit aed9e74

Please sign in to comment.