btree_plus_store/copyable/
set.rs

1use crate::BTreeStore;
2use std::borrow::Borrow;
3use std::cmp::Ordering;
4use std::fmt::{Debug, Formatter};
5use std::hash::{Hash, Hasher};
6use std::marker::PhantomData;
7use std::mem::{size_of, transmute, MaybeUninit};
8use std::ops::{Deref, RangeBounds};
9
10/// A copyable, immutable b-tree set, which doesn't drop its contents.
11pub struct BTreeSet<'store, T> {
12    inner: RawBTreeSet<'store, T>,
13}
14
15pub type Iter<'a, T> = crate::set::Iter<'a, T>;
16pub type Range<'a, T> = crate::set::Range<'a, T>;
17
18impl<'store, T> From<crate::BTreeSet<'store, T>> for BTreeSet<'store, T> {
19    /// Creates a copyable set from a non-copyable set. Afterwards, the set is no longer mutable and
20    /// will no longer drop its contents.
21    #[inline]
22    fn from(inner: crate::BTreeSet<'store, T>) -> Self {
23        Self {
24            inner: RawBTreeSet::from(inner),
25        }
26    }
27}
28
29impl<'store, T> BTreeSet<'store, T> {
30    /// Returns the number of elements in the set.
31    #[inline]
32    pub fn len(&self) -> usize {
33        self.inner.len()
34    }
35
36    /// Returns `true` if the set contains no elements.
37    #[inline]
38    pub fn is_empty(&self) -> bool {
39        self.inner.is_empty()
40    }
41
42    /// The first value in the set, or `None` if empty.
43    #[inline]
44    pub fn first(&self) -> Option<&T> {
45        self.inner.first()
46    }
47
48    /// The last value in the set, or `None` if empty.
49    #[inline]
50    pub fn last(&self) -> Option<&T> {
51        self.inner.last()
52    }
53
54    /// Returns `true` if the set contains a value.
55    #[inline]
56    pub fn contains<U: Ord>(&self, value: &U) -> bool
57    where
58        T: Borrow<U>,
59    {
60        self.inner.contains(value)
61    }
62
63    /// Returns a reference to the equivalent value in the set, if any.
64    ///
65    /// This is (only) useful when `U` is a different type than `T`.
66    #[inline]
67    pub fn get<U: Ord>(&self, value: &U) -> Option<&T>
68    where
69        T: Borrow<U>,
70    {
71        self.inner.get(value)
72    }
73
74    /// Validates the set, *panic*ing if it is invalid. Specifically, we check that the number of
75    /// entries in each node is within the b-tree invariant bounds, and that the elements are in
76    /// order.
77    ///
78    /// Ideally, this should always be a no-op.
79    #[inline]
80    pub fn validate(&self)
81    where
82        T: Debug + Ord,
83    {
84        self.inner.validate()
85    }
86
87    /// Prints the b-tree in ascii
88    #[inline]
89    pub fn print(&self, f: &mut Formatter<'_>) -> std::fmt::Result
90    where
91        T: Debug,
92    {
93        self.inner.print(f)
94    }
95
96    /// Returns an iterator over the set.
97    #[inline]
98    pub fn iter(&self) -> Iter<'_, T> {
99        self.inner.iter()
100    }
101
102    /// Returns an iterator over the set within the given bounds
103    #[inline]
104    pub fn range<U: Ord>(&self, bounds: impl RangeBounds<U>) -> Range<T>
105    where
106        T: Borrow<U>,
107    {
108        self.inner.range(bounds)
109    }
110}
111
112// region common trait impls
113impl<'store, T: Debug> Debug for BTreeSet<'store, T> {
114    #[inline]
115    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
116        self.inner.fmt(f)
117    }
118}
119
120impl<'store, T> Clone for BTreeSet<'store, T> {
121    #[inline]
122    fn clone(&self) -> Self {
123        // SAFETY: This is copy-able because:
124        // - All of the fields (all of `inner`'s fields) are copy-able
125        // - `inner` implements [Drop], but we wrapped it in [ManuallyDrop]
126        // - Most importantly, we only allow access to functions which access inner's indirect data
127        //   via shared references, which means we can safely create multiple copies which point to
128        //   the same indirect data.
129        *self
130    }
131}
132
133impl<'store, T> Copy for BTreeSet<'store, T> {}
134
135impl<'store, T: PartialEq> PartialEq for BTreeSet<'store, T> {
136    #[inline]
137    fn eq(&self, other: &Self) -> bool {
138        &*self.inner == &*other.inner
139    }
140
141    #[inline]
142    fn ne(&self, other: &Self) -> bool {
143        &*self.inner != &*other.inner
144    }
145}
146
147impl<'store, T: Eq> Eq for BTreeSet<'store, T> {}
148
149impl<'store, T: PartialOrd> PartialOrd for BTreeSet<'store, T> {
150    #[inline]
151    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
152        self.inner.partial_cmp(&other.inner)
153    }
154}
155
156impl<'store, T: Ord> Ord for BTreeSet<'store, T> {
157    #[inline]
158    fn cmp(&self, other: &Self) -> Ordering {
159        self.inner.cmp(&other.inner)
160    }
161}
162
163impl<'store, T: Hash> Hash for BTreeSet<'store, T> {
164    #[inline]
165    fn hash<H: Hasher>(&self, state: &mut H) {
166        self.inner.hash(state)
167    }
168}
169// endregion
170
171// region RawBTreeSet
172/// [crate::BTreeSet] but as raw data so it can be [Copy]'d. Also doesn't run drop code.
173struct RawBTreeSet<'store, T> {
174    // generic parameters may not be used in const operations
175    // But fortunately [crate::BTreeSet]'s size doesn't depend on its generics, because everything
176    // is under an indirect pointer, and `T` is [Sized]
177    data: [MaybeUninit<u8>; size_of::<crate::BTreeSet<'static, ()>>()],
178    _p: PhantomData<&'store T>,
179}
180
181impl<'store, T> From<crate::BTreeSet<'store, T>> for RawBTreeSet<'store, T> {
182    #[inline]
183    fn from(inner: crate::BTreeSet<'store, T>) -> Self {
184        Self {
185            data: unsafe { transmute(inner) },
186            _p: PhantomData,
187        }
188    }
189}
190
191impl<'store, T> Deref for RawBTreeSet<'store, T> {
192    type Target = crate::BTreeSet<'store, T>;
193
194    #[inline]
195    fn deref(&self) -> &Self::Target {
196        unsafe { &*(self.data.as_ptr() as *const crate::BTreeSet<'store, T>) }
197    }
198}
199
200impl<'store, T> Clone for RawBTreeSet<'store, T> {
201    #[inline]
202    fn clone(&self) -> Self {
203        Self {
204            data: self.data,
205            _p: PhantomData,
206        }
207    }
208}
209
210impl<'store, T> Copy for RawBTreeSet<'store, T> {}
211// endregion
212
213//noinspection DuplicatedCode
214impl<'a, 'store: 'a, T> IntoIterator for &'a BTreeSet<'store, T> {
215    type Item = &'a T;
216    type IntoIter = Iter<'a, T>;
217
218    #[inline]
219    fn into_iter(self) -> Self::IntoIter {
220        self.iter()
221    }
222}
223
224impl<'store, T> crate::copyable::sealed::BTree<'store, T, ()> for BTreeSet<'store, T> {
225    #[inline]
226    fn assert_store(&self, store: &BTreeStore<T, ()>) {
227        self.inner.assert_store(store)
228    }
229
230    #[inline]
231    fn nodes(&self) -> crate::copyable::sealed::NodeIter<'store, T, ()> {
232        self.inner.nodes()
233    }
234}