#![no_std]
use core::ops::Range;
extern crate alloc;
use alloc::vec::Vec;
mod mut_ref_guard;
mod order;
mod slice_guard;
mod trait_impls;
pub use {
mut_ref_guard::MutRefGuard,
order::{FullOrd, Order},
slice_guard::SliceGuard,
};
#[cfg(test)]
mod tests;
#[derive(Clone, Hash)]
pub struct OrdBySet<T, Orderer = FullOrd>
where
Orderer: Order<T>,
{
storage: Vec<T>,
orderer: Orderer,
}
impl<T, Orderer: Order<T> + Default> OrdBySet<T, Orderer> {
pub fn new() -> Self {
Self::default()
}
}
impl<T: Ord> OrdBySet<T, FullOrd> {
pub fn fully_ordered() -> Self {
Self::new()
}
}
impl<T, Orderer: Order<T>> OrdBySet<T, Orderer> {
pub fn new_with_order(orderer: Orderer) -> Self {
Self {
storage: Vec::new(),
orderer,
}
}
pub fn insert(&mut self, item: T) {
let insertion_point = self
.storage
.binary_search_by(|x| self.orderer.order_of(&x, &item))
.unwrap_or_else(|insert_at| insert_at);
self.storage.insert(insertion_point, item);
}
fn get_index_range_of(&self, item: &T) -> Option<Range<usize>> {
let start = self
.storage
.partition_point(|probe| self.orderer.order_of(&probe, &item).is_lt());
let len = self.storage[start..]
.partition_point(|probe| self.orderer.order_of(&probe, &item).is_eq());
let end = start + len;
(end > start).then(|| start..end)
}
pub fn remove_all(&mut self, item: &T) -> bool {
if let Some(range) = self.get_index_range_of(item) {
drop(self.storage.drain(range));
true
} else {
false
}
}
pub fn remove_first(&mut self, item: &T) -> Option<T> {
let location_range = self.get_index_range_of(item)?;
let contains_item = !location_range.is_empty();
contains_item.then(|| self.storage.remove(location_range.start))
}
pub fn drain(&mut self, item: &T) -> Vec<T> {
self.get_index_range_of(item)
.map(|range| self.storage.drain(range).collect())
.unwrap_or_default()
}
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&T) -> bool,
{
self.storage.retain(f)
}
pub fn get(&self, item: &T) -> Option<&[T]> {
Some(&self.storage[self.get_index_range_of(item)?])
}
pub fn get_first(&self, item: &T) -> Option<&T> {
let index = self
.storage
.binary_search_by(|x| self.orderer.order_of(&x, item))
.ok()?;
self.storage.get(index)
}
pub fn get_mut(&mut self, item: &T) -> Option<SliceGuard<'_, T, Orderer>> {
let range = self.get_index_range_of(item)?;
Some(SliceGuard(self, range))
}
pub fn get_first_mut(&mut self, item: &T) -> Option<MutRefGuard<'_, T, Orderer>> {
let index = self
.storage
.binary_search_by(|x| self.orderer.order_of(&x, item))
.ok()?;
Some(MutRefGuard(self, index))
}
pub fn contains(&self, item: &T) -> bool {
self.storage
.binary_search_by(|x| self.orderer.order_of(&x, item))
.is_ok()
}
pub fn count(&self, item: &T) -> usize {
self.get_index_range_of(item)
.map(|range| range.len())
.unwrap_or(0)
}
pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
self.storage.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> + '_ {
self.storage.iter_mut()
}
pub fn with_items<Items: Into<Vec<T>>>(self, items: Items) -> Self {
let mut storage = items.into();
self.orderer.sort_slice(&mut storage);
Self { storage, ..self }
}
pub fn len(&self) -> usize {
self.storage.len()
}
pub fn capacity(&self) -> usize {
self.storage.capacity()
}
pub fn clear(&mut self) {
self.storage.truncate(0);
}
pub fn is_empty(&self) -> bool {
self.storage.is_empty()
}
fn range_to_index_range(&self, low: &T, high: &T) -> Option<Range<usize>> {
if !self.orderer.order_of(low, high).is_lt() {
return None;
}
let start = self
.storage
.partition_point(|probe| self.orderer.order_of(probe, low).is_lt());
let len = self.storage[start..]
.partition_point(|probe| self.orderer.order_of(probe, high).is_le());
let end = start + len;
(end > start).then(|| start..end)
}
pub fn range(&self, low: &T, high: &T) -> Option<&[T]> {
self.range_to_index_range(low, high)
.map(|range| &self.storage[range])
}
pub fn range_mut(&mut self, low: &T, high: &T) -> Option<SliceGuard<'_, T, Orderer>> {
self.range_to_index_range(low, high)
.map(move |range| SliceGuard(self, range))
}
}
impl<T, Orderer: Order<T>> OrdBySet<T, Orderer>
where
T: PartialEq,
{
pub fn remove_specific(&mut self, val: &T) -> Option<T> {
let location_range = self.get_index_range_of(val)?;
let start = location_range.start;
let index = self.storage[location_range].iter().position(|x| x == val)? + start;
Some(self.storage.remove(index))
}
pub fn get_specific(&self, val: &T) -> Option<&T> {
let location_range = self.get_index_range_of(val)?;
let start = location_range.start;
let index = self.storage[location_range].iter().position(|x| x == val)? + start;
self.storage.get(index)
}
pub fn get_specific_mut(&mut self, val: &T) -> Option<MutRefGuard<'_, T, Orderer>> {
let location_range = self.get_index_range_of(val)?;
let start = location_range.start;
let index = self.storage[location_range].iter().position(|x| x == val)? + start;
Some(MutRefGuard(self, index))
}
pub fn contains_specific(&self, val: &T) -> bool {
if let Some(location_range) = self.get_index_range_of(val) {
self.storage[location_range].iter().any(|x| x == val)
} else {
false
}
}
}