use core::{borrow::Borrow, fmt};
use smallvec::SmallVec;
pub struct SmallOrdSet<T, const N: usize> {
items: SmallVec<[T; N]>,
}
impl<T, const N: usize> Default for SmallOrdSet<T, N> {
fn default() -> Self {
Self {
items: Default::default(),
}
}
}
impl<T, const N: usize> Eq for SmallOrdSet<T, N> where T: Eq {}
impl<T, const N: usize> PartialEq for SmallOrdSet<T, N>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.items.eq(&other.items)
}
}
impl<T, const N: usize> fmt::Debug for SmallOrdSet<T, N>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_set().entries(self.items.iter()).finish()
}
}
impl<T, const N: usize> Clone for SmallOrdSet<T, N>
where
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
items: self.items.clone(),
}
}
}
impl<T, const N: usize> SmallOrdSet<T, N>
where
T: Ord,
{
pub fn from_vec(items: SmallVec<[T; N]>) -> Self {
let mut set = Self { items };
set.sort_and_dedup();
set
}
#[inline]
pub fn from_buf(buf: [T; N]) -> Self {
Self::from_vec(buf.into())
}
}
impl<T, const N: usize> IntoIterator for SmallOrdSet<T, N> {
type IntoIter = smallvec::IntoIter<[T; N]>;
type Item = T;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<T, const N: usize> FromIterator<T> for SmallOrdSet<T, N>
where
T: Ord,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
let mut set = Self::default();
for item in iter {
set.insert(item);
}
set
}
}
impl<T, const N: usize> SmallOrdSet<T, N>
where
T: Ord,
{
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn as_slice(&self) -> &[T] {
self.items.as_slice()
}
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.items.iter()
}
pub fn insert(&mut self, item: T) -> bool {
match self.find(&item) {
Ok(_) => false,
Err(idx) => {
self.items.insert(idx, item);
true
}
}
}
pub fn remove<Q>(&mut self, item: &Q) -> Option<T>
where
T: Borrow<Q>,
Q: Ord + ?Sized,
{
match self.find(item) {
Ok(idx) => Some(self.items.remove(idx)),
Err(_) => None,
}
}
pub fn clear(&mut self) {
self.items.clear();
}
pub fn contains<Q>(&self, item: &Q) -> bool
where
T: Borrow<Q>,
Q: Ord + ?Sized,
{
self.find(item).is_ok()
}
pub fn get<Q>(&self, item: &Q) -> Option<&T>
where
T: Borrow<Q>,
Q: Ord + ?Sized,
{
match self.find(item) {
Ok(idx) => Some(&self.items[idx]),
Err(_) => None,
}
}
pub fn get_mut<Q>(&mut self, item: &Q) -> Option<&mut T>
where
T: Borrow<Q>,
Q: Ord + ?Sized,
{
match self.find(item) {
Ok(idx) => Some(&mut self.items[idx]),
Err(_) => None,
}
}
#[inline]
fn find<Q>(&self, item: &Q) -> Result<usize, usize>
where
T: Borrow<Q>,
Q: Ord + ?Sized,
{
self.items.binary_search_by(|probe| Ord::cmp(probe.borrow(), item))
}
fn sort_and_dedup(&mut self) {
self.items.sort_unstable();
self.items.dedup();
}
}