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}