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#[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}