1 #![cfg(feature = "experimental_array_set")]
3 // This was contributed by user `dhardy`! Big thanks.
5 use super::{take, Array}
;
10 ops
::{AddAssign, SubAssign}
,
13 /// Error resulting from attempting to insert into a full array
14 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
15 pub struct InsertError
;
17 // TODO(when std): impl std::error::Error for InsertError {}
19 impl fmt
::Display
for InsertError
{
20 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
21 write
!(f
, "ArraySet: insertion failed")
25 /// An array-backed set
27 /// This set supports `O(n)` operations and has a fixed size, thus may fail to
28 /// insert items. The potential advantage is a *really* small size.
30 /// The set is backed by an array of type `A` and indexed by type `L`.
31 /// The item type must support `Default`.
32 /// Due to restrictions, `L` may be only `u8` or `u16`.
33 #[derive(Clone, Debug, Default)]
34 pub struct ArraySet
<A
: Array
, L
> {
39 impl<A
: Array
+ Default
, L
: From
<u8>> ArraySet
<A
, L
> {
40 /// Constructs a new, empty, set
42 pub fn new() -> Self {
43 ArraySet { arr: Default::default(), len: 0.into() }
47 impl<A
: Array
, L
: Copy
+ Into
<usize>> ArraySet
<A
, L
> {
48 /// Constructs a new set from given inputs
50 /// Panics if `len> arr.len()`.
52 pub fn from(arr
: A
, len
: L
) -> Self {
53 if len
.into() > A
::CAPACITY
{
54 panic
!("ArraySet::from(array, len): len > array.len()");
60 impl<A
: Array
, L
> ArraySet
<A
, L
>
62 L
: Copy
+ PartialEq
+ From
<u8> + Into
<usize>,
64 /// Returns the fixed capacity of the set
66 pub fn capacity(&self) -> usize {
70 /// Returns the number of elements in the set
72 pub fn len(&self) -> usize {
76 /// Returns true when the set contains no elements
78 pub fn is_empty(&self) -> bool
{
82 /// Removes all elements
84 pub fn clear(&mut self) {
88 /// Iterate over all contents
90 pub fn iter(&self) -> Iter
<A
::Item
> {
91 Iter { a: self.arr.as_slice(), i: 0 }
95 impl<A
: Array
, L
> ArraySet
<A
, L
>
97 L
: Copy
+ PartialOrd
+ AddAssign
+ SubAssign
+ From
<u8> + Into
<usize>,
99 /// Check whether the set contains `elt`
101 pub fn contains
<Q
: Eq
+ ?Sized
>(&self, elt
: &Q
) -> bool
105 self.get(elt
).is_some()
108 /// Get a reference to a contained item matching `elt`
109 pub fn get
<Q
: Eq
+ ?Sized
>(&self, elt
: &Q
) -> Option
<&A
::Item
>
113 let len
: usize = self.len
.into();
114 let arr
= self.arr
.as_slice();
116 if arr
[i
].borrow() == elt
{
117 return Some(&arr
[i
]);
123 /// Remove an item matching `elt`, if any
124 pub fn remove
<Q
: Eq
+ ?Sized
>(&mut self, elt
: &Q
) -> Option
<A
::Item
>
128 let len
: usize = self.len
.into();
129 let arr
= self.arr
.as_slice_mut();
131 if arr
[i
].borrow() == elt
{
136 self.len
-= L
::from(1);
137 return Some(take(&mut arr
[l1
]));
143 /// Remove any items for which `f(item) == false`
144 pub fn retain
<F
>(&mut self, mut f
: F
)
146 F
: FnMut(&A
::Item
) -> bool
,
148 let mut len
= self.len
;
149 let arr
= self.arr
.as_slice_mut();
151 while i
< len
.into() {
155 arr
.swap(i
, len
.into());
165 impl<A
: Array
, L
> ArraySet
<A
, L
>
168 L
: Copy
+ PartialOrd
+ AddAssign
+ SubAssign
+ From
<u8> + Into
<usize>,
172 /// Due to the fixed size of the backing array, insertion may fail.
174 pub fn insert(&mut self, elt
: A
::Item
) -> Result
<bool
, InsertError
> {
175 if self.contains(&elt
) {
179 let len
= self.len
.into();
180 let arr
= self.arr
.as_slice_mut();
181 if len
>= arr
.len() {
182 return Err(InsertError
);
185 self.len
+= L
::from(1);
189 /* Hits borrow checker
190 pub fn get_or_insert(&mut self, elt: A::Item) -> Result<&A::Item, InsertError> {
191 if let Some(r) = self.get(&elt) {
195 let len: usize = self.len.into();
196 Ok(&self.arr.as_slice()[len - 1])
200 /// Replace an item matching `elt` with `elt`, or insert `elt`
202 /// Returns the replaced item, if any. Fails when there is no matching item
203 /// and the backing array is full, preventing insertion.
207 ) -> Result
<Option
<A
::Item
>, InsertError
> {
208 let len
: usize = self.len
.into();
209 let arr
= self.arr
.as_slice_mut();
212 swap(&mut arr
[i
], &mut elt
);
213 return Ok(Some(elt
));
217 if len
>= arr
.len() {
218 return Err(InsertError
);
221 self.len
+= L
::from(1);
226 /// Type returned by [`ArraySet::iter`]
227 pub struct Iter
<'a
, T
> {
232 impl<'a
, T
> ExactSizeIterator
for Iter
<'a
, T
> {
234 fn len(&self) -> usize {
235 self.a
.len() - self.i
239 impl<'a
, T
> Iterator
for Iter
<'a
, T
> {
243 fn next(&mut self) -> Option
<Self::Item
> {
244 if self.i
< self.a
.len() {
254 fn size_hint(&self) -> (usize, Option
<usize>) {
255 let len
= self.len();
263 use core
::mem
::size_of
;
267 assert_eq
!(size_of
::<ArraySet
<[i8; 7], u8>>(), 8);
272 let mut set
: ArraySet
<[i8; 7], u8> = ArraySet
::new();
273 assert_eq
!(set
.capacity(), 7);
275 assert_eq
!(set
.insert(1), Ok(true));
276 assert_eq
!(set
.insert(5), Ok(true));
277 assert_eq
!(set
.insert(6), Ok(true));
278 assert_eq
!(set
.len(), 3);
280 assert_eq
!(set
.insert(5), Ok(false));
281 assert_eq
!(set
.len(), 3);
283 assert_eq
!(set
.replace(1), Ok(Some(1)));
284 assert_eq
!(set
.replace(2), Ok(None
));
285 assert_eq
!(set
.len(), 4);
287 assert_eq
!(set
.insert(3), Ok(true));
288 assert_eq
!(set
.insert(4), Ok(true));
289 assert_eq
!(set
.insert(7), Ok(true));
290 assert_eq
!(set
.insert(8), Err(InsertError
));
291 assert_eq
!(set
.len(), 7);
293 assert_eq
!(set
.replace(9), Err(InsertError
));
295 assert_eq
!(set
.remove(&3), Some(3));
296 assert_eq
!(set
.len(), 6);
298 set
.retain(|x
| *x
== 3 || *x
== 6);
299 assert_eq
!(set
.len(), 1);
300 assert
!(!set
.contains(&3));
301 assert
!(set
.contains(&6));