libdiffsitter/
neg_idx_vec.rs1use std::ops::{Index, IndexMut};
6
7#[derive(Debug, Clone, Eq, PartialEq)]
18pub struct NegIdxVec<T> {
19 pub data: Vec<T>,
21
22 len: usize,
25}
26
27#[allow(dead_code)]
28impl<T> NegIdxVec<T> {
29 pub fn new<F>(len: usize, f: F) -> Self
39 where
40 F: FnMut() -> T,
41 {
42 let mut v = Vec::new();
43 v.resize_with(len, f);
44
45 Self { data: v, len }
46 }
47
48 pub fn reserve(&mut self, additional: usize) {
50 self.data.reserve(additional);
51 }
52
53 pub fn reserve_exact(&mut self, additional: usize) {
57 self.data.reserve_exact(additional);
58 }
59
60 pub fn capacity(&self) -> usize {
63 self.data.capacity()
64 }
65
66 fn idx_helper(&self, idx: i32) -> usize {
74 let len: i32 = self.len.try_into().unwrap();
75
76 let final_index = if idx >= 0 {
77 idx.try_into().unwrap()
78 } else {
79 let offset_idx = len + idx;
80 debug_assert!(offset_idx >= 0);
81 offset_idx.try_into().unwrap()
82 };
83 debug_assert!(final_index < len.try_into().unwrap());
84 final_index
85 }
86
87 #[must_use]
89 pub fn len(&self) -> usize {
90 self.data.len()
91 }
92
93 #[must_use]
95 pub fn is_empty(&self) -> bool {
96 self.data.is_empty()
97 }
98}
99
100impl<T> From<Vec<T>> for NegIdxVec<T> {
101 fn from(v: Vec<T>) -> Self {
102 let len = v.len();
104 Self { data: v, len }
105 }
106}
107
108impl<T> FromIterator<T> for NegIdxVec<T> {
109 fn from_iter<Iter: IntoIterator<Item = T>>(iter: Iter) -> Self {
110 let data = Vec::from_iter(iter);
111 let len = data.len();
112 Self { data, len }
113 }
114}
115
116impl<T: Clone> From<&[T]> for NegIdxVec<T> {
117 fn from(value: &[T]) -> Self {
118 let v: Vec<T> = Vec::from(value);
119 let len = v.len();
120 Self { data: v, len }
121 }
122}
123
124impl<T> Default for NegIdxVec<T> {
125 fn default() -> Self {
126 Self {
127 data: Vec::new(),
128 len: 0,
129 }
130 }
131}
132
133impl<T> Index<i32> for NegIdxVec<T> {
134 type Output = T;
135
136 fn index(&self, idx: i32) -> &<Self as std::ops::Index<i32>>::Output {
137 &self.data[self.idx_helper(idx)]
138 }
139}
140
141impl<T> IndexMut<i32> for NegIdxVec<T> {
142 fn index_mut(&mut self, idx: i32) -> &mut <Self as std::ops::Index<i32>>::Output {
143 let offset_idx = self.idx_helper(idx);
144 &mut self.data[offset_idx]
145 }
146}
147
148impl<T> IntoIterator for NegIdxVec<T> {
149 type Item = T;
150 type IntoIter = std::vec::IntoIter<Self::Item>;
151
152 fn into_iter(self) -> Self::IntoIter {
153 self.data.into_iter()
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160 use pretty_assertions::assert_eq;
161 use rstest::rstest;
162
163 fn test_vector() -> Vec<u32> {
165 (0..100).collect()
166 }
167
168 #[test]
169 fn test_negative_indices() {
170 let vec = test_vector();
171 let neg_vec = NegIdxVec::<u32>::from(vec.clone());
172
173 for (idx, &elem) in vec.iter().rev().enumerate() {
174 assert_eq!(elem, neg_vec[-(idx as i32 + 1)]);
175 }
176 }
177
178 #[test]
179 fn test_positive_indices() {
180 let vec = test_vector();
181 let neg_vec = NegIdxVec::<u32>::from(vec.clone());
182
183 for (idx, &elem) in vec.iter().enumerate() {
184 assert_eq!(elem, neg_vec[idx as i32]);
185 }
186 }
187
188 #[test]
189 #[should_panic]
190 fn test_positive_overflow() {
191 let vec = NegIdxVec::<u32>::from(test_vector());
192 let _ = vec[vec.len() as i32 + 1];
193 }
194
195 #[test]
196 fn test_is_empty() {
197 {
198 let vec = NegIdxVec::<u8>::default();
199 assert!(vec.is_empty());
200 assert_eq!(vec.len(), 0);
201 }
202 {
203 let vec = NegIdxVec::<u8>::from(vec![0, 1, 2, 3]);
204 assert!(!vec.is_empty());
205 assert_eq!(vec.len(), 4);
206 }
207 }
208
209 #[test]
210 #[should_panic]
211 fn test_negative_overflow() {
212 let vec = NegIdxVec::<u32>::from(test_vector());
213 let idx = (vec.len() as i32) * -2;
214 let _ = vec[idx];
215 }
216
217 #[rstest]
218 #[case(1)]
219 #[case(2)]
220 #[case(10)]
221 fn test_create_new_with_size(#[case] size: usize) {
222 let vec = NegIdxVec::<u32>::new(size, Default::default);
223 assert_eq!(vec.len(), size);
224 }
225
226 #[rstest]
227 #[case(1)]
228 #[case(10)]
229 #[case(200)]
230 fn test_reserve_inexact(#[case] additional_elements: usize) {
231 let mut vec = NegIdxVec::<u8>::default();
232 assert_eq!(vec.len(), 0);
233 vec.reserve(additional_elements);
234 assert!(vec.capacity() >= additional_elements);
235 }
236
237 #[test]
238 fn test_create_default() {
239 let vec = NegIdxVec::<u8>::default();
240 assert_eq!(vec.len(), 0);
241 assert!(vec.is_empty());
242 }
243
244 #[test]
245 fn test_into_iter() {
246 let source_vec: Vec<i32> = vec![0, 1, 2, 3, 10, 49];
247 let neg_idx_vec: NegIdxVec<i32> = NegIdxVec::from(&source_vec[..]);
248 let collected_vec: Vec<i32> = neg_idx_vec.into_iter().collect();
249 assert_eq!(source_vec, collected_vec);
250 }
251
252 #[test]
253 fn test_from_iter() {
254 let source_vec: Vec<i32> = vec![0, 1, 2, 3, 10, 49];
255 let neg_idx_vec = NegIdxVec::from_iter(source_vec.clone().into_iter());
256 let extracted_vec: Vec<i32> = neg_idx_vec.into_iter().collect();
257 assert_eq!(source_vec, extracted_vec);
258 }
259}