#![feature(min_const_generics)]
#![feature(const_in_array_repeat_expressions)]
#![warn(clippy::pedantic)]
#![allow(clippy::redundant_pattern_matching)]
#![no_std]
use core::{cmp::Ordering, fmt, iter, mem};
use tinyvec::{ArrayVec, ArrayVecIterator};
struct Node<K, V> {
kv: (K, V),
children: [Option<usize>; 2],
}
impl<K: Clone, V: Clone> Clone for Node<K, V> {
#[inline]
fn clone(&self) -> Self {
Node {
kv: self.kv.clone(),
children: self.children,
}
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Node<K, V> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.kv, f)
}
}
pub struct TinyMap<K: PartialOrd, V, const N: usize> {
arena: ArrayVec<[Option<Node<K, V>>; N]>,
root: Option<usize>,
}
macro_rules! unwrap_tpn {
($self: expr, $e: expr) => {{
match $self.try_push_node($e) {
Ok(u) => Some(u),
Err(n) => {
let Node { kv, .. } = n;
return Err(kv);
}
}
}};
}
enum ChildType {
Left,
Right,
}
impl<K: PartialOrd, V, const N: usize> TinyMap<K, V, N> {
#[must_use]
#[inline]
pub fn new() -> Self {
Self {
arena: ArrayVec::from_array_len([None; N], 0),
root: None,
}
}
pub fn len(&self) -> usize {
self.arena
.iter()
.filter(|n| match n {
Some(_) => true,
None => false,
})
.count()
}
pub fn is_empty(&self) -> bool {
match self.root {
Some(_) => false,
None => true,
}
}
#[must_use]
#[inline]
fn node_at(&self, index: usize) -> Option<&Node<K, V>> {
self.arena[index].as_ref()
}
#[must_use]
#[inline]
fn node_at_mut(&mut self, index: usize) -> Option<&mut Node<K, V>> {
self.arena[index].as_mut()
}
#[must_use]
#[inline]
fn root(&self) -> Option<usize> {
self.root
}
#[must_use]
#[inline]
fn node_by_key(&self, key: &K) -> Option<&Node<K, V>> {
let mut current = self.root();
loop {
match current {
None => return None,
Some(val) => {
let node = self.node_at(val).expect("Invalid node tree");
current = match node.kv.0.partial_cmp(key) {
None => return None,
Some(Ordering::Equal) => return Some(node),
Some(Ordering::Less) => node.children[0],
Some(Ordering::Greater) => node.children[1],
};
}
}
}
}
#[must_use]
#[inline]
fn node_by_key_mut(&mut self, key: &K) -> Option<&mut Node<K, V>> {
let mut current = self.root();
loop {
match current {
None => return None,
Some(val) => {
let node = self.node_at(val).expect("Invalid node tree");
current = match node.kv.0.partial_cmp(key) {
None => return None,
Some(Ordering::Equal) => {
return Some(self.node_at_mut(val).expect("Invalid node tree"));
}
Some(Ordering::Less) => node.children[0],
Some(Ordering::Greater) => node.children[1],
};
}
}
}
}
#[must_use]
#[inline]
pub fn get(&self, key: &K) -> Option<&V> {
match self.node_by_key(key) {
Some(node) => Some(&node.kv.1),
None => None,
}
}
#[must_use]
#[inline]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
match self.node_by_key_mut(key) {
Some(node) => Some(&mut node.kv.1),
None => None,
}
}
#[must_use]
#[inline]
pub fn contains_key(&self, key: &K) -> bool {
match self.node_by_key(key) {
Some(_) => true,
None => false,
}
}
#[inline]
fn try_push_node(&mut self, node: Node<K, V>) -> Result<usize, Node<K, V>> {
match self.arena.try_push(Some(node)) {
Some(mut node) => {
let pos = self.arena.iter().position(Option::is_none);
match pos {
Some(pos) => {
mem::swap(&mut self.arena[pos], &mut node);
Ok(pos)
}
None => Err(node.unwrap()),
}
}
None => Ok(self.arena.len() - 1),
}
}
#[inline]
fn insert_from_root(
&mut self,
mut node: Node<K, V>,
mut current: usize,
) -> Result<Option<V>, (K, V)>
where
K: Ord,
{
let mut next;
loop {
let cmp_node = self.node_at(current).unwrap();
let ct = match cmp_node.kv.0.cmp(&node.kv.0) {
Ordering::Less => {
next = cmp_node.children[0];
ChildType::Left
}
Ordering::Greater => {
next = cmp_node.children[1];
ChildType::Right
}
Ordering::Equal => {
mem::swap(&mut self.node_at_mut(current).unwrap().kv.1, &mut node.kv.1);
return Ok(Some(node.kv.1));
}
};
match next {
None => {
let index = unwrap_tpn!(self, node);
let cmp_node_mut = self.node_at_mut(current).unwrap();
let slot = match ct {
ChildType::Left => &mut cmp_node_mut.children[0],
ChildType::Right => &mut cmp_node_mut.children[1],
};
*slot = index;
return Ok(None);
}
Some(next) => {
current = next;
}
}
}
}
#[inline]
pub fn try_insert(&mut self, key: K, value: V) -> Result<Option<V>, (K, V)>
where
K: Ord,
{
let node = Node {
kv: (key, value),
children: [None; 2],
};
match self.root {
None => {
self.root = unwrap_tpn!(self, node);
Ok(None)
}
Some(root) => self.insert_from_root(node, root),
}
}
#[inline]
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: Ord,
{
match self.try_insert(key, value) {
Err(_) => panic!("Unable to push node into binary tree"),
Ok(res) => res,
}
}
#[inline]
pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)>
where
K: Ord,
{
const ERR_MSG: &str = "Invalid binary tree path";
enum ParentChildRelation {
ChildIsRoot,
Left,
Right,
}
let mut parent_index: Option<usize> = None;
let mut last_relationship = ParentChildRelation::ChildIsRoot;
let mut current: Option<usize> = self.root;
loop {
let c = match current {
Some(c) => c,
None => return None,
};
let cmp_node = self.node_at(c).expect(ERR_MSG);
match cmp_node.kv.0.partial_cmp(key) {
None => return None,
Some(Ordering::Equal) => {
let mut replacement_node = match cmp_node.children {
[None, None] => None,
[Some(child), None] | [None, Some(child)] => Some(child),
[Some(child1), Some(child2)] => {
let mut reloc_node = None;
mem::swap(&mut reloc_node, &mut self.arena[child2]);
if let Err(_) = self.insert_from_root(reloc_node.unwrap(), child1) {
panic!("This should not happen!");
}
Some(child1)
}
};
let slot = match (last_relationship, parent_index) {
(ParentChildRelation::ChildIsRoot, _) => &mut self.root,
(ParentChildRelation::Left, Some(p)) => {
&mut self.node_at_mut(p).expect(ERR_MSG).children[0]
}
(ParentChildRelation::Right, Some(p)) => {
&mut self.node_at_mut(p).expect(ERR_MSG).children[1]
}
_ => unreachable!(),
};
mem::swap(slot, &mut replacement_node);
let n = self.arena[replacement_node.unwrap()].take();
return Some(n.unwrap().kv);
}
Some(Ordering::Less) => {
parent_index = current;
current = cmp_node.children[0];
last_relationship = ParentChildRelation::Left;
}
Some(Ordering::Greater) => {
parent_index = current;
current = cmp_node.children[1];
last_relationship = ParentChildRelation::Right;
}
}
}
}
#[inline]
pub fn remove(&mut self, key: &K) -> Option<V>
where
K: Ord,
{
match self.remove_entry(key) {
Some((_k, v)) => Some(v),
None => None,
}
}
#[inline]
pub fn clear(&mut self) {
self.arena.clear();
self.root = None;
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.arena.iter().filter_map(|node| match node.as_ref() {
None => None,
Some(Node {
kv: (ref k, ref v), ..
}) => Some((k, v)),
})
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
self.arena
.iter_mut()
.filter_map(|node| match node.as_mut() {
None => None,
Some(Node {
kv: (ref k, ref mut v),
..
}) => Some((k, v)),
})
}
#[inline]
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.arena.iter().filter_map(|node| match node.as_ref() {
None => None,
Some(Node { kv: (ref k, _), .. }) => Some(k),
})
}
#[inline]
pub fn values(&self) -> impl Iterator<Item = &V> {
self.arena.iter().filter_map(|node| match node.as_ref() {
None => None,
Some(Node { kv: (_, ref v), .. }) => Some(v),
})
}
#[inline]
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.arena
.iter_mut()
.filter_map(|node| match node.as_mut() {
None => None,
Some(Node {
kv: (_, ref mut v), ..
}) => Some(v),
})
}
}
#[repr(transparent)]
pub struct TinyMapIterator<K, V, const N: usize> {
inner: ArrayVecIterator<[Option<Node<K, V>>; N]>,
}
impl<K, V, const N: usize> Iterator for TinyMapIterator<K, V, N> {
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.find_map(|node| match node {
None => None,
Some(node) => Some(node.kv),
})
}
#[inline]
#[must_use]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.inner.size_hint().1)
}
}
impl<K: PartialOrd, V, const N: usize> Default for TinyMap<K, V, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<K: PartialOrd + Clone, V: Clone, const N: usize> Clone for TinyMap<K, V, N> {
#[inline]
fn clone(&self) -> Self {
TinyMap {
arena: self.arena.clone(),
root: self.root,
}
}
}
impl<K: PartialOrd + fmt::Debug, V: fmt::Debug, const N: usize> fmt::Debug for TinyMap<K, V, N> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.arena, f)
}
}
impl<K: PartialOrd, V, const N: usize> iter::IntoIterator for TinyMap<K, V, N> {
type Item = (K, V);
type IntoIter = TinyMapIterator<K, V, N>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
TinyMapIterator {
inner: self.arena.into_iter(),
}
}
}
impl<K: Ord, V, const N: usize> iter::Extend<(K, V)> for TinyMap<K, V, N> {
#[inline]
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
iter.into_iter().for_each(|(k, v)| {
self.insert(k, v);
});
}
}
impl<K: Ord, V, const N: usize> iter::FromIterator<(K, V)> for TinyMap<K, V, N> {
#[inline]
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut map = TinyMap::new();
map.extend(iter);
map
}
}
#[test]
fn test_remove() {
let mut map: TinyMap<u32, u32, 25> = TinyMap::new();
for i in 0..25 {
map.insert(i, i);
}
for j in 10..15 {
map.remove(&j);
}
let _test = map.get(&16).unwrap();
}