offset_vec/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5extern crate alloc;
6
7#[cfg(doc)]
8use alloc::{vec::Vec, string::String};
9
10use core::{
11    iter::once,
12    ops::{Bound, Deref, DerefMut, Index, IndexMut, Range, RangeBounds},
13    slice::SliceIndex,
14};
15
16mod slice;
17mod offset;
18mod vec_like;
19
20pub use slice::*;
21pub use offset::*;
22pub use vec_like::*;
23
24mod externs {
25    mod core_impls;
26}
27
28/// Packer for [`Vec`] and [`String`] etc
29///
30/// For all methods index add a `offset`
31///
32/// Create from [`Offset::offset`] or [`create`]
33///
34/// # Examples
35///
36/// ```
37/// use offset_vec::Offset;
38///
39/// let mut vec = vec![0, 1, 2, 3, 4];
40/// let mut vec1 = vec.offset_mut(2);
41///
42/// assert_eq!(vec1, [2, 3, 4]);
43/// assert_eq!(vec1[1], 3);
44///
45/// vec1[1] += 2;
46/// assert_eq!(vec, [0, 1, 2, 5, 4]);
47/// ```
48#[derive(Debug, Clone, Default)]
49pub struct OffsetVec<V: VecLike> {
50    vec: V,
51    offset: usize,
52}
53
54impl<V: VecLike> Deref for OffsetVec<V> {
55    type Target = V::Slice;
56
57    #[inline]
58    fn deref(&self) -> &Self::Target {
59        let offset = self.offset;
60        let slice = self.vec.as_slice();
61        &slice[offset..]
62    }
63}
64
65impl<V: VecLike> DerefMut for OffsetVec<V> {
66    #[inline]
67    fn deref_mut(&mut self) -> &mut Self::Target {
68        let offset = self.offset;
69        let slice_mut = self.vec.as_mut_slice();
70        &mut slice_mut[offset..]
71    }
72}
73
74impl<V, I> Index<I> for OffsetVec<V>
75where V: VecLike,
76      I: SliceIndex<V::Slice>,
77      V::Slice: Index<I>,
78{
79    type Output = <V::Slice as Index<I>>::Output;
80
81    #[track_caller]
82    fn index(&self, index: I) -> &Self::Output {
83        let slice = &**self;
84        &slice[index]
85    }
86}
87
88impl<V, I> IndexMut<I> for OffsetVec<V>
89where V: VecLike,
90      I: SliceIndex<V::Slice>,
91      V::Slice: IndexMut<I>,
92{
93    #[track_caller]
94    fn index_mut(&mut self, index: I) -> &mut Self::Output {
95        let slice = &mut **self;
96        &mut slice[index]
97    }
98}
99
100impl<V: VecLike> OffsetVec<V> {
101    #[inline]
102    pub fn origin_vec(&self) -> &V {
103        &self.vec
104    }
105
106    #[inline]
107    pub fn origin_vec_mut(&mut self) -> &mut V {
108        &mut self.vec
109    }
110
111    #[inline]
112    pub fn into_origin_vec(self) -> V {
113        self.vec
114    }
115
116    #[inline]
117    pub fn as_slice(&self) -> &V::Slice {
118        self
119    }
120
121    #[inline]
122    pub fn as_mut_slice(&mut self) -> &mut V::Slice {
123        self
124    }
125
126    pub fn iter<'a>(&'a self) -> <&'a V::Slice as IntoIterator>::IntoIter
127    where &'a V::Slice: IntoIterator
128    {
129        self.as_slice().into_iter()
130    }
131
132    pub fn iter_mut<'a>(&'a mut self) -> <&'a V::Slice as IntoIterator>::IntoIter
133    where &'a V::Slice: IntoIterator
134    {
135        self.as_mut_slice().into_iter()
136    }
137
138    #[inline]
139    pub fn is_empty(&self) -> bool {
140        self.len() == 0
141    }
142
143    #[inline]
144    pub fn len(&self) -> usize {
145        self.vec.len() - self.offset
146    }
147
148    #[inline]
149    pub fn capacity(&self) -> usize {
150        self.vec.capacity() - self.offset
151    }
152
153    pub fn reserve(&mut self, additional: usize) {
154        self.vec.reserve(additional);
155    }
156
157    pub fn reserve_exact(&mut self, additional: usize) {
158        self.vec.reserve_exact(additional);
159    }
160
161    pub fn shrink_to_fit(&mut self) {
162        self.vec.shrink_to_fit();
163    }
164
165    pub fn shrink_to(&mut self, min_capacity: usize) {
166        self.vec.shrink_to(min_capacity);
167    }
168
169
170    pub fn offset(&self) -> usize {
171        self.offset
172    }
173
174    pub fn push(&mut self, value: V::Elem) {
175        self.vec.push(value);
176    }
177
178    pub fn pop(&mut self) -> Option<V::Elem> {
179        if self.is_empty() {
180            return None;
181        }
182
183        self.vec.pop()
184    }
185
186    #[track_caller]
187    pub fn remove(&mut self, index: usize) -> V::Elem {
188        let len = self.len();
189        if index > len {
190            index_out_of_range(index, self.offset, len)
191        }
192        self.vec.remove(index + self.offset)
193    }
194
195    #[track_caller]
196    pub fn insert(&mut self, index: usize, elem: V::Elem) {
197        let len = self.len();
198        if index > len {
199            index_out_of_range(index, self.offset, len)
200        }
201        self.vec.insert(index + self.offset, elem)
202    }
203
204    pub fn truncate(&mut self, len: usize) {
205        self.vec.truncate(len + self.offset);
206    }
207
208    pub fn append(&mut self, other: &mut V::Collection) {
209        self.vec.append(other);
210    }
211
212    pub fn clear(&mut self) {
213        self.truncate(self.offset);
214    }
215
216    #[track_caller]
217    fn map_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
218        let start = match range.start_bound() {
219            Bound::Included(&n) => n,
220            Bound::Excluded(&n) => n.checked_add(1).expect("start range overflow"),
221            Bound::Unbounded => 0,
222        };
223        let end = match range.end_bound() {
224            Bound::Included(&n) => n.checked_add(1).expect("end range overflow"),
225            Bound::Excluded(&n) => n,
226            Bound::Unbounded => self.len(),
227        };
228        if start > end {
229            #[cold]
230            #[track_caller]
231            #[inline(never)]
232            fn fail(index: usize, end: usize) -> ! {
233                panic!("range index starts at {index} but ends at {end}");
234            }
235            fail(start, end)
236        }
237        if end > self.len() {
238            #[cold]
239            #[track_caller]
240            #[inline(never)]
241            fn fail(index: usize, len: usize) -> ! {
242                panic!("range end index {index} out of range for slice of length {len}");
243            }
244            fail(end, self.len())
245        }
246        let offset = self.offset;
247        Range { start: start+offset, end: end+offset }
248    }
249
250    #[track_caller]
251    pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> V::Drain<'_> {
252        self.vec.drain(self.map_range(range))
253    }
254
255    #[track_caller]
256    #[must_use = "use `.truncate()` if you don't need the other half"]
257    pub fn split_off(&mut self, at: usize) -> V::Collection {
258        let len = self.len();
259        if at > len {
260            index_out_of_range(at, self.offset, len)
261        }
262        self.vec.split_off(at + self.offset)
263    }
264
265    pub fn resize(&mut self, new_len: usize, value: V::Elem)
266    where V::Elem: Clone,
267    {
268        self.vec.resize(new_len+self.offset, value);
269    }
270
271    pub fn resize_with<F>(&mut self, new_len: usize, f: F)
272    where F: FnMut() -> V::Elem,
273    {
274        self.vec.resize_with(new_len+self.offset, f);
275    }
276}
277
278impl<V: VecLikeSolid> OffsetVec<V> {
279    pub fn retain<F: FnMut(&V::Elem) -> bool>(&mut self, f: F) {
280        self.vec.retain(f);
281    }
282
283    pub fn retain_mut<F: FnMut(&mut V::Elem) -> bool>(&mut self, f: F) {
284        self.vec.retain_mut(f);
285    }
286
287    #[track_caller]
288    pub fn swap_remove(&mut self, index: usize) -> V::Elem {
289        let len = self.len();
290        if index > len {
291            index_out_of_range(index, self.offset, len)
292        }
293        self.vec.swap_remove(index + self.offset)
294    }
295
296    pub fn pop_if<F>(&mut self, predicate: F) -> Option<V::Elem>
297    where F: FnOnce(&mut V::Elem) -> bool,
298    {
299        if self.is_empty() {
300            return None;
301        }
302
303        self.vec.pop_if(predicate)
304    }
305}
306
307impl<V: VecLikeAbstract> OffsetVec<V> {
308    pub fn retain_val<F: FnMut(V::Elem) -> bool>(&mut self, f: F) {
309        self.vec.retain(f);
310    }
311}
312
313impl<V: VecLike<Slice = str>> OffsetVec<V> {
314    #[inline]
315    pub fn as_str(&self) -> &str {
316        self
317    }
318
319    #[inline]
320    pub fn as_mut_str(&mut self) -> &mut str {
321        self
322    }
323
324    pub fn push_str<'a>(&mut self, s: &'a str)
325    where V::Collection: Extend<&'a str>,
326    {
327        self.vec.as_mut_collection().extend(once(s));
328    }
329}
330
331#[cold]
332#[track_caller]
333#[inline(never)]
334fn index_out_of_range(index: usize, offset: usize, len: usize) -> ! {
335    panic!("offset index ({index} -> {}) out of length (is {len} -> {})",
336           index+offset,
337           len+offset);
338}