use std::{cmp::Ordering, mem};
use awint::awint_dag::smallvec::{smallvec, SmallVec};
pub fn binary_search_similar_by<T, F: FnMut(&T) -> Ordering>(
slice: &[T],
mut f: F,
) -> (usize, Ordering) {
if slice.is_empty() {
return (0, Ordering::Less)
}
let mut size = slice.len();
let mut left = 0;
let mut right = size;
while left < right {
let mid = left + (size / 2);
let cmp = f(&slice[mid]);
left = if cmp == Ordering::Less { mid + 1 } else { left };
right = if cmp == Ordering::Greater { mid } else { right };
if cmp == Ordering::Equal {
return (mid, Ordering::Equal);
}
size = right - left;
}
if left == slice.len() {
(slice.len() - 1, Ordering::Greater)
} else {
(left, f(&slice[left]).reverse())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SmallMap<K, V> {
set: SmallVec<[(K, V); 8]>,
}
impl<K, V> SmallMap<K, V> {
pub fn new() -> Self {
Self { set: smallvec![] }
}
pub fn len(&self) -> usize {
self.set.len()
}
pub fn is_empty(&self) -> bool {
self.set.is_empty()
}
}
impl<K: Ord, V> SmallMap<K, V> {
pub fn insert(&mut self, k: K, v: V) -> Result<(), V> {
let (i, direction) = binary_search_similar_by(&self.set, |(k_prime, _)| k_prime.cmp(&k));
match direction {
Ordering::Less => {
self.set.insert(i, (k, v));
}
Ordering::Equal => return Err(mem::replace(&mut self.set[i].1, v)),
Ordering::Greater => {
self.set.insert(i + 1, (k, v));
}
}
Ok(())
}
#[must_use]
pub fn contains(&mut self, k: &K) -> bool {
binary_search_similar_by(&self.set, |(k_prime, _)| k_prime.cmp(k)).1 == Ordering::Equal
}
#[must_use]
pub fn get(&mut self, k: &K) -> Option<&V> {
let (i, direction) = binary_search_similar_by(&self.set, |(k_prime, _)| k_prime.cmp(k));
match direction {
Ordering::Equal => Some(&self.set.get(i).unwrap().1),
_ => None,
}
}
#[must_use]
pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
let (i, direction) = binary_search_similar_by(&self.set, |(k_prime, _)| k_prime.cmp(k));
match direction {
Ordering::Equal => Some(&mut self.set.get_mut(i).unwrap().1),
_ => None,
}
}
#[must_use]
pub fn remove(&mut self, k: &K) -> Option<V> {
let (i, direction) = binary_search_similar_by(&self.set, |(k_prime, _)| k_prime.cmp(k));
match direction {
Ordering::Equal => Some(self.set.remove(i).1),
_ => None,
}
}
}
impl<K, V> Default for SmallMap<K, V> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SmallSet<K> {
small_map: SmallMap<K, ()>,
}
impl<K> SmallSet<K> {
pub fn new() -> Self {
Self {
small_map: SmallMap::new(),
}
}
pub fn len(&self) -> usize {
self.small_map.len()
}
pub fn is_empty(&self) -> bool {
self.small_map.is_empty()
}
}
impl<K: Ord> SmallSet<K> {
pub fn insert(&mut self, k: K) -> bool {
self.small_map.insert(k, ()).is_ok()
}
#[must_use]
pub fn contains(&mut self, k: &K) -> bool {
self.small_map.contains(k)
}
#[must_use]
pub fn remove(&mut self, k: &K) -> Option<()> {
self.small_map.remove(k)
}
}
impl<K> Default for SmallSet<K> {
fn default() -> Self {
Self::new()
}
}