Skip to main content

nanvm_lib/common/
sized_index.rs

1use core::ops::Index;
2
3use crate::common::{default::default, index_iter::IndexIter, uint::Uint};
4
5/// A container indexed by `I` from `0` up to [`length`](Self::length).
6///
7/// The length is fixed: it does not change for as long as the container is
8/// held, so [`IndexIter`] can promise an exact `size_hint` and stay fused. A
9/// container with interior mutability that could change its length must not
10/// implement this trait.
11pub trait SizedIndex<I: Uint>: Index<I> {
12    fn length(&self) -> I;
13    fn is_empty(&self) -> bool {
14        self.length() == default()
15    }
16    /// Element `i` if it is below [`length`](Self::length), and `None` past
17    /// the end, where `Index` panics: the bound every reader of an element
18    /// that may be absent would otherwise write for itself.
19    fn get(&self, i: I) -> Option<&Self::Output> {
20        if i < self.length() {
21            Some(&self[i])
22        } else {
23            None
24        }
25    }
26    fn last(&self) -> Option<&Self::Output> {
27        if self.is_empty() {
28            None
29        } else {
30            Some(&self[self.length() - 1.into()])
31        }
32    }
33    fn index_iter(self) -> IndexIter<I, Self>
34    where
35        Self: Sized,
36    {
37        IndexIter::new(self)
38    }
39}
40
41impl<T> SizedIndex<usize> for [T] {
42    fn length(&self) -> usize {
43        self.len()
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::SizedIndex;
50    use crate::{naive::Naive, vm::String};
51
52    /// An index below the length is its element; the length and past it
53    /// are `None`, where `Index` would panic.
54    #[test]
55    fn get() {
56        let s: String<Naive> = "ab".into();
57        assert_eq!(s.get(0), Some(&0x61));
58        assert_eq!(s.get(1), Some(&0x62));
59        assert_eq!(s.get(2), None);
60        assert_eq!(s.get(u32::MAX), None);
61        assert_eq!(String::<Naive>::from("").get(0), None);
62    }
63}