arrayset.rs 7.0 KB

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