1 #![cfg(feature = "experimental_array_set")] 2 3 // This was contributed by user `dhardy`! Big thanks. 4 5 use super::{take, Array}; 6 use core::{ 7 borrow::Borrow, 8 fmt, 9 mem::swap, 10 ops::{AddAssign, SubAssign}, 11 }; 12 13 /// Error resulting from attempting to insert into a full array 14 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 15 pub struct InsertError; 16 17 // TODO(when std): impl std::error::Error for InsertError {} 18 19 impl fmt::Display for InsertError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 21 write!(f, "ArraySet: insertion failed") 22 } 23 } 24 25 /// An array-backed set 26 /// 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. 29 /// 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> { 35 arr: A, 36 len: L, 37 } 38 39 impl<A: Array + Default, L: From<u8>> ArraySet<A, L> { 40 /// Constructs a new, empty, set 41 #[inline] new() -> Self42 pub fn new() -> Self { 43 ArraySet { arr: Default::default(), len: 0.into() } 44 } 45 } 46 47 impl<A: Array, L: Copy + Into<usize>> ArraySet<A, L> { 48 /// Constructs a new set from given inputs 49 /// 50 /// Panics if `len> arr.len()`. 51 #[inline] from(arr: A, len: L) -> Self52 pub fn from(arr: A, len: L) -> Self { 53 if len.into() > A::CAPACITY { 54 panic!("ArraySet::from(array, len): len > array.len()"); 55 } 56 ArraySet { arr, len } 57 } 58 } 59 60 impl<A: Array, L> ArraySet<A, L> 61 where 62 L: Copy + PartialEq + From<u8> + Into<usize>, 63 { 64 /// Returns the fixed capacity of the set 65 #[inline] capacity(&self) -> usize66 pub fn capacity(&self) -> usize { 67 A::CAPACITY 68 } 69 70 /// Returns the number of elements in the set 71 #[inline] len(&self) -> usize72 pub fn len(&self) -> usize { 73 self.len.into() 74 } 75 76 /// Returns true when the set contains no elements 77 #[inline] is_empty(&self) -> bool78 pub fn is_empty(&self) -> bool { 79 self.len == 0.into() 80 } 81 82 /// Removes all elements 83 #[inline] clear(&mut self)84 pub fn clear(&mut self) { 85 self.len = 0.into(); 86 } 87 88 /// Iterate over all contents 89 #[inline] iter(&self) -> Iter<A::Item>90 pub fn iter(&self) -> Iter<A::Item> { 91 Iter { a: self.arr.as_slice(), i: 0 } 92 } 93 } 94 95 impl<A: Array, L> ArraySet<A, L> 96 where 97 L: Copy + PartialOrd + AddAssign + SubAssign + From<u8> + Into<usize>, 98 { 99 /// Check whether the set contains `elt` 100 #[inline] contains<Q: Eq + ?Sized>(&self, elt: &Q) -> bool where A::Item: Borrow<Q>,101 pub fn contains<Q: Eq + ?Sized>(&self, elt: &Q) -> bool 102 where 103 A::Item: Borrow<Q>, 104 { 105 self.get(elt).is_some() 106 } 107 108 /// Get a reference to a contained item matching `elt` get<Q: Eq + ?Sized>(&self, elt: &Q) -> Option<&A::Item> where A::Item: Borrow<Q>,109 pub fn get<Q: Eq + ?Sized>(&self, elt: &Q) -> Option<&A::Item> 110 where 111 A::Item: Borrow<Q>, 112 { 113 let len: usize = self.len.into(); 114 let arr = self.arr.as_slice(); 115 for i in 0..len { 116 if arr[i].borrow() == elt { 117 return Some(&arr[i]); 118 } 119 } 120 None 121 } 122 123 /// Remove an item matching `elt`, if any remove<Q: Eq + ?Sized>(&mut self, elt: &Q) -> Option<A::Item> where A::Item: Borrow<Q>,124 pub fn remove<Q: Eq + ?Sized>(&mut self, elt: &Q) -> Option<A::Item> 125 where 126 A::Item: Borrow<Q>, 127 { 128 let len: usize = self.len.into(); 129 let arr = self.arr.as_slice_mut(); 130 for i in 0..len { 131 if arr[i].borrow() == elt { 132 let l1 = len - 1; 133 if i < l1 { 134 arr.swap(i, l1); 135 } 136 self.len -= L::from(1); 137 return Some(take(&mut arr[l1])); 138 } 139 } 140 None 141 } 142 143 /// Remove any items for which `f(item) == false` retain<F>(&mut self, mut f: F) where F: FnMut(&A::Item) -> bool,144 pub fn retain<F>(&mut self, mut f: F) 145 where 146 F: FnMut(&A::Item) -> bool, 147 { 148 let mut len = self.len; 149 let arr = self.arr.as_slice_mut(); 150 let mut i = 0; 151 while i < len.into() { 152 if !f(&arr[i]) { 153 len -= L::from(1); 154 if i < len.into() { 155 arr.swap(i, len.into()); 156 } 157 } else { 158 i += 1; 159 } 160 } 161 self.len = len; 162 } 163 } 164 165 impl<A: Array, L> ArraySet<A, L> 166 where 167 A::Item: Eq, 168 L: Copy + PartialOrd + AddAssign + SubAssign + From<u8> + Into<usize>, 169 { 170 /// Insert an item 171 /// 172 /// Due to the fixed size of the backing array, insertion may fail. 173 #[inline] insert(&mut self, elt: A::Item) -> Result<bool, InsertError>174 pub fn insert(&mut self, elt: A::Item) -> Result<bool, InsertError> { 175 if self.contains(&elt) { 176 return Ok(false); 177 } 178 179 let len = self.len.into(); 180 let arr = self.arr.as_slice_mut(); 181 if len >= arr.len() { 182 return Err(InsertError); 183 } 184 arr[len] = elt; 185 self.len += L::from(1); 186 Ok(true) 187 } 188 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) { 192 return Ok(r); 193 } 194 self.insert(elt)?; 195 let len: usize = self.len.into(); 196 Ok(&self.arr.as_slice()[len - 1]) 197 } 198 */ 199 200 /// Replace an item matching `elt` with `elt`, or insert `elt` 201 /// 202 /// Returns the replaced item, if any. Fails when there is no matching item 203 /// and the backing array is full, preventing insertion. replace( &mut self, mut elt: A::Item, ) -> Result<Option<A::Item>, InsertError>204 pub fn replace( 205 &mut self, 206 mut elt: A::Item, 207 ) -> Result<Option<A::Item>, InsertError> { 208 let len: usize = self.len.into(); 209 let arr = self.arr.as_slice_mut(); 210 for i in 0..len { 211 if arr[i] == elt { 212 swap(&mut arr[i], &mut elt); 213 return Ok(Some(elt)); 214 } 215 } 216 217 if len >= arr.len() { 218 return Err(InsertError); 219 } 220 arr[len] = elt; 221 self.len += L::from(1); 222 Ok(None) 223 } 224 } 225 226 /// Type returned by [`ArraySet::iter`] 227 pub struct Iter<'a, T> { 228 a: &'a [T], 229 i: usize, 230 } 231 232 impl<'a, T> ExactSizeIterator for Iter<'a, T> { 233 #[inline] len(&self) -> usize234 fn len(&self) -> usize { 235 self.a.len() - self.i 236 } 237 } 238 239 impl<'a, T> Iterator for Iter<'a, T> { 240 type Item = &'a T; 241 242 #[inline] next(&mut self) -> Option<Self::Item>243 fn next(&mut self) -> Option<Self::Item> { 244 if self.i < self.a.len() { 245 let i = self.i; 246 self.i += 1; 247 Some(&self.a[i]) 248 } else { 249 None 250 } 251 } 252 253 #[inline] size_hint(&self) -> (usize, Option<usize>)254 fn size_hint(&self) -> (usize, Option<usize>) { 255 let len = self.len(); 256 (len, Some(len)) 257 } 258 } 259 260 #[cfg(test)] 261 mod test { 262 use super::*; 263 use core::mem::size_of; 264 265 #[test] test_size()266 fn test_size() { 267 assert_eq!(size_of::<ArraySet<[i8; 7], u8>>(), 8); 268 } 269 270 #[test] test()271 fn test() { 272 let mut set: ArraySet<[i8; 7], u8> = ArraySet::new(); 273 assert_eq!(set.capacity(), 7); 274 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); 279 280 assert_eq!(set.insert(5), Ok(false)); 281 assert_eq!(set.len(), 3); 282 283 assert_eq!(set.replace(1), Ok(Some(1))); 284 assert_eq!(set.replace(2), Ok(None)); 285 assert_eq!(set.len(), 4); 286 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); 292 293 assert_eq!(set.replace(9), Err(InsertError)); 294 295 assert_eq!(set.remove(&3), Some(3)); 296 assert_eq!(set.len(), 6); 297 298 set.retain(|x| *x == 3 || *x == 6); 299 assert_eq!(set.len(), 1); 300 assert!(!set.contains(&3)); 301 assert!(set.contains(&6)); 302 } 303 } 304