use std::cmp::Ordering;
use std::borrow::Borrow;
use std::ops::{Deref, RangeBounds, Bound};
use std::{error, fmt, mem};
#[cfg(feature="serde")]
use serde::{Serialize, Deserialize};
use crate::{exponential_search, exponential_search_by, exponential_search_by_key};
#[cfg_attr(feature="serde", derive(Serialize))]
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Set<T>([T]);
impl<T> Set<T> {
#[inline]
pub fn new(slice: &[T]) -> Result<&Self, Error>
where T: Ord
{
is_sort_dedup(slice).map(|_| Self::new_unchecked(slice))
}
#[inline]
pub fn new_unchecked(slice: &[T]) -> &Self {
unsafe { mem::transmute(slice) }
}
#[inline]
pub fn range<K, R>(&self, range: R) -> &Self
where K: Ord + ?Sized,
R: RangeBounds<K>,
T: Borrow<K>,
{
let left = match range.start_bound() {
Bound::Included(x) => match self.exponential_search_by(|e| e.borrow().cmp(x)) {
Ok(index) => index,
Err(index) => index,
},
Bound::Excluded(x) => match self.exponential_search_by(|e| e.borrow().cmp(x)) {
Ok(index) => index + 1,
Err(index) => index,
},
Bound::Unbounded => 0,
};
let right = match range.end_bound() {
Bound::Included(x) => match self.exponential_search_by(|e| e.borrow().cmp(x)) {
Ok(index) => index + 1,
Err(index) => index,
},
Bound::Excluded(x) => match self.exponential_search_by(|e| e.borrow().cmp(x)) {
Ok(index) => index,
Err(index) => index,
},
Bound::Unbounded => self.len(),
};
Self::new_unchecked(&self[left..right])
}
#[inline]
pub fn exponential_search(&self, elem: &T) -> Result<usize, usize>
where T: Ord,
{
exponential_search(self, elem)
}
#[inline]
pub fn exponential_search_by<F>(&self, f: F) -> Result<usize, usize>
where F: FnMut(&T) -> Ordering,
{
exponential_search_by(self, f)
}
#[inline]
pub fn exponential_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
where F: FnMut(&T) -> B,
B: Ord,
{
exponential_search_by_key(self, b, f)
}
#[inline]
pub fn contains(&self, x: &T) -> bool
where T: Ord,
{
self.exponential_search(x).is_ok()
}
#[inline]
pub fn to_set_buf(&self) -> SetBuf<T>
where T: Clone
{
SetBuf(self.0.to_vec())
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&self.0
}
#[inline]
pub fn iter(&self) -> std::slice::Iter<T> {
self.0.iter()
}
}
impl<T: Clone> ToOwned for Set<T> {
type Owned = SetBuf<T>;
fn to_owned(&self) -> Self::Owned {
SetBuf(self.0.to_owned())
}
}
impl<T> Default for &Set<T> {
fn default() -> Self {
Set::new_unchecked(&[])
}
}
impl<T> Deref for Set<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> AsRef<[T]> for Set<T> {
fn as_ref(&self) -> &[T] {
&self.0
}
}
impl<T> AsRef<Set<T>> for Set<T> {
fn as_ref(&self) -> &Set<T> {
self
}
}
impl<'a, T> IntoIterator for &'a Set<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg_attr(feature="serde", derive(Serialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SetBuf<T>(Vec<T>);
impl<T> SetBuf<T> {
#[inline]
pub fn new(vec: Vec<T>) -> Result<Self, Error>
where T: Ord
{
is_sort_dedup(&vec).map(|_| SetBuf::new_unchecked(vec))
}
pub fn from_dirty(mut vec: Vec<T>) -> Self
where T: Ord,
{
sort_dedup_vec(&mut vec);
SetBuf(vec)
}
#[inline]
pub fn new_unchecked(vec: Vec<T>) -> Self {
SetBuf(vec)
}
#[inline]
pub fn as_set(&self) -> &Set<T> {
Set::new_unchecked(self.0.as_slice())
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
self.0
}
#[inline]
pub fn iter(&self) -> std::slice::Iter<T> {
self.0.iter()
}
}
impl<T> Borrow<Set<T>> for SetBuf<T> {
fn borrow(&self) -> &Set<T> {
self.as_set()
}
}
impl<T> Default for SetBuf<T> {
fn default() -> Self {
SetBuf::new_unchecked(Vec::new())
}
}
impl<T> Deref for SetBuf<T> {
type Target = Set<T>;
fn deref(&self) -> &Self::Target {
self.as_set()
}
}
impl<T> AsRef<Set<T>> for SetBuf<T> {
fn as_ref(&self) -> &Set<T> {
self.as_set()
}
}
impl<T> AsRef<[T]> for SetBuf<T> {
fn as_ref(&self) -> &[T] {
self.0.as_slice()
}
}
impl<T> IntoIterator for SetBuf<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[cfg(feature="serde")]
use serde::de::{Deserializer, Error as SerdeError};
#[cfg(feature="serde")]
impl<'de, T> Deserialize<'de> for SetBuf<T>
where
T: Deserialize<'de> + Ord,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let vec = Vec::deserialize(deserializer)?;
match SetBuf::new(vec) {
Ok(set) => Ok(set),
Err(e) => Err(D::Error::custom(e)),
}
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
Vec::deserialize_in_place(deserializer, &mut place.0)?;
is_sort_dedup(&place.0).map_err(D::Error::custom)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Error {
NotSort,
NotDedup,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let desc = match self {
Error::NotSort => "elements are not sorted.",
Error::NotDedup => "elements contain duplicates.",
};
f.write_str(desc)
}
}
impl error::Error for Error {}
pub type Errors = Vec<Option<Error>>;
pub fn vec_slices_into_sets<T: Ord>(vec: Vec<&[T]>) -> Result<Vec<&Set<T>>, (Vec<&[T]>, Errors)> {
let mut has_error = false;
let mut errors = Errors::with_capacity(vec.len());
for slice in &vec {
let res = is_sort_dedup(slice).err();
has_error = res.is_some();
errors.push(res);
}
if has_error {
return Err((vec, errors))
}
Ok(vec_slices_into_sets_unchecked(vec))
}
pub fn vec_slices_into_sets_unchecked<T>(vec: Vec<&[T]>) -> Vec<&Set<T>> {
unsafe { mem::transmute(vec) }
}
pub fn vec_sets_into_slices<T>(vec: Vec<&Set<T>>) -> Vec<&[T]> {
unsafe { mem::transmute(vec) }
}
pub fn slice_sets_into_slices<'a, T: 'a>(slice: &'a [&'a Set<T>]) -> &'a [&'a [T]] {
unsafe { mem::transmute(slice) }
}
pub fn sort_dedup_vec<T: Ord>(vec: &mut Vec<T>) {
vec.sort_unstable();
vec.dedup();
}
pub fn is_sort_dedup<T: Ord>(slice: &[T]) -> Result<(), Error> {
for pair in slice.windows(2) {
match pair[0].cmp(&pair[1]) {
Ordering::Less => (),
Ordering::Equal => return Err(Error::NotDedup),
Ordering::Greater => return Err(Error::NotSort),
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::ops::Bound::*;
#[test]
fn range_set() {
let set = Set::new(&[1, 2, 4, 6, 7]).unwrap();
let subset = set.range((Excluded(1), Unbounded));
assert_eq!(subset.as_slice(), &[2, 4, 6, 7]);
let subset = set.range((Excluded(1), Included(4)));
assert_eq!(subset.as_slice(), &[2, 4]);
let subset = set.range((Excluded(0), Included(4)));
assert_eq!(subset.as_slice(), &[1, 2, 4]);
let subset = set.range((Unbounded, Excluded(10)));
assert_eq!(subset.as_slice(), &[1, 2, 4, 6, 7]);
}
#[test]
fn cow_set_setbuf() {
use std::borrow::Cow;
let set = Set::new(&[1, 2, 4, 6, 7]).unwrap();
let borrowed_cow = Cow::Borrowed(set);
let owned_cow = borrowed_cow.to_owned();
assert_eq!(&*owned_cow, set);
}
}