1#![allow(clippy::unwrap_used)]
7#![allow(clippy::expect_used)]
8#![allow(clippy::indexing_slicing)]
9#![allow(clippy::panic)]
10
11use super::*;
12use crate::ule::*;
13use alloc::boxed::Box;
14use alloc::vec::Vec;
15use core::any;
16use core::convert::TryInto;
17use core::marker::PhantomData;
18use core::ops::Deref;
19use core::ops::Range;
20use core::{fmt, ptr, slice};
21
22use super::components::LENGTH_WIDTH;
23use super::components::MAX_INDEX;
24use super::components::MAX_LENGTH;
25use super::components::METADATA_WIDTH;
26
27pub struct VarZeroVecOwned<T: ?Sized, F = Index16> {
34 marker: PhantomData<(Box<T>, F)>,
35 entire_slice: Vec<u8>,
37}
38
39impl<T: ?Sized, F> Clone for VarZeroVecOwned<T, F> {
40 fn clone(&self) -> Self {
41 VarZeroVecOwned {
42 marker: self.marker,
43 entire_slice: self.entire_slice.clone(),
44 }
45 }
46}
47
48#[derive(PartialEq)]
50enum ShiftType {
51 Insert,
52 Replace,
53 Remove,
54}
55
56impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Deref for VarZeroVecOwned<T, F> {
57 type Target = VarZeroSlice<T, F>;
58 fn deref(&self) -> &VarZeroSlice<T, F> {
59 self.as_slice()
60 }
61}
62
63impl<T: VarULE + ?Sized, F> VarZeroVecOwned<T, F> {
64 pub fn new() -> Self {
66 Self {
67 marker: PhantomData,
68 entire_slice: Vec::new(),
69 }
70 }
71}
72
73impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> {
74 pub fn from_slice(slice: &VarZeroSlice<T, F>) -> Self {
76 Self {
77 marker: PhantomData,
78 entire_slice: slice.as_bytes().into(),
79 }
80 }
81
82 pub fn try_from_elements<A>(elements: &[A]) -> Result<Self, &'static str>
84 where
85 A: EncodeAsVarULE<T>,
86 {
87 Ok(if elements.is_empty() {
88 Self::from_slice(VarZeroSlice::new_empty())
89 } else {
90 Self {
91 marker: PhantomData,
92 entire_slice: components::get_serializable_bytes_non_empty::<T, A, F>(elements)
94 .ok_or(
95 "Attempted to build VarZeroVec out of elements that \
96 cumulatively are larger than a u32 in size",
97 )?,
98 }
99 })
100 }
101
102 pub fn as_slice(&self) -> &VarZeroSlice<T, F> {
104 let slice: &[u8] = &self.entire_slice;
105 unsafe {
106 VarZeroSlice::from_byte_slice_unchecked(slice)
108 }
109 }
110
111 pub(crate) fn with_capacity(capacity: usize) -> Self {
115 Self {
116 marker: PhantomData,
117 entire_slice: Vec::with_capacity(capacity * (F::INDEX_WIDTH + 4)),
118 }
119 }
120
121 pub(crate) fn reserve(&mut self, capacity: usize) {
125 self.entire_slice.reserve(capacity * (F::INDEX_WIDTH + 4))
126 }
127
128 unsafe fn element_position_unchecked(&self, idx: usize) -> usize {
135 let len = self.len();
136 let out = if idx == len {
137 self.entire_slice.len() - LENGTH_WIDTH - METADATA_WIDTH - (F::INDEX_WIDTH * len)
138 } else {
139 F::rawbytes_to_usize(*self.index_data(idx))
140 };
141 debug_assert!(
142 out + LENGTH_WIDTH + METADATA_WIDTH + len * F::INDEX_WIDTH <= self.entire_slice.len()
143 );
144 out
145 }
146
147 unsafe fn element_range_unchecked(&self, idx: usize) -> core::ops::Range<usize> {
152 let start = self.element_position_unchecked(idx);
153 let end = self.element_position_unchecked(idx + 1);
154 debug_assert!(start <= end, "{start} > {end}");
155 start..end
156 }
157
158 unsafe fn set_len(&mut self, len: usize) {
163 assert!(len <= MAX_LENGTH);
164 let len_bytes = len.to_le_bytes();
165 self.entire_slice[0..LENGTH_WIDTH].copy_from_slice(&len_bytes[0..LENGTH_WIDTH]);
166 assert_eq!(len_bytes[LENGTH_WIDTH..].iter().sum::<u8>(), 0);
168 }
169
170 fn index_range(index: usize) -> Range<usize> {
171 let pos = LENGTH_WIDTH + METADATA_WIDTH + F::INDEX_WIDTH * index;
172 pos..pos + F::INDEX_WIDTH
173 }
174
175 unsafe fn index_data(&self, index: usize) -> &F::RawBytes {
180 &F::RawBytes::from_byte_slice_unchecked(&self.entire_slice[Self::index_range(index)])[0]
181 }
182
183 unsafe fn index_data_mut(&mut self, index: usize) -> &mut F::RawBytes {
189 let ptr = self.entire_slice.as_mut_ptr();
190 let range = Self::index_range(index);
191
192 let data = slice::from_raw_parts_mut(ptr.add(range.start), F::INDEX_WIDTH);
196
197 &mut F::rawbytes_from_byte_slice_unchecked_mut(data)[0]
198 }
199
200 unsafe fn shift_indices(&mut self, starting_index: usize, amount: i32) {
206 let len = self.len();
207 let indices = F::rawbytes_from_byte_slice_unchecked_mut(
208 &mut self.entire_slice[LENGTH_WIDTH + METADATA_WIDTH
209 ..LENGTH_WIDTH + METADATA_WIDTH + F::INDEX_WIDTH * len],
210 );
211 for idx in &mut indices[starting_index..] {
212 let mut new_idx = F::rawbytes_to_usize(*idx);
213 if amount > 0 {
214 new_idx = new_idx.checked_add(amount.try_into().unwrap()).unwrap();
215 } else {
216 new_idx = new_idx.checked_sub((-amount).try_into().unwrap()).unwrap();
217 }
218 *idx = F::usize_to_rawbytes(new_idx);
219 }
220 }
221
222 pub fn as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F> {
227 self.as_slice().into()
228 }
229
230 pub fn clear(&mut self) {
232 self.entire_slice.clear()
233 }
234
235 #[inline]
237 pub fn into_bytes(self) -> Vec<u8> {
238 self.entire_slice
239 }
240
241 unsafe fn shift(&mut self, index: usize, new_size: usize, shift_type: ShiftType) -> &mut [u8] {
249 let len = self.len();
258 let slice_len = self.entire_slice.len();
259
260 let prev_element = match shift_type {
261 ShiftType::Insert => {
262 let pos = self.element_position_unchecked(index);
263 pos..pos
266 }
267 _ => self.element_range_unchecked(index),
268 };
269
270 let index_shift: i64 = match shift_type {
272 ShiftType::Insert => F::INDEX_WIDTH as i64,
273 ShiftType::Replace => 0,
274 ShiftType::Remove => -(F::INDEX_WIDTH as i64),
275 };
276 let shift: i64 =
278 new_size as i64 - (prev_element.end - prev_element.start) as i64 + index_shift;
279 let new_slice_len = slice_len.wrapping_add(shift as usize);
280 if shift > 0 {
281 if new_slice_len > F::MAX_VALUE as usize {
282 panic!(
283 "Attempted to grow VarZeroVec to an encoded size that does not fit within the length size used by {}",
284 any::type_name::<F>()
285 );
286 }
287 self.entire_slice.resize(new_slice_len, 0);
288 }
289
290 {
292 let slice_range = self.entire_slice.as_mut_ptr_range();
295 let old_slice_end = slice_range.start.add(slice_len);
296 let data_start = slice_range
297 .start
298 .add(LENGTH_WIDTH + METADATA_WIDTH + len * F::INDEX_WIDTH);
299 let prev_element_p =
300 data_start.add(prev_element.start)..data_start.add(prev_element.end);
301
302 let index_range = {
307 let index_start = slice_range
308 .start
309 .add(LENGTH_WIDTH + METADATA_WIDTH + F::INDEX_WIDTH * index);
310 index_start..index_start.add(F::INDEX_WIDTH)
311 };
312
313 unsafe fn shift_bytes(block: Range<*const u8>, to: *mut u8) {
314 debug_assert!(block.end >= block.start);
315 ptr::copy(block.start, to, block.end.offset_from(block.start) as usize);
316 }
317
318 if shift_type == ShiftType::Remove {
319 shift_bytes(index_range.end..prev_element_p.start, index_range.start);
321 }
322
323 shift_bytes(
325 prev_element_p.end..old_slice_end,
326 prev_element_p
327 .start
328 .offset((new_size as i64 + index_shift) as isize),
329 );
330
331 let first_affected_index = match shift_type {
332 ShiftType::Insert => {
333 shift_bytes(index_range.start..prev_element_p.start, index_range.end);
335
336 *self.index_data_mut(index) = F::usize_to_rawbytes(prev_element.start);
337 self.set_len(len + 1);
338 index + 1
339 }
340 ShiftType::Remove => {
341 self.set_len(len - 1);
342 index
343 }
344 ShiftType::Replace => index + 1,
345 };
346 self.entire_slice.set_len(new_slice_len);
350
351 self.shift_indices(first_affected_index, (shift - index_shift) as i32);
353 };
354
355 debug_assert!(self.verify_integrity());
356
357 let element_pos = LENGTH_WIDTH
359 + METADATA_WIDTH
360 + self.len() * F::INDEX_WIDTH
361 + self.element_position_unchecked(index);
362 &mut self.entire_slice[element_pos..element_pos + new_size]
363 }
364
365 fn verify_integrity(&self) -> bool {
371 if self.is_empty() && !self.entire_slice.is_empty() {
372 return false;
373 }
374 let slice_len = self.entire_slice.len();
375 match slice_len {
376 0 => return true,
377 1..=3 => return false,
378 _ => (),
379 }
380 let len = unsafe {
381 RawBytesULE::<LENGTH_WIDTH>::from_byte_slice_unchecked(
382 &self.entire_slice[..LENGTH_WIDTH],
383 )[0]
384 .as_unsigned_int()
385 };
386 if len == 0 {
387 return false;
389 }
390 if slice_len < LENGTH_WIDTH + METADATA_WIDTH + len as usize * F::INDEX_WIDTH {
391 return false;
393 }
394 let data_len =
395 self.entire_slice.len() - LENGTH_WIDTH - METADATA_WIDTH - len as usize * F::INDEX_WIDTH;
396 if data_len > MAX_INDEX {
397 return false;
399 }
400
401 let indices = unsafe {
403 F::RawBytes::from_byte_slice_unchecked(
404 &self.entire_slice[LENGTH_WIDTH + METADATA_WIDTH
405 ..LENGTH_WIDTH + METADATA_WIDTH + len as usize * F::INDEX_WIDTH],
406 )
407 };
408 for idx in indices {
409 if F::rawbytes_to_usize(*idx) > data_len {
410 return false;
412 }
413 }
414 for window in indices.windows(2) {
415 if F::rawbytes_to_usize(window[0]) > F::rawbytes_to_usize(window[1]) {
416 return false;
418 }
419 }
420 true
421 }
422
423 pub fn push<A: EncodeAsVarULE<T> + ?Sized>(&mut self, element: &A) {
425 self.insert(self.len(), element)
426 }
427
428 pub fn insert<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) {
430 let len = self.len();
431 if index > len {
432 panic!("Called out-of-bounds insert() on VarZeroVec, index {index} len {len}");
433 }
434
435 let value_len = element.encode_var_ule_len();
436
437 if len == 0 {
438 let header_len = LENGTH_WIDTH + METADATA_WIDTH + F::INDEX_WIDTH;
439 let cap = header_len + value_len;
440 self.entire_slice.resize(cap, 0);
441 self.entire_slice[0] = 1; element.encode_var_ule_write(&mut self.entire_slice[header_len..]);
443 return;
444 }
445
446 assert!(value_len < MAX_INDEX);
447 unsafe {
448 let place = self.shift(index, value_len, ShiftType::Insert);
449 element.encode_var_ule_write(place);
450 }
451 }
452
453 pub fn remove(&mut self, index: usize) {
455 let len = self.len();
456 if index >= len {
457 panic!("Called out-of-bounds remove() on VarZeroVec, index {index} len {len}");
458 }
459 if len == 1 {
460 self.entire_slice.clear();
462 return;
463 }
464 unsafe {
465 self.shift(index, 0, ShiftType::Remove);
466 }
467 }
468
469 pub fn replace<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) {
471 let len = self.len();
472 if index >= len {
473 panic!("Called out-of-bounds replace() on VarZeroVec, index {index} len {len}");
474 }
475
476 let value_len = element.encode_var_ule_len();
477
478 assert!(value_len < MAX_INDEX);
479 unsafe {
480 let place = self.shift(index, value_len, ShiftType::Replace);
481 element.encode_var_ule_write(place);
482 }
483 }
484}
485
486impl<T: VarULE + ?Sized, F: VarZeroVecFormat> fmt::Debug for VarZeroVecOwned<T, F>
487where
488 T: fmt::Debug,
489{
490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491 VarZeroSlice::fmt(self, f)
492 }
493}
494
495impl<T: VarULE + ?Sized, F> Default for VarZeroVecOwned<T, F> {
496 fn default() -> Self {
497 Self::new()
498 }
499}
500
501impl<T, A, F> PartialEq<&'_ [A]> for VarZeroVecOwned<T, F>
502where
503 T: VarULE + ?Sized,
504 T: PartialEq,
505 A: AsRef<T>,
506 F: VarZeroVecFormat,
507{
508 #[inline]
509 fn eq(&self, other: &&[A]) -> bool {
510 self.iter().eq(other.iter().map(|t| t.as_ref()))
511 }
512}
513
514impl<'a, T: ?Sized + VarULE, F: VarZeroVecFormat> From<&'a VarZeroSlice<T, F>>
515 for VarZeroVecOwned<T, F>
516{
517 fn from(other: &'a VarZeroSlice<T, F>) -> Self {
518 Self::from_slice(other)
519 }
520}
521
522#[cfg(test)]
523mod test {
524 use super::VarZeroVecOwned;
525 #[test]
526 fn test_insert_integrity() {
527 let mut items: Vec<String> = Vec::new();
528 let mut zerovec = VarZeroVecOwned::<str>::new();
529
530 items.insert(0, "1234567890".into());
532 zerovec.insert(0, "1234567890");
533 assert_eq!(zerovec, &*items);
534
535 zerovec.insert(1, "foo3");
536 items.insert(1, "foo3".into());
537 assert_eq!(zerovec, &*items);
538
539 items.insert(items.len(), "qwertyuiop".into());
541 zerovec.insert(zerovec.len(), "qwertyuiop");
542 assert_eq!(zerovec, &*items);
543
544 items.insert(0, "asdfghjkl;".into());
545 zerovec.insert(0, "asdfghjkl;");
546 assert_eq!(zerovec, &*items);
547
548 items.insert(2, "".into());
549 zerovec.insert(2, "");
550 assert_eq!(zerovec, &*items);
551 }
552
553 #[test]
554 fn test_empty_inserts() {
556 let mut items: Vec<String> = Vec::new();
557 let mut zerovec = VarZeroVecOwned::<str>::new();
558
559 items.insert(0, "".into());
561 zerovec.insert(0, "");
562 assert_eq!(zerovec, &*items);
563
564 items.insert(0, "".into());
565 zerovec.insert(0, "");
566 assert_eq!(zerovec, &*items);
567
568 items.insert(0, "1234567890".into());
569 zerovec.insert(0, "1234567890");
570 assert_eq!(zerovec, &*items);
571
572 items.insert(0, "".into());
573 zerovec.insert(0, "");
574 assert_eq!(zerovec, &*items);
575 }
576
577 #[test]
578 fn test_small_insert_integrity() {
579 let mut items: Vec<String> = Vec::new();
582 let mut zerovec = VarZeroVecOwned::<str>::new();
583
584 items.insert(0, "abc".into());
586 zerovec.insert(0, "abc");
587 assert_eq!(zerovec, &*items);
588
589 zerovec.insert(1, "def");
590 items.insert(1, "def".into());
591 assert_eq!(zerovec, &*items);
592 }
593
594 #[test]
595 #[should_panic]
596 fn test_insert_past_end() {
597 VarZeroVecOwned::<str>::new().insert(1, "");
598 }
599
600 #[test]
601 fn test_remove_integrity() {
602 let mut items: Vec<&str> = vec!["apples", "bananas", "eeples", "", "baneenees", "five", ""];
603 let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&items).unwrap();
604
605 for index in [0, 2, 4, 0, 1, 1, 0] {
606 items.remove(index);
607 zerovec.remove(index);
608 assert_eq!(zerovec, &*items, "index {}, len {}", index, items.len());
609 }
610 }
611
612 #[test]
613 fn test_removing_last_element_clears() {
614 let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&["buy some apples"]).unwrap();
615 assert!(!zerovec.as_bytes().is_empty());
616 zerovec.remove(0);
617 assert!(zerovec.as_bytes().is_empty());
618 }
619
620 #[test]
621 #[should_panic]
622 fn test_remove_past_end() {
623 VarZeroVecOwned::<str>::new().remove(0);
624 }
625
626 #[test]
627 fn test_replace_integrity() {
628 let mut items: Vec<&str> = vec!["apples", "bananas", "eeples", "", "baneenees", "five", ""];
629 let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&items).unwrap();
630
631 items[0] = "blablah";
633 zerovec.replace(0, "blablah");
634 assert_eq!(zerovec, &*items);
635
636 items[1] = "twily";
638 zerovec.replace(1, "twily");
639 assert_eq!(zerovec, &*items);
640
641 items[3] = "aoeuidhtns";
643 zerovec.replace(3, "aoeuidhtns");
644 assert_eq!(zerovec, &*items);
645
646 items[6] = "0123456789";
648 zerovec.replace(6, "0123456789");
649 assert_eq!(zerovec, &*items);
650
651 items[2] = "";
653 zerovec.replace(2, "");
654 assert_eq!(zerovec, &*items);
655 }
656
657 #[test]
658 #[should_panic]
659 fn test_replace_past_end() {
660 VarZeroVecOwned::<str>::new().replace(0, "");
661 }
662}