use core::fmt;
use std::borrow::Borrow;
use std::collections::BTreeSet;
use std::num::NonZeroUsize;
#[cfg(feature = "serde")]
use serde::Deserialize;
#[cfg(feature = "serde")]
use serde::Serialize;
use crate::iter::NonEmptyIterator;
use crate::FromNonEmptyIterator;
use crate::IntoIteratorExt;
use crate::IntoNonEmptyIterator;
use crate::Singleton;
#[macro_export]
macro_rules! nebts {
($h:expr, $( $x:expr ),* $(,)?) => {{
let mut set = $crate::NEBTreeSet::new($h);
$( set.insert($x); )*
set
}};
($h:expr) => {
$crate::NEBTreeSet::new($h)
}
}
#[allow(clippy::unsafe_derive_deserialize)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(bound(
serialize = "T: Ord + Clone + Serialize",
deserialize = "T: Ord + Deserialize<'de>"
)),
serde(into = "BTreeSet<T>", try_from = "BTreeSet<T>")
)]
#[derive(Clone)]
pub struct NEBTreeSet<T> {
inner: BTreeSet<T>,
}
impl<T> NEBTreeSet<T>
where
T: Ord,
{
#[must_use]
pub fn new(value: T) -> Self {
let mut inner = BTreeSet::new();
inner.insert(value);
Self { inner }
}
pub fn iter(&self) -> std::collections::btree_set::Iter<'_, T> {
self.inner.iter()
}
pub fn nonempty_iter(&self) -> Iter<'_, T> {
Iter {
iter: self.inner.iter(),
}
}
#[must_use]
pub fn len(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(self.inner.len()) }
}
#[must_use]
pub fn try_from_set(set: BTreeSet<T>) -> Option<NEBTreeSet<T>> {
if set.is_empty() {
None
} else {
Some(NEBTreeSet { inner: set })
}
}
#[must_use]
pub fn contains<Q>(&self, value: &Q) -> bool
where
T: Ord + Borrow<Q>,
Q: Ord + ?Sized,
{
self.inner.contains(value)
}
pub fn difference<'a>(
&'a self,
other: &'a NEBTreeSet<T>,
) -> std::collections::btree_set::Difference<'a, T> {
self.inner.difference(&other.inner)
}
#[must_use]
pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
T: Ord + Borrow<Q>,
Q: Ord,
{
self.inner.get(value)
}
pub fn insert(&mut self, value: T) -> bool {
self.inner.insert(value)
}
pub fn intersection<'a>(
&'a self,
other: &'a NEBTreeSet<T>,
) -> std::collections::btree_set::Intersection<'a, T> {
self.inner.intersection(&other.inner)
}
#[must_use]
pub fn is_disjoint(&self, other: &NEBTreeSet<T>) -> bool {
self.inner.is_disjoint(&other.inner)
}
#[must_use]
pub fn is_subset(&self, other: &NEBTreeSet<T>) -> bool {
self.inner.is_subset(&other.inner)
}
#[must_use]
pub fn is_superset(&self, other: &NEBTreeSet<T>) -> bool {
self.inner.is_superset(&other.inner)
}
pub fn replace(&mut self, value: T) -> Option<T> {
self.inner.replace(value)
}
pub fn union<'a>(&'a self, other: &'a NEBTreeSet<T>) -> Union<'a, T> {
Union {
inner: self.inner.union(&other.inner),
}
}
}
impl<T> AsRef<BTreeSet<T>> for NEBTreeSet<T> {
fn as_ref(&self) -> &BTreeSet<T> {
&self.inner
}
}
impl<T> AsMut<BTreeSet<T>> for NEBTreeSet<T> {
fn as_mut(&mut self) -> &mut BTreeSet<T> {
&mut self.inner
}
}
impl<T> PartialEq for NEBTreeSet<T>
where
T: Ord,
{
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.intersection(other).count() == self.len().get()
}
}
impl<T> Eq for NEBTreeSet<T> where T: Ord {}
impl<T> IntoNonEmptyIterator for NEBTreeSet<T> {
type IntoNEIter = IntoIter<T>;
fn into_nonempty_iter(self) -> Self::IntoNEIter {
IntoIter {
iter: self.inner.into_iter(),
}
}
}
impl<'a, T> IntoNonEmptyIterator for &'a NEBTreeSet<T>
where
T: Ord,
{
type IntoNEIter = Iter<'a, T>;
fn into_nonempty_iter(self) -> Self::IntoNEIter {
self.nonempty_iter()
}
}
impl<T> IntoIterator for NEBTreeSet<T> {
type Item = T;
type IntoIter = std::collections::btree_set::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a, T> IntoIterator for &'a NEBTreeSet<T>
where
T: Ord,
{
type Item = &'a T;
type IntoIter = std::collections::btree_set::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T> FromNonEmptyIterator<T> for NEBTreeSet<T>
where
T: Ord,
{
fn from_nonempty_iter<I>(iter: I) -> Self
where
I: IntoNonEmptyIterator<Item = T>,
{
NEBTreeSet {
inner: iter.into_nonempty_iter().into_iter().collect(),
}
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct Iter<'a, T: 'a> {
iter: std::collections::btree_set::Iter<'a, T>,
}
impl<'a, T: 'a> IntoIterator for Iter<'a, T> {
type Item = &'a T;
type IntoIter = std::collections::btree_set::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter
}
}
impl<T> NonEmptyIterator for Iter<'_, T> {}
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct IntoIter<T> {
iter: std::collections::btree_set::IntoIter<T>,
}
impl<T> IntoIterator for IntoIter<T> {
type Item = T;
type IntoIter = std::collections::btree_set::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.iter
}
}
impl<T> NonEmptyIterator for IntoIter<T> {}
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.fmt(f)
}
}
#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
pub struct Union<'a, T: 'a> {
inner: std::collections::btree_set::Union<'a, T>,
}
impl<'a, T> IntoIterator for Union<'a, T>
where
T: Ord,
{
type Item = &'a T;
type IntoIter = std::collections::btree_set::Union<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.inner
}
}
impl<T> NonEmptyIterator for Union<'_, T> where T: Ord {}
impl<T> fmt::Debug for Union<'_, T>
where
T: fmt::Debug + Ord,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<T> From<NEBTreeSet<T>> for BTreeSet<T>
where
T: Ord,
{
fn from(s: NEBTreeSet<T>) -> Self {
s.inner
}
}
impl<T: fmt::Debug> fmt::Debug for NEBTreeSet<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<T> TryFrom<BTreeSet<T>> for NEBTreeSet<T>
where
T: Ord,
{
type Error = crate::Error;
fn try_from(set: BTreeSet<T>) -> Result<Self, Self::Error> {
let ne = set
.try_into_nonempty_iter()
.ok_or(crate::Error::Empty)?
.collect();
Ok(ne)
}
}
impl<T> Singleton for NEBTreeSet<T>
where
T: Ord,
{
type Item = T;
fn singleton(item: Self::Item) -> Self {
NEBTreeSet::new(item)
}
}
impl<T> Extend<T> for NEBTreeSet<T>
where
T: Ord,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.inner.extend(iter);
}
}
#[cfg(test)]
mod test {
use maplit::btreeset;
#[test]
fn debug_impl() {
let expected = format!("{:?}", btreeset! {0});
let actual = format!("{:?}", nebts! {0});
assert_eq!(expected, actual);
}
#[test]
fn iter_debug_impl() {
let expected = format!("{:?}", btreeset! {0}.iter());
let actual = format!("{:?}", nebts! {0}.nonempty_iter());
assert_eq!(expected, actual);
}
}
#[cfg(feature = "serde")]
#[cfg(test)]
mod serde_tests {
use crate::NEBTreeSet;
use std::collections::BTreeSet;
#[test]
fn json() {
let set0 = nebts![1, 1, 2, 3, 2, 1, 4];
let j = serde_json::to_string(&set0).unwrap();
let set1 = serde_json::from_str(&j).unwrap();
assert_eq!(set0, set1);
let empty: BTreeSet<usize> = BTreeSet::new();
let j = serde_json::to_string(&empty).unwrap();
let bad = serde_json::from_str::<NEBTreeSet<usize>>(&j);
assert!(bad.is_err());
}
}