copy_stack_vec/
index.rs

1// This file is part of copy-stack-vec.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Indexing support for [`CopyStackVec`](crate::CopyStackVec).
5//!
6//! This module provides `Index` and `IndexMut` impls that mirror slice behavior:
7//! - panics on out-of-bounds;
8//! - supports all standard range forms, including inclusive ranges;
9//! - views are restricted to the initialized prefix `[0..len)`.
10
11// Crate imports
12use crate::vec::CopyStackVec;
13
14// Core imports
15use core::ops::{
16    Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
17};
18
19impl<T: Copy, const N: usize> Index<usize> for CopyStackVec<T, N> {
20    type Output = T;
21    fn index(&self, i: usize) -> &Self::Output {
22        &self.as_slice()[i]
23    }
24}
25
26// Read-only ranges
27impl<T: Copy, const N: usize> Index<Range<usize>> for CopyStackVec<T, N> {
28    type Output = [T];
29    fn index(&self, r: Range<usize>) -> &Self::Output {
30        &self.as_slice()[r]
31    }
32}
33impl<T: Copy, const N: usize> Index<RangeFrom<usize>> for CopyStackVec<T, N> {
34    type Output = [T];
35    fn index(&self, r: RangeFrom<usize>) -> &Self::Output {
36        &self.as_slice()[r]
37    }
38}
39impl<T: Copy, const N: usize> Index<RangeTo<usize>> for CopyStackVec<T, N> {
40    type Output = [T];
41    fn index(&self, r: RangeTo<usize>) -> &Self::Output {
42        &self.as_slice()[r]
43    }
44}
45impl<T: Copy, const N: usize> Index<RangeToInclusive<usize>> for CopyStackVec<T, N> {
46    type Output = [T];
47    fn index(&self, r: RangeToInclusive<usize>) -> &Self::Output {
48        &self.as_slice()[r]
49    }
50}
51impl<T: Copy, const N: usize> Index<RangeInclusive<usize>> for CopyStackVec<T, N> {
52    type Output = [T];
53    fn index(&self, r: RangeInclusive<usize>) -> &Self::Output {
54        &self.as_slice()[r]
55    }
56}
57impl<T: Copy, const N: usize> Index<RangeFull> for CopyStackVec<T, N> {
58    type Output = [T];
59    fn index(&self, _: RangeFull) -> &Self::Output {
60        self.as_slice()
61    }
62}
63
64// Mutable ranges
65impl<T: Copy, const N: usize> IndexMut<usize> for CopyStackVec<T, N> {
66    fn index_mut(&mut self, i: usize) -> &mut Self::Output {
67        &mut self.as_mut_slice()[i]
68    }
69}
70impl<T: Copy, const N: usize> IndexMut<Range<usize>> for CopyStackVec<T, N> {
71    fn index_mut(&mut self, r: Range<usize>) -> &mut Self::Output {
72        &mut self.as_mut_slice()[r]
73    }
74}
75impl<T: Copy, const N: usize> IndexMut<RangeFrom<usize>> for CopyStackVec<T, N> {
76    fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut Self::Output {
77        &mut self.as_mut_slice()[r]
78    }
79}
80impl<T: Copy, const N: usize> IndexMut<RangeTo<usize>> for CopyStackVec<T, N> {
81    fn index_mut(&mut self, r: RangeTo<usize>) -> &mut Self::Output {
82        &mut self.as_mut_slice()[r]
83    }
84}
85impl<T: Copy, const N: usize> IndexMut<RangeToInclusive<usize>> for CopyStackVec<T, N> {
86    fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut Self::Output {
87        &mut self.as_mut_slice()[r]
88    }
89}
90impl<T: Copy, const N: usize> IndexMut<RangeInclusive<usize>> for CopyStackVec<T, N> {
91    fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut Self::Output {
92        &mut self.as_mut_slice()[r]
93    }
94}
95impl<T: Copy, const N: usize> IndexMut<RangeFull> for CopyStackVec<T, N> {
96    fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
97        self.as_mut_slice()
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    // Imports
104    use super::CopyStackVec;
105
106    #[test]
107    fn test_ranges() {
108        let mut v: CopyStackVec<i32, 6> = CopyStackVec::try_from(&[0, 1, 2, 3, 4][..]).unwrap();
109        assert_eq!(&v[1..3], &[1, 2]);
110        v[1..3].copy_from_slice(&[10, 20]);
111        assert_eq!(v.as_slice(), &[0, 10, 20, 3, 4]);
112    }
113
114    #[test]
115    #[should_panic]
116    fn test_oob_panics() {
117        let v: CopyStackVec<i32, 2> = CopyStackVec::default();
118        let _ = v[0];
119    }
120
121    #[test]
122    fn test_indexing_and_ranges_full_suite() {
123        let mut v: CopyStackVec<i32, 6> = CopyStackVec::try_from(&[0, 1, 2, 3, 4][..]).unwrap();
124
125        assert_eq!(v[0], 0);
126        assert_eq!(&v[1..3], &[1, 2]);
127        assert_eq!(&v[2..], &[2, 3, 4]);
128        assert_eq!(&v[..3], &[0, 1, 2]);
129        assert_eq!(&v[..=2], &[0, 1, 2]);
130        assert_eq!(&v[1..=3], &[1, 2, 3]);
131        assert_eq!(&v[..], &[0, 1, 2, 3, 4]);
132
133        v[1..3].copy_from_slice(&[10, 20]);
134        assert_eq!(v.as_slice(), &[0, 10, 20, 3, 4]);
135    }
136
137    #[test]
138    fn test_empty_ranges_work() {
139        let v: CopyStackVec<i32, 5> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
140        // Empty slices should be valid and equal to []
141        assert_eq!(&v[1..1], &[] as &[i32]);
142        assert_eq!(&v[..0], &[] as &[i32]);
143        assert_eq!(&v[3..3], &[] as &[i32]);
144    }
145
146    #[test]
147    #[should_panic]
148    #[allow(clippy::reversed_empty_ranges)]
149    fn test_inverted_range_panics() {
150        let v: CopyStackVec<i32, 3> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
151        let _ = &v[2..1];
152    }
153
154    #[test]
155    fn test_mut_inclusive_range() {
156        let mut v: CopyStackVec<i32, 6> = CopyStackVec::try_from(&[0, 1, 2, 3][..]).unwrap();
157        v[1..=2].copy_from_slice(&[9, 8]);
158        assert_eq!(v.as_slice(), &[0, 9, 8, 3]);
159    }
160
161    #[test]
162    #[should_panic]
163    fn inclusive_upper_oob_panics() {
164        let v: CopyStackVec<i32, 3> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
165        let _ = &v[..=3]; // out-of-bounds: upper bound == len
166    }
167
168    #[test]
169    #[should_panic]
170    fn inclusive_mut_upper_oob_panics() {
171        let mut v: CopyStackVec<i32, 3> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
172        let _ = &mut v[..=3]; // out-of-bounds: upper bound == len
173    }
174
175    #[test]
176    fn inclusive_single_element() {
177        let mut v: CopyStackVec<i32, 4> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
178        v[1..=1].copy_from_slice(&[99]);
179        assert_eq!(v.as_slice(), &[1, 99, 3]);
180    }
181
182    #[test]
183    fn test_index_mut_single_element() {
184        let mut v: CopyStackVec<i32, 4> = CopyStackVec::try_from(&[1, 2, 3, 4][..]).unwrap();
185
186        // Mutate a single element via `IndexMut<usize>`.
187        v[1] = 10;
188        v[3] = 40;
189
190        assert_eq!(v.as_slice(), &[1, 10, 3, 40]);
191    }
192
193    #[test]
194    fn test_index_mut_range_from() {
195        let mut v: CopyStackVec<i32, 5> = CopyStackVec::try_from(&[1, 2, 3, 4, 5][..]).unwrap();
196
197        {
198            // `IndexMut<RangeFrom<usize>>` → &mut [T]
199            let tail: &mut [i32] = &mut v[2..];
200            tail.copy_from_slice(&[30, 40, 50]);
201        }
202
203        assert_eq!(v.as_slice(), &[1, 2, 30, 40, 50]);
204    }
205
206    #[test]
207    fn test_index_mut_range_to() {
208        let mut v: CopyStackVec<i32, 5> = CopyStackVec::try_from(&[1, 2, 3, 4, 5][..]).unwrap();
209
210        {
211            // `IndexMut<RangeTo<usize>>` → &mut [T]
212            let head: &mut [i32] = &mut v[..3];
213            head.copy_from_slice(&[10, 20, 30]);
214        }
215
216        assert_eq!(v.as_slice(), &[10, 20, 30, 4, 5]);
217    }
218
219    #[test]
220    fn test_index_mut_range_full() {
221        let mut v: CopyStackVec<i32, 3> = CopyStackVec::try_from(&[1, 2, 3][..]).unwrap();
222
223        {
224            // `IndexMut<RangeFull>` → &mut [T]
225            let all: &mut [i32] = &mut v[..];
226            all.copy_from_slice(&[7, 8, 9]);
227        }
228
229        assert_eq!(v.as_slice(), &[7, 8, 9]);
230    }
231}