nonempty_containers/
ne_ordered_set.rs

1use crate::errors::NonEmptyError;
2use crate::errors::NonEmptyError::Empty;
3use std::collections::btree_set::{IntoIter, Iter};
4use std::collections::BTreeSet;
5
6/// An ordered non-empty set type guaranteeing at least one element.
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
8pub struct NEOrderedSet<T: Ord>(BTreeSet<T>);
9
10impl<T: Ord> NEOrderedSet<T> {
11    /// Creates a new non-empty ordered set from one element and optional additional elements.
12    pub fn new(head: T, tail: Vec<T>) -> Self {
13        let mut set = BTreeSet::new();
14        set.insert(head);
15        set.extend(tail);
16        Self(set)
17    }
18
19    /// Creates a singleton ordered non-empty set.
20    pub fn singleton(value: T) -> Self {
21        let mut set = BTreeSet::new();
22        set.insert(value);
23        Self(set)
24    }
25
26    /// Attempts to create a non-empty ordered set from a BTreeSet.
27    /// Returns an error if the provided set is empty.
28    pub fn from(set: BTreeSet<T>) -> Result<Self, NonEmptyError> {
29        if set.is_empty() {
30            Err(Empty)
31        } else {
32            Ok(Self(set))
33        }
34    }
35
36    /// Hidden constructor used internally by macros.
37    #[doc(hidden)]
38    pub fn __from_set_unsafe(set: BTreeSet<T>) -> Self {
39        debug_assert!(!set.is_empty());
40        Self(set)
41    }
42
43    /// Extracts the underlying ordered set.
44    pub fn into_set(self) -> BTreeSet<T> {
45        self.0
46    }
47
48    /// Always returns false since the set is never empty.
49    pub fn is_empty(&self) -> bool {
50        false
51    }
52
53    /// Adds an element. Returns true if the set did not already contain the value.
54    pub fn insert(&mut self, value: T) -> bool {
55        self.0.insert(value)
56    }
57
58    /// Removes an element. Returns true if the set contained the value.
59    pub fn remove(&mut self, value: &T) -> bool {
60        if self.0.len() == 1 && self.0.contains(&value) {
61            false // Prevent removal to maintain non-empty invariant
62        } else {
63            self.0.remove(&value)
64        }
65    }
66
67    /// Returns true if the set contains a value.
68    pub fn contains(&self, value: &T) -> bool {
69        self.0.contains(value)
70    }
71
72    /// Returns the number of elements in the set.
73    pub fn len(&self) -> usize {
74        self.0.len()
75    }
76}
77
78impl<T: Ord> From<NEOrderedSet<T>> for BTreeSet<T> {
79    fn from(set: NEOrderedSet<T>) -> Self {
80        set.into_set()
81    }
82}
83
84impl<T: Ord> TryFrom<BTreeSet<T>> for NEOrderedSet<T> {
85    type Error = NonEmptyError;
86
87    fn try_from(set: BTreeSet<T>) -> Result<Self, Self::Error> {
88        Self::from(set)
89    }
90}
91
92impl<T: Ord> IntoIterator for NEOrderedSet<T> {
93    type Item = T;
94    type IntoIter = IntoIter<T>;
95
96    fn into_iter(self) -> Self::IntoIter {
97        self.0.into_iter()
98    }
99}
100
101impl<'a, T: Ord> IntoIterator for &'a NEOrderedSet<T> {
102    type Item = &'a T;
103    type IntoIter = Iter<'a, T>;
104
105    fn into_iter(self) -> Self::IntoIter {
106        self.0.iter()
107    }
108}