offset_views/
lib.rs

1pub mod with_offset;
2pub use with_offset::WithOffset;
3
4use std::ops::{Index, IndexMut};
5use std::slice::SliceIndex;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct OffsetSlice<'a, T> {
9    parent: &'a [T],
10    offset: isize,
11}
12
13impl<'a, T> OffsetSlice<'a, T> {
14    pub fn new(parent: &'a [T], offset: isize) -> OffsetSlice<'a, T> {
15        OffsetSlice { parent, offset }
16    }
17}
18
19// impl<'a, T> Index<isize> for OffsetSlice<'a, T> {
20//     type Output = T;
21//     fn index(&self, index: isize) -> &Self::Output {
22//         let index: usize = (index + self.offset)
23//             .try_into()
24//             .expect("cannot convert to `usize`");
25//         self.parent.index(index)
26//     }
27// }
28
29impl<'a, T, I> Index<I> for OffsetSlice<'a, T>
30where
31    I: WithOffset<isize>,
32    I::Output: SliceIndex<[T]>,
33{
34    type Output = <I::Output as SliceIndex<[T]>>::Output;
35    fn index(&self, index: I) -> &Self::Output {
36        let index = index.with_offset(self.offset);
37        self.parent.index(index)
38    }
39}
40
41#[derive(Debug, PartialEq, Eq)]
42pub struct OffsetSliceMut<'a, T> {
43    parent: &'a mut [T],
44    offset: isize,
45}
46
47impl<'a, T> OffsetSliceMut<'a, T> {
48    pub fn new(parent: &'a mut [T], offset: isize) -> OffsetSliceMut<'a, T> {
49        OffsetSliceMut { parent, offset }
50    }
51}
52
53impl<'a, T, I> Index<I> for OffsetSliceMut<'a, T>
54where
55    I: WithOffset<isize>,
56    I::Output: SliceIndex<[T]>,
57{
58    type Output = <I::Output as SliceIndex<[T]>>::Output;
59    fn index(&self, index: I) -> &Self::Output {
60        let index = index.with_offset(self.offset);
61        self.parent.index(index)
62    }
63}
64
65impl<'a, T, I> IndexMut<I> for OffsetSliceMut<'a, T>
66where
67    I: WithOffset<isize>,
68    I::Output: SliceIndex<[T]>,
69{
70    fn index_mut(&mut self, index: I) -> &mut Self::Output {
71        let index = index.with_offset(self.offset);
72        self.parent.index_mut(index)
73    }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77struct OffsetView<P, O> {
78    parent: P,
79    offset: O,
80}
81
82impl<P, O> OffsetView<P, O> {
83    fn new(parent: P, offset: O) -> OffsetView<P, O> {
84        OffsetView { parent, offset }
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use cool_asserts::assert_panics;
92
93    #[test]
94    fn offset_slice_works() {
95        let a = [0, 1, 2, 3, 4, 5];
96        let os = OffsetSlice::new(&a, -3isize);
97        for i in 3..=8 {
98            assert_eq!(os[i], i - 3);
99        }
100        assert_panics!(os[2], includes("cannot convert to `usize`"));
101        assert_panics!(os[9], includes("index out of bounds"));
102    }
103
104    #[test]
105    fn offset_slice_mut_works() {
106        let mut a = [0, 1, 2, 3, 4, 5];
107        let mut os = OffsetSliceMut::new(&mut a, -3isize);
108        for i in 3..=8 {
109            assert_eq!(os[i], i - 3);
110            os[i] = 0;
111        }
112        assert_panics!(os[2], includes("cannot convert to `usize`"));
113        assert_panics!(os[9], includes("index out of bounds"));
114        for i in 3..=8 {
115            assert_eq!(os[i], 0);
116        }
117    }
118
119    #[test]
120    fn can_create_from_string() {
121        let parent = String::from("Hello!");
122        let view = OffsetView::new(&parent, -2);
123        assert_eq!(view.parent, &parent);
124        assert_eq!(view.offset, -2);
125    }
126
127    #[test]
128    fn can_create_from_array() {
129        let parent = [0, 1, 2, 3];
130        let view = OffsetView::new(&parent, -2);
131        assert_eq!(view.parent, &parent);
132        assert_eq!(view.offset, -2);
133    }
134}