slots_slice/lib.rs
1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3#![deny(rustdoc::broken_intra_doc_links)]
4#![deny(rustdoc::invalid_rust_codeblocks)]
5#![deny(rustdoc::missing_crate_level_docs)]
6#![warn(rustdoc::invalid_codeblock_attributes)]
7pub type Slots<T> = [Option<T>];
8
9pub mod prelude {
10 pub use crate as slots_slice;
11 pub use crate::{array_of, replace, Direction, Slots, SlotsMutTrait, SlotsTrait};
12}
13
14/// Represents the direction for searching slots.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum Direction {
17 /// Search from the first slot to the last slot.
18 Front,
19 /// Search from the last slot to the first slot.
20 Back,
21}
22
23/// Provides utility methods for accessing and manipulating a collection of slots.
24///
25/// Content: counting, accessing indices, values, and entries.
26pub trait SlotsTrait<T>: AsRef<Slots<T>> {
27 /// Returns the number of occupied slots in the collection.
28 ///
29 /// # Examples
30 ///
31 /// ```
32 /// use slots_slice::SlotsTrait;
33 ///
34 /// let slots = [None, Some('a'), Some('b'), None];
35 /// assert_eq!(slots.count(), 2);
36 /// ```
37 fn count(&self) -> usize {
38 self.as_ref().iter().filter(|slot| slot.is_some()).count()
39 }
40
41 /// Checks if the collection is empty, i.e., all slots are empty.
42 ///
43 /// # Examples
44 ///
45 /// ```
46 /// use slots_slice::SlotsTrait;
47 ///
48 /// let slots: [Option<()>; 3] = [None, None, None];
49 /// assert!(slots.is_empty());
50 /// ```
51 fn is_empty(&self) -> bool {
52 self.count() == 0
53 }
54
55 /// Checks if the collection is full, i.e., all slots are occupied.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// use slots_slice::SlotsTrait;
61 ///
62 /// let slots = [Some('a'), Some('b'), Some('c')];
63 /// assert!(slots.is_full());
64 /// ```
65 fn is_full(&self) -> bool {
66 self.count() == self.as_ref().len()
67 }
68
69 /// Returns the index of the first slot that matches the occupancy state.
70 ///
71 /// # Examples
72 ///
73 /// ```
74 /// use slots_slice::{SlotsTrait, Direction};
75 ///
76 /// let slots = [None, Some('a'), None, Some('b')];
77 /// assert_eq!(slots.front_index(false), Some(0));
78 /// assert_eq!(slots.front_index(true), Some(1));
79 /// ```
80 fn front_index(&self, occupied: bool) -> Option<usize> {
81 self.as_ref()
82 .iter()
83 .position(move |slot| slot.is_some() == occupied)
84 }
85
86 /// Returns a reference to the value of the first occupied slot.
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use slots_slice::SlotsTrait;
92 ///
93 /// let slots = [None, Some('a'), Some('b')];
94 /// assert_eq!(slots.front_value(), Some(&'a'));
95 /// ```
96 fn front_value(&self) -> Option<&T> {
97 self.as_ref().iter().find_map(|slot| slot.as_ref())
98 }
99
100 /// Returns the index and a reference to the value of the first occupied slot.
101 ///
102 /// # Examples
103 ///
104 /// ```
105 /// use slots_slice::SlotsTrait;
106 ///
107 /// let slots = [None, Some('a'), Some('b')];
108 /// assert_eq!(slots.front_entry(), Some((1, &'a')));
109 /// ```
110 fn front_entry(&self) -> Option<(usize, &T)> {
111 self.as_ref()
112 .iter()
113 .enumerate()
114 .find_map(|(i, slot)| slot.as_ref().map(|v| (i, v)))
115 }
116
117 /// Returns the index of the last slot that matches the occupancy state.
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// use slots_slice::{SlotsTrait, Direction};
123 ///
124 /// let slots = [None, Some('a'), None, Some('b')];
125 /// assert_eq!(slots.back_index(false), Some(2));
126 /// assert_eq!(slots.back_index(true), Some(3));
127 /// ```
128 fn back_index(&self, occupied: bool) -> Option<usize> {
129 self.as_ref()
130 .iter()
131 .rposition(move |slot| slot.is_some() == occupied)
132 }
133
134 /// Returns a reference to the value of the last occupied slot.
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// use slots_slice::SlotsTrait;
140 ///
141 /// let slots = [Some('a'), Some('b'), None];
142 /// assert_eq!(slots.back_value(), Some(&'b'));
143 /// ```
144 fn back_value(&self) -> Option<&T> {
145 self.as_ref().iter().rev().find_map(|slot| slot.as_ref())
146 }
147
148 /// Returns the index and a reference to the value of the last occupied slot.
149 ///
150 /// # Examples
151 ///
152 /// ```
153 /// use slots_slice::SlotsTrait;
154 ///
155 /// let slots = [Some('a'), Some('b'), None];
156 /// assert_eq!(slots.back_entry(), Some((1, &'b')));
157 /// ```
158 fn back_entry(&self) -> Option<(usize, &T)> {
159 self.as_ref()
160 .iter()
161 .enumerate()
162 .rev()
163 .find_map(|(i, slot)| slot.as_ref().map(|v| (i, v)))
164 }
165
166 /// Returns the index of the slot in the specified direction that matches the occupancy state.
167 ///
168 /// # Examples
169 ///
170 /// ```
171 /// use slots_slice::{SlotsTrait, Direction};
172 ///
173 /// let slots = [None, Some('a'), None, Some('b')];
174 /// assert_eq!(slots.get_index(Direction::Front, false), slots.front_index(false));
175 /// assert_eq!(slots.get_index(Direction::Front, true), slots.front_index(true));
176 /// assert_eq!(slots.get_index(Direction::Back, false), slots.back_index(false));
177 /// assert_eq!(slots.get_index(Direction::Back, true), slots.back_index(true));
178 /// ```
179 fn get_index(&self, direction: Direction, occupied: bool) -> Option<usize> {
180 match direction {
181 Direction::Front => self.front_index(occupied),
182 Direction::Back => self.back_index(occupied),
183 }
184 }
185
186 /// Returns a reference to the value of the slot in the specified direction.
187 ///
188 /// # Examples
189 ///
190 /// ```
191 /// use slots_slice::{SlotsTrait, Direction};
192 ///
193 /// let slots = [Some('a'), None, Some('b')];
194 /// assert_eq!(slots.get_value(Direction::Front), slots.front_value());
195 /// assert_eq!(slots.get_value(Direction::Back), slots.back_value());
196 /// ```
197 fn get_value(&self, direction: Direction) -> Option<&T> {
198 match direction {
199 Direction::Front => self.front_value(),
200 Direction::Back => self.back_value(),
201 }
202 }
203
204 /// Returns the index and a reference to the value of the slot in the specified direction.
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// use slots_slice::{SlotsTrait, Direction};
210 ///
211 /// let slots = [Some('a'), None, Some('b')];
212 /// assert_eq!(slots.get_entry(Direction::Front), slots.front_entry());
213 /// assert_eq!(slots.get_entry(Direction::Back), slots.back_entry());
214 /// ```
215 fn get_entry(&self, direction: Direction) -> Option<(usize, &T)> {
216 match direction {
217 Direction::Front => self.front_entry(),
218 Direction::Back => self.back_entry(),
219 }
220 }
221}
222
223impl<T, A> SlotsTrait<T> for A where A: AsRef<Slots<T>> {}
224
225/// Provides mutable access and manipulation methods for a collection of slots.
226///
227/// This trait extends the [`SlotsTrait<T>`] trait and adds additional methods for mutating the slots.
228/// It is implemented for types that can be converted to a mutable reference of [`Slots<T>`].
229pub trait SlotsMutTrait<T>: SlotsTrait<T> + AsMut<Slots<T>> {
230 /// Returns a mutable reference to the value of the first occupied slot.
231 ///
232 /// # Examples
233 ///
234 /// ```
235 /// use slots_slice::SlotsMutTrait;
236 ///
237 /// let mut slots = [Some('a'), None, Some('b')];
238 /// if let Some(value) = slots.front_value_mut() {
239 /// *value = 'c';
240 /// }
241 /// assert_eq!(slots[0], Some('c'));
242 /// ```
243 fn front_value_mut(&mut self) -> Option<&mut T> {
244 self.as_mut().iter_mut().find_map(|slot| slot.as_mut())
245 }
246
247 /// Returns the index and a mutable reference to the value of the first occupied slot.
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use slots_slice::SlotsMutTrait;
253 ///
254 /// let mut slots = [Some('a'), None, Some('b')];
255 /// if let Some((index, value)) = slots.front_entry_mut() {
256 /// *value = 'c';
257 /// }
258 /// assert_eq!(slots[0], Some('c'));
259 /// ```
260 fn front_entry_mut(&mut self) -> Option<(usize, &mut T)> {
261 self.as_mut()
262 .iter_mut()
263 .enumerate()
264 .find_map(|(i, slot)| slot.as_mut().map(|v| (i, v)))
265 }
266
267 /// Returns a mutable reference to the value of the last occupied slot.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use slots_slice::SlotsMutTrait;
273 ///
274 /// let mut slots = [Some('a'), None, Some('b')];
275 /// if let Some(value) = slots.back_value_mut() {
276 /// *value = 'c';
277 /// }
278 /// assert_eq!(slots[2], Some('c'));
279 /// ```
280 fn back_value_mut(&mut self) -> Option<&mut T> {
281 self.as_mut()
282 .iter_mut()
283 .rev()
284 .find_map(|slot| slot.as_mut())
285 }
286
287 /// Returns the index and a mutable reference to the value of the last occupied slot.
288 ///
289 /// # Examples
290 ///
291 /// ```
292 /// use slots_slice::SlotsMutTrait;
293 ///
294 /// let mut slots = [Some('a'), None, Some('b')];
295 /// if let Some((index, value)) = slots.back_entry_mut() {
296 /// *value = 'c';
297 /// }
298 /// assert_eq!(slots[2], Some('c'));
299 /// ```
300 fn back_entry_mut(&mut self) -> Option<(usize, &mut T)> {
301 self.as_mut()
302 .iter_mut()
303 .rev()
304 .enumerate()
305 .find_map(|(i, slot)| slot.as_mut().map(|v| (i, v)))
306 }
307
308 /// Returns a mutable reference to the value of the slot in the specified direction.
309 ///
310 /// # Examples
311 ///
312 /// ```
313 /// use slots_slice::{SlotsMutTrait, Direction};
314 ///
315 /// let mut slots = [Some('a'), None, Some('b')];
316 /// if let Some(value) = slots.get_value_mut(Direction::Front) {
317 /// *value = 'c';
318 /// }
319 /// assert_eq!(slots[0], Some('c'));
320 ///
321 /// if let Some(value) = slots.get_value_mut(Direction::Back) {
322 /// *value = 'd';
323 /// }
324 /// assert_eq!(slots[2], Some('d'));
325 /// ```
326 fn get_value_mut(&mut self, direction: Direction) -> Option<&mut T> {
327 match direction {
328 Direction::Front => self.front_value_mut(),
329 Direction::Back => self.back_value_mut(),
330 }
331 }
332
333 /// Returns the index and a mutable reference to the value of the slot in the specified direction.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// use slots_slice::{SlotsMutTrait, Direction};
339 ///
340 /// let mut slots = [Some('a'), None, Some('b')];
341 /// if let Some((index, value)) = slots.get_entry_mut(Direction::Front) {
342 /// *value = 'c';
343 /// }
344 /// assert_eq!(slots[0], Some('c'));
345 ///
346 /// if let Some((index, value)) = slots.get_entry_mut(Direction::Back) {
347 /// *value = 'd';
348 /// }
349 /// assert_eq!(slots[2], Some('d'));
350 /// ```
351 fn get_entry_mut(&mut self, direction: Direction) -> Option<(usize, &mut T)> {
352 match direction {
353 Direction::Front => self.front_entry_mut(),
354 Direction::Back => self.back_entry_mut(),
355 }
356 }
357
358 /// Collapses the slots towards the front by removing unoccupied slots and shifting occupied slots to the left.
359 ///
360 /// # Examples
361 ///
362 /// ```
363 /// use slots_slice::SlotsMutTrait;
364 ///
365 /// let mut slots = [None, Some('a'), None, Some('b')];
366 /// slots.collapse_front();
367 /// assert_eq!(slots, [Some('a'), Some('b'), None, None]);
368 /// ```
369 fn collapse_front(&mut self) {
370 let slots = self.as_mut();
371 let mut write_index = 0;
372
373 for read_index in 0..slots.len() {
374 if slots[read_index].is_some() {
375 slots[write_index] = slots[read_index].take();
376 write_index += 1;
377 }
378 }
379 }
380
381 /// Collapses the slots towards the back by removing unoccupied slots and shifting occupied slots to the right.
382 ///
383 /// # Examples
384 ///
385 /// ```
386 /// use slots_slice::SlotsMutTrait;
387 ///
388 /// let mut slots = [None, Some('a'), None, Some('b')];
389 /// slots.collapse_back();
390 /// assert_eq!(slots, [None, None, Some('a'), Some('b')]);
391 /// ```
392 fn collapse_back(&mut self) {
393 let slots = self.as_mut();
394 let mut write_index = slots.len();
395
396 for read_index in (0..slots.len()).rev() {
397 if slots[read_index].is_some() {
398 write_index -= 1;
399 slots[write_index] = slots[read_index].take();
400 }
401 }
402 }
403
404 /// Collapses the slots in the specified direction by removing unoccupied slots and shifting occupied slots accordingly.
405 ///
406 /// # Examples
407 ///
408 /// ```
409 /// use slots_slice::{SlotsMutTrait, Direction};
410 ///
411 /// let mut slots = [None, Some('a'), None, Some('b')];
412 /// slots.collapse(Direction::Front);
413 /// assert_eq!(slots, [Some('a'), Some('b'), None, None]);
414 ///
415 /// let mut slots = [None, Some('a'), None, Some('b')];
416 /// slots.collapse(Direction::Back);
417 /// assert_eq!(slots, [None, None, Some('a'), Some('b')]);
418 /// ```
419 fn collapse(&mut self, direction: Direction) {
420 match direction {
421 Direction::Front => self.collapse_front(),
422 Direction::Back => self.collapse_back(),
423 }
424 }
425
426 /// Replaces the values of the slots based on the provided index-value pairs.
427 ///
428 /// The method takes an iterator of `(index, value)` pairs and replaces the values of the slots at the specified indices with the provided values.
429 ///
430 /// # Panics
431 ///
432 /// This method panics if an index is out of bounds.
433 ///
434 /// # Examples
435 ///
436 /// ```
437 /// use slots_slice::SlotsMutTrait;
438 ///
439 /// let mut slots = [None, None, None];
440 /// slots.replace([(0, 'a'), (2, 'b')]);
441 /// assert_eq!(slots, [Some('a'), None, Some('b')]);
442 /// ```
443 fn replace(&mut self, mapping: impl IntoIterator<Item = (usize, T)>) {
444 let slots = self.as_mut();
445 for (index, value) in mapping.into_iter() {
446 slots[index] = Some(value);
447 }
448 }
449
450 /// Tries to replace the values of the slots based on the provided index-value pairs, returning an error if any index is out of bounds.
451 ///
452 /// The method takes an iterator of `(index, value)` pairs and tries to replace the values of the slots at the specified indices with the provided values.
453 /// If any index is out of bounds, it returns an `Err` variant with the `(index, value)` pair that caused the error and the remaining iterator.
454 /// If all replacements are successful, it returns an `Ok` variant.
455 ///
456 /// # Examples
457 ///
458 /// ```
459 /// use slots_slice::SlotsMutTrait;
460 ///
461 /// let mut slots = [None, None, None];
462 ///
463 /// let result = slots.try_replace([(0, 'a'), (2, 'b')]);
464 /// assert!(result.is_ok());
465 /// assert_eq!(slots, [Some('a'), None, Some('b')]);
466 ///
467 /// let result = slots.try_replace([(1, 'c'), (3, 'd')]);
468 /// assert!(result.is_err());
469 /// let ((index, value), remaining) = result.unwrap_err();
470 /// assert_eq!(index, 3);
471 /// assert_eq!(value, 'd');
472 /// assert_eq!(remaining.collect::<Vec<_>>(), vec![]);
473 ///
474 /// ```
475 fn try_replace<M: IntoIterator<Item = (usize, T)>>(
476 &mut self,
477 mapping: M,
478 ) -> Result<(), ((usize, T), M::IntoIter)> {
479 let slots = self.as_mut();
480 let mut iter = mapping.into_iter();
481 while let Some((index, value)) = iter.next() {
482 if let Some(slot) = slots.get_mut(index) {
483 *slot = Some(value);
484 } else {
485 return Err(((index, value), iter));
486 }
487 }
488 Ok(())
489 }
490}
491impl<T, A> SlotsMutTrait<T> for A where A: SlotsTrait<T> + AsMut<Slots<T>> {}
492
493/// Returns an iterator over the indices of occupied or unoccupied slots in the `slots`.
494///
495/// # Example
496///
497/// ```
498/// use slots_slice;
499///
500/// let slots = [None, None, Some('a'), None, Some('b')];
501/// let occupied_indices: Vec<usize> = slots_slice::indices(&slots, true).collect();
502/// assert_eq!(occupied_indices, vec![2, 4]);
503///
504/// let unoccupied_indices: Vec<usize> = slots_slice::indices(&slots, false).collect();
505/// assert_eq!(unoccupied_indices, vec![0, 1, 3]);
506/// ```
507pub fn indices<'a, T>(slots: &'a Slots<T>, occupied: bool) -> impl Iterator<Item = usize> + 'a {
508 slots
509 .iter()
510 .enumerate()
511 .filter_map(move |(i, slot)| (slot.is_some() == occupied).then_some(i))
512}
513
514/// Returns an iterator over the values of occupied slots in the `slots`.
515///
516/// # Example
517///
518/// ```
519/// use slots_slice;
520///
521/// let slots = [None, None, Some('a'), None, Some('b')];
522/// let occupied_values: Vec<&char> = slots_slice::values(&slots).collect();
523/// assert_eq!(occupied_values, vec![&'a', &'b']);
524/// ```
525pub fn values<'a, T>(slots: &'a Slots<T>) -> impl Iterator<Item = &'a T> + 'a {
526 slots.iter().filter_map(|slot| slot.as_ref())
527}
528
529/// Returns an iterator over mutable references to the values of occupied slots in the `slots`.
530///
531/// # Example
532///
533/// ```
534/// use slots_slice;
535///
536/// let mut slots = [None, None, Some('a'), None, Some('b')];
537/// for value in slots_slice::values_mut(&mut slots) {
538/// *value = 'x';
539/// }
540/// assert_eq!(slots, [None, None, Some('x'), None, Some('x')]);
541/// ```
542pub fn values_mut<'a, T>(slots: &'a mut Slots<T>) -> impl Iterator<Item = &'a mut T> + 'a {
543 slots.iter_mut().filter_map(|slot| slot.as_mut())
544}
545
546/// Returns an iterator over the entries (index, value) of occupied slots in the `slots`.
547///
548/// # Example
549///
550/// ```
551/// use slots_slice;
552///
553/// let slots = [None, None, Some('a'), None, Some('b')];
554/// let occupied_entries: Vec<(usize, &char)> = slots_slice::entries(&slots).collect();
555/// assert_eq!(occupied_entries, vec![(2, &'a'), (4, &'b')]);
556/// ```
557pub fn entries<'a, T>(slots: &'a Slots<T>) -> impl Iterator<Item = (usize, &'a T)> + 'a {
558 slots
559 .iter()
560 .enumerate()
561 .filter_map(|(i, slot)| slot.as_ref().map(|v| (i, v)))
562}
563
564/// Returns an iterator over mutable references to the entries (index, value) of occupied slots in the `slots`.
565///
566/// # Example
567///
568/// ```
569/// use slots_slice;
570///
571/// let mut slots = [None, None, Some('a'), None, Some('b')];
572/// for (index, value) in slots_slice::entries_mut(&mut slots) {
573/// *value = 'x';
574/// }
575/// assert_eq!(slots, [None, None, Some('x'), None, Some('x')]);
576/// ```
577pub fn entries_mut<'a, T>(
578 slots: &'a mut Slots<T>,
579) -> impl Iterator<Item = (usize, &'a mut T)> + 'a {
580 slots
581 .iter_mut()
582 .enumerate()
583 .filter_map(|(i, slot)| slot.as_mut().map(|v| (i, v)))
584}
585
586/// Replaces the values at specified indices in the `slots` with the provided values.
587///
588/// This macro allows replacing multiple values in the `slots` at once. It takes a set of index-value pairs enclosed in curly braces.
589///
590/// # Examples
591///
592/// ```
593/// use slots_slice::replace;
594///
595/// let mut slots: [Option<u32>; 5] = [None; 5];
596///
597/// slots_slice::replace!(slots, { 1 => 42, 3 => 99 });
598///
599/// assert_eq!(slots, [None, Some(42), None, Some(99), None]);
600/// ```
601///
602/// # Panics
603/// As this macro uses [`ops::Index`](core::ops::Index), it may panic if any index is out of bounds.
604#[macro_export]
605macro_rules! replace {
606 ($slots:expr, { $($index:expr => $value:expr,)* }) => {
607 {
608 let slots = $slots.as_mut();
609 $(
610 slots[$index] = Some($value);
611 )*
612 }
613 };
614 ($slots:expr, { $($index:expr => $value:expr),* }) => {
615 replace!($slots, { $($index => $value,)* })
616 };
617}
618
619/// Creates an array of [`Option<T>`] with specified values at corresponding indices.
620///
621/// This macro allows creating an array of `Option<T>` with provided values at specified indices.
622/// The array size is determined by the first argument specified. Useful for large slots.
623///
624/// # Examples
625///
626/// ```
627/// use slots_slice::array_of;
628///
629/// let slots: [Option<char>; 5] = slots_slice::array_of!(5, { 1 => 'a', 3 => 'b' });
630///
631/// assert_eq!(slots, [None, Some('a'), None, Some('b'), None]);
632/// ```
633#[macro_export]
634macro_rules! array_of {
635 ($max:expr, { $($index:expr => $value:expr,)* }) => {
636 {
637 let mut slots: [_; $max] = ::core::array::from_fn(|_| None);
638 $(
639 slots[$index] = Some($value);
640 )*
641 slots
642 }
643 };
644 ($max:expr, { $($index:expr => $value:expr),* }) => {
645 array_of!($max, { $($index => $value,)* })
646 }
647}
648
649#[cfg(test)]
650mod test {
651 use super::*;
652
653 #[test]
654 fn create() {
655 assert_eq!(
656 [None, None, Some('a'), None, Some('b')],
657 array_of!(5, {
658 2 => 'a',
659 4 => 'b',
660 })
661 );
662 }
663
664 #[test]
665 fn test() {
666 let slots = array_of!(5, {
667 2 => 'a',
668 4 => 'b',
669 });
670
671 assert_eq!(slots, [None, None, Some('a'), None, Some('b')]);
672
673 assert_eq!(slots.count(), 2);
674 assert_eq!(slots.is_empty(), false);
675 assert_eq!(slots.is_full(), false);
676
677 assert_eq!(slots.front_index(false), Some(0));
678 assert_eq!(slots.front_index(true), Some(2));
679 assert_eq!(slots.front_value(), Some(&'a'));
680 assert_eq!(slots.front_entry(), Some((2, &'a')));
681
682 assert_eq!(slots.back_index(false), Some(3));
683 assert_eq!(slots.back_index(true), Some(4));
684 assert_eq!(slots.back_value(), Some(&'b'));
685 assert_eq!(slots.back_entry(), Some((4, &'b')));
686
687 assert_eq!(
688 slots.get_index(Direction::Front, false),
689 slots.front_index(false)
690 );
691 assert_eq!(
692 slots.get_index(Direction::Back, true),
693 slots.back_index(true)
694 );
695 assert_eq!(slots.get_value(Direction::Front), slots.front_value());
696 assert_eq!(slots.get_value(Direction::Back), slots.back_value());
697 assert_eq!(slots.get_entry(Direction::Front), slots.front_entry());
698 assert_eq!(slots.get_entry(Direction::Back), slots.back_entry());
699 }
700 #[test]
701 fn test_mut() {
702 let mut slots = array_of!(6, {
703 1 => 'a',
704 3 => 'b',
705 5 => 'C',
706 });
707
708 if let Some(value) = slots.front_value_mut() {
709 value.make_ascii_uppercase();
710 }
711 assert_eq!(slots.front_value(), Some(&'A'));
712
713 if let Some(value) = slots.back_value_mut() {
714 value.make_ascii_lowercase();
715 }
716 assert_eq!(slots.back_value(), Some(&'c'));
717
718 slots.collapse_front();
719 assert_eq!(slots, [Some('A'), Some('b'), Some('c'), None, None, None]);
720
721 slots.replace([(0, 'x'), (2, 'y'), (4, 'z')]);
722 assert_eq!(
723 slots,
724 [Some('x'), Some('b'), Some('y'), None, Some('z'), None]
725 );
726
727 for (i, value) in entries_mut(&mut slots) {
728 if i % 2 == 0 {
729 value.make_ascii_uppercase();
730 }
731 }
732 assert_eq!(
733 slots,
734 [Some('X'), Some('b'), Some('Y'), None, Some('Z'), None]
735 );
736 }
737
738 #[test]
739 fn c_front() {
740 let mut slots = [None, Some('a'), None, Some('b'), None, Some('c')];
741 slots.collapse_front();
742 assert_eq!(slots, [Some('a'), Some('b'), Some('c'), None, None, None]);
743 }
744 #[test]
745 fn c_back() {
746 let mut slots = [None, Some('a'), None, Some('b'), None, Some('c')];
747 slots.collapse_back();
748 assert_eq!(slots, [None, None, None, Some('a'), Some('b'), Some('c')]);
749 }
750 #[test]
751 fn replace() {
752 let mut slots = [None, None, None, None, None, None];
753 slots.replace([(1, 'a'), (2, 'b'), (3, 'c')]);
754 assert_eq!(slots, [None, Some('a'), Some('b'), Some('c'), None, None]);
755 }
756 #[test]
757 fn try_replace_ok() {
758 let mut slots = [None, None, None, None, None, None];
759 assert_eq!(
760 slots
761 .try_replace([(1, 'a'), (2, 'b'), (3, 'c')])
762 .map_err(|(entry, it)| (entry, it.collect::<Vec<_>>())),
763 Ok(())
764 );
765 assert_eq!(slots, [None, Some('a'), Some('b'), Some('c'), None, None]);
766 }
767 #[test]
768 fn try_replace_err() {
769 let mut slots = [None, None, None, None, None, None];
770 assert_eq!(
771 slots
772 .try_replace([(1, 'a'), (6, 'f'), (2, 'b'), (3, 'c')])
773 .map_err(|(entry, it)| (entry, it.collect::<Vec<_>>())),
774 Err(((6, 'f'), vec![(2, 'b'), (3, 'c')]))
775 );
776 }
777 #[test]
778 fn replace_macro() {
779 let mut slots = [None, None, None, None, None, None];
780 replace!(slots, {
781 1 => 'a',
782 2 => 'b',
783 3 => 'c',
784 });
785 assert_eq!(slots, [None, Some('a'), Some('b'), Some('c'), None, None]);
786 }
787 #[test]
788 fn slots_arr() {
789 let slots = array_of!(7, {
790 0 => 'a',
791 2 => 'b',
792 5 => 'c',
793 });
794 assert_eq!(
795 slots,
796 [Some('a'), None, Some('b'), None, None, Some('c'), None]
797 );
798 }
799 #[test]
800 fn iter_occupied_indices() {
801 let slots = array_of!(6, {
802 1 => 'a',
803 3 => 'b',
804 5 => 'c',
805 });
806 let mut indices = indices(&slots, true);
807 assert_eq!(indices.next(), Some(1));
808 assert_eq!(indices.next(), Some(3));
809 assert_eq!(indices.next(), Some(5));
810 assert_eq!(indices.next(), None);
811 }
812 #[test]
813 fn iter_empty_indices() {
814 let slots = array_of!(6, {
815 1 => 'a',
816 3 => 'b',
817 5 => 'c',
818 });
819 let mut indices = indices(&slots, false);
820 assert_eq!(indices.next(), Some(0));
821 assert_eq!(indices.next(), Some(2));
822 assert_eq!(indices.next(), Some(4));
823 assert_eq!(indices.next(), None);
824 }
825 #[test]
826 fn iter_values() {
827 let slots = array_of!(6, {
828 1 => 'a',
829 3 => 'b',
830 5 => 'c',
831 });
832 let mut values = values(&slots);
833 assert_eq!(values.next(), Some(&'a'));
834 assert_eq!(values.next(), Some(&'b'));
835 assert_eq!(values.next(), Some(&'c'));
836 assert_eq!(values.next(), None);
837 }
838 #[test]
839 fn iter_values_mut() {
840 let mut slots = array_of!(6, {
841 1 => 'a',
842 3 => 'b',
843 5 => 'c',
844 });
845 for value in values_mut(&mut slots) {
846 *value = 'x';
847 }
848 assert_eq!(slots, array_of!(6, { 1 => 'x', 3 => 'x', 5 => 'x' }));
849 }
850 #[test]
851 fn iter_entries() {
852 let slots = array_of!(6, {
853 1 => 'a',
854 3 => 'b',
855 5 => 'c',
856 });
857 let mut entries = entries(&slots);
858 assert_eq!(entries.next(), Some((1, &'a')));
859 assert_eq!(entries.next(), Some((3, &'b')));
860 assert_eq!(entries.next(), Some((5, &'c')));
861 assert_eq!(entries.next(), None);
862 }
863 #[test]
864 fn iter_entries_mut() {
865 let mut slots = array_of!(6, {
866 1 => 'a',
867 3 => 'b',
868 5 => 'c',
869 });
870 for (i, value) in entries_mut(&mut slots) {
871 if i == 3 {
872 *value = 'x';
873 }
874 }
875 assert_eq!(slots, array_of!(6, { 1 => 'a', 3 => 'x', 5 => 'c' }));
876 }
877}