hvec/lib.rs
1//! In memory of Anna Harren, who coined the term
2//! [turbofish](https://turbo.fish/) - which you'll see a lot of
3//! if you use this crate.
4//!
5//! The main purpose of this crate is the `HarrenVec` type -
6//! a [`Vec`]-like data structure that can store items
7//! of different types and sizes from each other.
8//!
9//! Values of any type can be stored, and they are
10//! stored contiguous in memory like a normal [`Vec`] would.
11//!
12//! The intended use case for this data structure is
13//! efficiently packing structs with large optional fields,
14//! while avoiding [`Box`]-ing those values.
15//!
16//! It supports values with a [`Drop`] implementation by default.
17//!
18//! However, if you include the `no_drop` feature, then
19//! dropping the `HarrenVec` will _not_ call the destructors of
20//! the contents. Instead you should use the
21//! [`HarrenVec::into_iter`] method to ensure you are consuming
22//! and dropping values correctly. If the values do not have
23//! destructors, this is not necessary.
24//!
25//! # Examples
26//! ```
27//! use hvec::HarrenVec;
28//!
29//! struct SmallMessage {
30//! id: usize,
31//! has_extra: bool,
32//! }
33//!
34//! struct LargeExtraField {
35//! data: [[f64; 4]; 4],
36//! }
37//!
38//! let mut messages = HarrenVec::new();
39//! messages.push(SmallMessage { id: 0, has_extra: false });
40//! messages.push(SmallMessage { id: 1, has_extra: true });
41//! messages.push(LargeExtraField { data: [[0.; 4]; 4] });
42//! messages.push(SmallMessage { id: 2, has_extra: false });
43//!
44//! let mut iter = messages.into_iter();
45//! while let Some(message) = iter.next::<SmallMessage>() {
46//! println!("id = {}", message.id);
47//! if message.has_extra {
48//! let extra = iter.next::<LargeExtraField>().unwrap();
49//! println!("extra data = {:?}", extra.data);
50//! }
51//! }
52//!
53//! // Output:
54//! // id = 0
55//! // id = 1
56//! // extra data = [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]
57//! // id = 2
58//! ```
59
60use std::any::TypeId;
61use std::mem::MaybeUninit;
62
63#[cfg(not(feature = "no_drop"))]
64use std::collections::HashMap;
65
66#[cfg(not(feature = "no_drop"))]
67fn generic_drop<T>(p: *const ()) {
68 let p = p as *const T;
69 let _ = unsafe { p.read() };
70}
71
72#[cfg(not(feature = "no_drop"))]
73fn drop_fn_ptr<T>() -> *const () {
74 let f: fn(*const ()) = generic_drop::<T>;
75 f as _
76}
77
78/// A [`Vec`]-like data structure that can store items
79/// of different types and sizes from each other.
80///
81/// Values of any type can be stored, and they are
82/// stored contiguous in memory like a normal [`Vec`] would.
83///
84/// The intended use case for this data structure is
85/// efficiently packing structs with large optional fields,
86/// while avoiding [`Box`]-ing those values.
87///
88/// It supports values with a [`Drop`] implementation by default.
89///
90/// However, if you include the `no_drop` feature, then
91/// dropping the `HarrenVec` will _not_ call the destructors of
92/// the contents. Instead you should use the
93/// [`HarrenVec::into_iter`] method to ensure you are consuming
94/// and dropping values correctly. If the values do not have
95/// destructors, this is not necessary.
96///
97/// # Examples
98/// ```
99/// use hvec::HarrenVec;
100///
101/// struct SmallMessage {
102/// id: usize,
103/// has_extra: bool,
104/// }
105///
106/// struct LargeExtraField {
107/// data: [[f64; 4]; 4],
108/// }
109///
110/// let mut messages = HarrenVec::new();
111/// messages.push(SmallMessage { id: 0, has_extra: false });
112/// messages.push(SmallMessage { id: 1, has_extra: true });
113/// messages.push(LargeExtraField { data: [[0.; 4]; 4] });
114/// messages.push(SmallMessage { id: 2, has_extra: false });
115///
116/// let mut iter = messages.into_iter();
117/// while let Some(message) = iter.next::<SmallMessage>() {
118/// println!("id = {}", message.id);
119/// if message.has_extra {
120/// let extra = iter.next::<LargeExtraField>().unwrap();
121/// println!("extra data = {:?}", extra.data);
122/// }
123/// }
124///
125/// // Output:
126/// // id = 0
127/// // id = 1
128/// // extra data = [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]
129/// // id = 2
130/// ```
131#[derive(Debug, Clone)]
132pub struct HarrenVec {
133 types: Vec<TypeId>,
134 indices: Vec<usize>,
135 backing: Vec<u8>,
136 max_align: usize,
137
138 #[cfg(not(feature = "no_drop"))]
139 destructors: HashMap<TypeId, *const ()>,
140}
141
142impl Default for HarrenVec {
143 fn default() -> Self {
144 HarrenVec {
145 types: Default::default(),
146 indices: Default::default(),
147 backing: Default::default(),
148 max_align: 1,
149
150 #[cfg(not(feature = "no_drop"))]
151 destructors: HashMap::default(),
152 }
153 }
154}
155
156/// Type alias for [`HarrenVec`].
157pub type HVec = HarrenVec;
158
159impl HarrenVec {
160 /// Constructs a new empty [`HarrenVec`].
161 ///
162 /// # Examples
163 /// ```
164 /// # use hvec::HarrenVec;
165 /// let mut list = HarrenVec::new();
166 /// ```
167 pub fn new() -> Self {
168 Self::default()
169 }
170
171 /// Constructs a new empty [`HarrenVec`] with at least the
172 /// specified capacity in items and bytes.
173 ///
174 /// The `HarrenVec` stores the types of the data separately
175 /// from the data. In practice, it will re-allocate if
176 /// either of these capacities are exceeded.
177 ///
178 /// # Examples
179 /// ```
180 /// # use hvec::HarrenVec;
181 /// let mut list = HarrenVec::with_capacity(4, 64);
182 /// assert!(list.item_capacity() >= 4);
183 /// assert!(list.byte_capacity() >= 64);
184 /// ```
185 pub fn with_capacity(items: usize, bytes: usize) -> Self {
186 HarrenVec {
187 types: Vec::with_capacity(items),
188 indices: Vec::with_capacity(items),
189 backing: Vec::with_capacity(bytes),
190 max_align: 1,
191
192 #[cfg(not(feature = "no_drop"))]
193 destructors: HashMap::default(),
194 }
195 }
196
197 #[cfg(not(feature = "no_drop"))]
198 fn register_destructor<T: 'static>(&mut self) {
199 let type_id = TypeId::of::<T>();
200 let drop_fn_p = drop_fn_ptr::<T>();
201 self.destructors.entry(type_id).or_insert(drop_fn_p);
202 }
203
204 #[cfg(not(feature = "no_drop"))]
205 fn run_destructor(&self, type_id: TypeId, ptr: *const ()) {
206 let drop_fn_p = self.destructors[&type_id];
207 let drop_fn: fn(*const ()) = unsafe { std::mem::transmute(drop_fn_p) };
208 drop_fn(ptr);
209 }
210
211 /// Reserve capacity for at least `items` more items and
212 /// `bytes` more bytes.
213 pub fn reserve(&mut self, items: usize, bytes: usize) {
214 self.types.reserve(items);
215 self.indices.reserve(items);
216 self.backing.reserve(bytes);
217 }
218
219 /// Reserve capacity for at least `items` more items and
220 /// `bytes` more bytes. (Attempts to reserve the minimum
221 /// possible, but this is not guaranteed.)
222 pub fn reserve_exact(&mut self, items: usize, bytes: usize) {
223 self.types.reserve_exact(items);
224 self.indices.reserve_exact(items);
225 self.backing.reserve_exact(bytes);
226 }
227
228 /// Reserve capacity for at least `items` more items and
229 /// `bytes` more bytes.
230 ///
231 /// # Errors
232 /// Returns an error if allocation fails.
233 pub fn try_reserve(
234 &mut self,
235 items: usize,
236 bytes: usize,
237 ) -> Result<(), std::collections::TryReserveError> {
238 self.types.try_reserve(items)?;
239 self.indices.try_reserve(items)?;
240 self.backing.try_reserve(bytes)?;
241 Ok(())
242 }
243
244 /// Reserve capacity for at least `items` more items and
245 /// `bytes` more bytes. (Attempts to reserve the minimum
246 /// possible, but this is not guaranteed.)
247 ///
248 /// # Errors
249 /// Returns an error if allocation fails.
250 pub fn try_reserve_exact(
251 &mut self,
252 items: usize,
253 bytes: usize,
254 ) -> Result<(), std::collections::TryReserveError> {
255 self.types.try_reserve_exact(items)?;
256 self.indices.try_reserve_exact(items)?;
257 self.backing.try_reserve_exact(bytes)?;
258 Ok(())
259 }
260
261 fn pad_to_align(&mut self, align: usize) {
262 let padding = (align - (self.backing.len() % align)) % align;
263 for _ in 0..padding {
264 self.backing.push(0);
265 }
266 }
267
268 /// Move all elements from another `HarrenVec` into
269 /// this one, leaving the `other` empty.
270 ///
271 /// # Examples
272 /// ```
273 /// # use hvec::hvec;
274 /// let mut a = hvec![1, 2, 3];
275 /// let mut b = hvec![4, 5, 6];
276 /// a.append(&mut b);
277 /// assert_eq!(a.len(), 6);
278 /// assert_eq!(b.len(), 0);
279 /// ```
280 pub fn append(&mut self, other: &mut HarrenVec) {
281 self.pad_to_align(other.max_align);
282
283 let mut offset = 0;
284 for i in 0..other.len() {
285 let end = other
286 .indices
287 .get(i + 1)
288 .copied()
289 .unwrap_or(other.backing.len());
290
291 self.indices.push(self.backing.len());
292 self.backing.extend_from_slice(&other.backing[offset..end]);
293 self.types.push(other.types[i]);
294
295 offset = end;
296 }
297
298 #[cfg(not(feature = "no_drop"))]
299 {
300 for (type_id, drop_fn) in other.destructors.drain() {
301 self.destructors.insert(type_id, drop_fn);
302 }
303 }
304
305 other.clear_without_drop();
306 }
307
308 /// Clears the contents of the `HarrenVec`.
309 ///
310 /// (Note that if the `no_drop` feature is enabled, then
311 /// this method will not call the destructors of any of its contents.
312 ///
313 /// If the contents do not have a [`Drop`] implementation, this is not a
314 /// concern.)
315 pub fn clear(&mut self) {
316 #[cfg(not(feature = "no_drop"))]
317 {
318 for i in 0..self.len() {
319 self.drop_item(i);
320 }
321 }
322 self.clear_without_drop();
323 }
324
325 fn clear_without_drop(&mut self) {
326 self.types.clear();
327 self.indices.clear();
328 self.backing.clear();
329 }
330
331 /// Truncates the contents of the `HarrenVec` to a set
332 /// number of items, clearing the rest.
333 ///
334 /// (Note that if the `no_drop` feature is enabled, then
335 /// this method will not call the destructors of any of its contents.
336 ///
337 /// If the contents do not have a [`Drop`] implementation, this is not a
338 /// concern.)
339 pub fn truncate(&mut self, items: usize) {
340 #[cfg(not(feature = "no_drop"))]
341 {
342 let end = items + 1;
343 if end < self.len() {
344 for i in end..self.len() {
345 self.drop_item(i);
346 }
347 }
348 }
349 if let Some(last_index) = self.indices.get(items).copied() {
350 self.types.truncate(items);
351 self.indices.truncate(items);
352 self.backing.truncate(last_index);
353 }
354 }
355
356 /// Returns the type of the last item in the `HarrenVec`.
357 ///
358 /// # Examples
359 /// ```
360 /// # use hvec::hvec;
361 /// use std::any::TypeId;
362 ///
363 /// let list = hvec![1_u8, 2_i32, 3_u64];
364 /// assert_eq!(list.peek_type(), Some(TypeId::of::<u64>()));
365 /// ```
366 pub fn peek_type(&self) -> Option<TypeId> {
367 self.types.last().copied()
368 }
369
370 /// Returns the type of the last item in the `HarrenVec`,
371 /// as well as a pointer to the first byte of it.
372 ///
373 /// # Safety
374 ///
375 /// The pointer returned points to memory owned by the
376 /// `HarrenVec`, and so it is only valid as long as it that
377 /// data is unchanged.
378 ///
379 /// # Examples
380 /// ```
381 /// # use hvec::hvec;
382 /// use std::any::TypeId;
383 ///
384 /// let list = hvec![1_u8, 2_i32, 3_u64];
385 /// let (type_id, ptr) = list.peek_ptr().unwrap();
386 ///
387 /// assert_eq!(type_id, TypeId::of::<u64>());
388 ///
389 /// unsafe {
390 /// let ptr = ptr as *const u64;
391 /// assert_eq!(*ptr, 3_u64);
392 /// }
393 /// ```
394 pub fn peek_ptr(&self) -> Option<(TypeId, *const u8)> {
395 self.types.last().map(|&type_id| {
396 let index = self.indices.last().unwrap();
397 (type_id, &self.backing[*index] as *const u8)
398 })
399 }
400
401 /// Returns the number of items in the `HarrenVec`.
402 pub fn len(&self) -> usize {
403 self.indices.len()
404 }
405
406 /// Returns the total number of bytes occupied by the
407 /// contents of the `HarrenVec`.
408 pub fn bytes_len(&self) -> usize {
409 self.backing.len()
410 }
411
412 /// Returns `true` if there are no contents.
413 pub fn is_empty(&self) -> bool {
414 self.indices.is_empty()
415 }
416
417 /// Returns an Iterator-like structure for stepping through
418 /// the contents of the `HarrenVec`.
419 ///
420 /// Note that because the type of each item can be
421 /// different, and may not be known, this "iterator" cannot
422 /// be used in `for` loops.
423 ///
424 /// # Examples
425 ///
426 /// The recommended way to use this method depends on how
427 /// much you know about the contents. If there is a main
428 /// type and you know in advance when that type will
429 /// deviate, you can use a `while-let` loop:
430 ///
431 /// ```
432 /// # use hvec::hvec;
433 /// let list = hvec![1_usize, 2_usize, 999_usize, "Wow, big number!".to_string(), 3_usize];
434 /// let mut iter = list.into_iter();
435 ///
436 /// let mut total = 0;
437 /// while let Some(number) = iter.next::<usize>() {
438 /// if number > 100 {
439 /// let comment = iter.next::<String>().unwrap();
440 /// assert_eq!(comment, "Wow, big number!");
441 /// }
442 /// total += number;
443 /// }
444 /// assert_eq!(total, 1005);
445 /// ```
446 ///
447 /// If you don't have a structure that allows you to know
448 /// what type the next element is in advance, you can check
449 /// the type of each item as you read it:
450 ///
451 /// ```
452 /// # use hvec::hvec;
453 /// use std::any::TypeId;
454 ///
455 /// let list = hvec![1_u8, 500_u16, 99999_u32];
456 /// let mut iter = list.into_iter();
457 ///
458 /// let mut total: usize = 0;
459 /// while let Some(type_id) = iter.peek_type() {
460 /// if type_id == TypeId::of::<u8>() {
461 /// total += iter.next::<u8>().unwrap() as usize;
462 /// } else if type_id == TypeId::of::<u16>() {
463 /// total += iter.next::<u16>().unwrap() as usize;
464 /// } else if type_id == TypeId::of::<u32>() {
465 /// total += iter.next::<u32>().unwrap() as usize;
466 /// }
467 /// }
468 /// assert_eq!(total, 100500);
469 /// ```
470 #[allow(clippy::should_implement_trait)]
471 pub fn into_iter(self) -> HarrenIter {
472 HarrenIter {
473 cursor: 0,
474 vec: self,
475 }
476 }
477
478 /// Returns an Iterator-like structure for stepping through immutable references to
479 /// the contents of the `HarrenVec`.
480 ///
481 /// See [`HarrenVec::into_iter`] for examples.
482 pub fn iter(&self) -> HarrenRefIter {
483 HarrenRefIter {
484 cursor: 0,
485 vec: self,
486 }
487 }
488
489 /// Returns an Iterator-like structure for stepping through mutable references to
490 /// the contents of the `HarrenVec`.
491 ///
492 /// See [`HarrenVec::into_iter`] for examples.
493 pub fn iter_mut(&mut self) -> HarrenMutIter {
494 HarrenMutIter {
495 cursor: 0,
496 vec: self,
497 }
498 }
499
500 /// Add an element of any type to the `HarrenVec`.
501 ///
502 /// # Examples
503 ///
504 /// ```
505 /// # use hvec::HarrenVec;
506 /// let mut list = HarrenVec::new();
507 /// list.push(1_u8);
508 /// list.push("Hello, world!".to_string());
509 /// assert_eq!(list.len(), 2);
510 /// ```
511 pub fn push<T: 'static>(&mut self, t: T) {
512 let type_id = TypeId::of::<T>();
513 let ptr = &t as *const T as *const u8;
514 let size = std::mem::size_of::<T>();
515 let bytes = unsafe { std::slice::from_raw_parts(ptr, size) };
516
517 let align = std::mem::align_of::<T>();
518 self.max_align = std::cmp::max(self.max_align, align);
519 self.pad_to_align(align);
520
521 self.indices.push(self.backing.len());
522 self.backing.extend_from_slice(bytes);
523 self.types.push(type_id);
524
525 #[cfg(not(feature = "no_drop"))]
526 self.register_destructor::<T>();
527
528 std::mem::forget(t);
529 }
530
531 /// Pop the last element from the `HarrenVec`.
532 ///
533 /// # Panics
534 ///
535 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
536 ///
537 /// This method panics if the actual element is not an
538 /// element of the specified type `T`.
539 ///
540 /// # Examples
541 ///
542 /// ```
543 /// # use hvec::hvec;
544 /// let mut list = hvec!["Hello".to_string()];
545 /// assert_eq!(list.pop::<String>().unwrap(), "Hello".to_string());
546 /// ```
547 pub fn pop<T: 'static>(&mut self) -> Option<T> {
548 self.types.pop().map(|type_id| {
549 let index = self.indices.pop().unwrap();
550
551 #[cfg(feature = "type_assertions")]
552 assert_eq!(TypeId::of::<T>(), type_id);
553
554 let result = unsafe { self.take_at::<T>(index) };
555 self.backing.truncate(index);
556 result
557 })
558 }
559
560 /// See [`Self::pop`]. Does not panic if the type doesn't match.
561 ///
562 /// # Safety
563 ///
564 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
565 pub unsafe fn pop_unchecked<T: 'static>(&mut self) -> Option<T> {
566 self.types.pop().map(|_| {
567 let index = self.indices.pop().unwrap();
568 let result = unsafe { self.take_at::<T>(index) };
569 self.backing.truncate(index);
570 result
571 })
572 }
573
574 unsafe fn ref_at<T>(&self, offset: usize) -> &T {
575 unsafe { std::mem::transmute(&self.backing[offset]) }
576 }
577
578 unsafe fn mut_ref_at<T>(&mut self, offset: usize) -> &mut T {
579 unsafe { std::mem::transmute(&mut self.backing[offset]) }
580 }
581
582 unsafe fn take_at<T>(&self, offset: usize) -> T {
583 let mut result: MaybeUninit<T> = MaybeUninit::uninit();
584
585 let ptr = &self.backing[offset] as *const u8 as *const T;
586 let dest = result.as_mut_ptr();
587 unsafe {
588 dest.copy_from(ptr, 1);
589 result.assume_init()
590 }
591 }
592
593 #[cfg(not(feature = "no_drop"))]
594 fn drop_item(&mut self, index: usize) {
595 let type_id = self.types[index];
596 let offset = self.indices[index];
597 let ptr = &self.backing[offset] as *const u8 as *const ();
598 self.run_destructor(type_id, ptr);
599 }
600
601 /// Returns true if this `HarrenVec` contains the element.
602 ///
603 /// # Examples
604 /// ```
605 /// # use hvec::hvec;
606 /// let list = hvec![1_usize, "Hello".to_string()];
607 /// assert!(list.contains::<usize>(&1));
608 /// assert!(list.contains::<String>(&"Hello".to_string()));
609 /// assert!(!list.contains::<isize>(&1));
610 /// assert!(!list.contains::<String>(&"???".to_string()));
611 /// ```
612 pub fn contains<T: PartialEq<T> + 'static>(&self, x: &T) -> bool {
613 for (item_index, type_id) in self.types.iter().enumerate() {
614 if *type_id == TypeId::of::<T>()
615 && unsafe { self.ref_at::<T>(self.indices[item_index]) == x }
616 {
617 return true;
618 }
619 }
620 false
621 }
622
623 /// Return a reference to the first item of the `HarrenVec`.
624 ///
625 /// # Panics
626 ///
627 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
628 ///
629 /// This method panics if the item is not of the specified
630 /// type `T`.
631 pub fn first<T: 'static>(&self) -> Option<&T> {
632 #[cfg(feature = "type_assertions")]
633 assert_eq!(Some(&TypeId::of::<T>()), self.types.first());
634
635 unsafe { self.first_unchecked::<T>() }
636 }
637
638 /// See [`Self::first`]. Does not panic if the type doesn't match.
639 ///
640 /// # Safety
641 ///
642 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
643 pub unsafe fn first_unchecked<T: 'static>(&self) -> Option<&T> {
644 self.indices
645 .first()
646 .copied()
647 .map(|i| unsafe { self.ref_at::<T>(i) })
648 }
649
650 /// Return a mutable reference to the first item of
651 /// the `HarrenVec`.
652 ///
653 /// # Panics
654 ///
655 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
656 ///
657 /// This method panics if the item is not of the specified
658 /// type `T`.
659 pub fn first_mut<T: 'static>(&mut self) -> Option<&mut T> {
660 #[cfg(feature = "type_assertions")]
661 assert_eq!(Some(&TypeId::of::<T>()), self.types.first());
662
663 unsafe { self.first_mut_unchecked() }
664 }
665
666 /// See [`Self::first_mut`]. Does not panic if the type doesn't match.
667 ///
668 /// # Safety
669 ///
670 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
671 pub unsafe fn first_mut_unchecked<T: 'static>(&mut self) -> Option<&mut T> {
672 self.indices
673 .first()
674 .copied()
675 .map(|i| unsafe { self.mut_ref_at::<T>(i) })
676 }
677
678 /// Return a reference to the last item of the `HarrenVec`.
679 ///
680 /// # Panics
681 ///
682 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
683 ///
684 /// This method panics if the item is not of the specified
685 /// type `T`.
686 pub fn last<T: 'static>(&self) -> Option<&T> {
687 #[cfg(feature = "type_assertions")]
688 assert_eq!(Some(&TypeId::of::<T>()), self.types.last());
689
690 unsafe { self.last_unchecked() }
691 }
692
693 /// See [`Self::last`]. Does not panic if the type doesn't match.
694 ///
695 /// # Safety
696 ///
697 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
698 pub unsafe fn last_unchecked<T: 'static>(&self) -> Option<&T> {
699 self.indices
700 .last()
701 .copied()
702 .map(|i| unsafe { self.ref_at::<T>(i) })
703 }
704
705 /// Return a mutable reference to the last item of
706 /// the `HarrenVec`.
707 ///
708 /// # Panics
709 ///
710 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
711 ///
712 /// This method panics if the item is not of the specified
713 /// type `T`.
714 pub fn last_mut<T: 'static>(&mut self) -> Option<&mut T> {
715 #[cfg(feature = "type_assertions")]
716 assert_eq!(Some(&TypeId::of::<T>()), self.types.last());
717
718 unsafe { self.last_mut_unchecked() }
719 }
720
721 /// See [`Self::last_mut`]. Does not panic if the type doesn't match.
722 ///
723 /// # Safety
724 ///
725 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
726 pub unsafe fn last_mut_unchecked<T: 'static>(&mut self) -> Option<&mut T> {
727 self.indices
728 .last()
729 .copied()
730 .map(|i| unsafe { self.mut_ref_at::<T>(i) })
731 }
732
733 /// Alias of the [`Self::last`] method.
734 ///
735 /// # Safety
736 ///
737 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
738 pub fn peek<T: 'static>(&self) -> Option<&T> {
739 self.last()
740 }
741
742 /// Alias of the [`Self::last_unchecked`] method.
743 ///
744 /// # Safety
745 ///
746 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
747 pub unsafe fn peek_unchecked<T: 'static>(&self) -> Option<&T> {
748 unsafe { self.last_unchecked() }
749 }
750
751 /// Alias of the [`Self::last_mut`] method.
752 ///
753 /// # Safety
754 ///
755 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
756 pub fn peek_mut<T: 'static>(&mut self) -> Option<&mut T> {
757 self.last_mut()
758 }
759
760 /// Alias of the [`Self::last_mut_unchecked`] method.
761 ///
762 /// # Safety
763 ///
764 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
765 pub unsafe fn peek_mut_unchecked<T: 'static>(&mut self) -> Option<&mut T> {
766 unsafe { self.last_mut_unchecked() }
767 }
768
769 /// Return a reference to the item of the `HarrenVec` at
770 /// the given index.
771 ///
772 /// # Panics
773 ///
774 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
775 ///
776 /// This method panics if the item is not of the specified
777 /// type `T`.
778 pub fn get<T: 'static>(&self, index: usize) -> Option<&T> {
779 #[cfg(feature = "type_assertions")]
780 assert_eq!(Some(&TypeId::of::<T>()), self.types.get(index));
781
782 unsafe { self.get_unchecked(index) }
783 }
784
785 /// See [`Self::get`]. Does not panic if the type doesn't match.
786 ///
787 /// # Safety
788 ///
789 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
790 pub unsafe fn get_unchecked<T: 'static>(&self, index: usize) -> Option<&T> {
791 self.indices
792 .get(index)
793 .copied()
794 .map(|i| unsafe { self.ref_at::<T>(i) })
795 }
796
797 /// Return a mutable reference to the item of
798 /// the `HarrenVec` at the given index.
799 ///
800 /// # Panics
801 ///
802 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
803 ///
804 /// This method panics if the item is not of the specified
805 /// type `T`.
806 pub fn get_mut<T: 'static>(&mut self, index: usize) -> Option<&mut T> {
807 #[cfg(feature = "type_assertions")]
808 assert_eq!(Some(&TypeId::of::<T>()), self.types.get(index));
809
810 unsafe { self.get_mut_unchecked(index) }
811 }
812
813 /// See [`Self::get_mut`]. Does not panic if the type doesn't match.
814 ///
815 /// # Safety
816 ///
817 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
818 pub unsafe fn get_mut_unchecked<T: 'static>(&mut self, index: usize) -> Option<&mut T> {
819 self.indices
820 .get(index)
821 .copied()
822 .map(|i| unsafe { self.mut_ref_at::<T>(i) })
823 }
824
825 /// Returns the total number of elements this `HarrenVec`
826 /// can store without reallocating.
827 ///
828 /// Note that this is separate from its capacity in bytes.
829 /// Allocation will occur if either capacity is exceeded.
830 pub fn item_capacity(&self) -> usize {
831 std::cmp::min(self.types.capacity(), self.indices.capacity())
832 }
833
834 /// Returns the total number of bytes this `HarrenVec`
835 /// can store without reallocating.
836 ///
837 /// Note that this is separate from its capacity in items.
838 /// Allocation will occur if either capacity is exceeded.
839 pub fn byte_capacity(&self) -> usize {
840 self.backing.capacity()
841 }
842
843 /// Returns true if `other` contains the exact same types
844 /// and bytes as this `HarrenVec`. Not that this does _not_
845 /// call the actual [`PartialEq`] implementation for the
846 /// stored values, so the result may not be intuitive for
847 /// more complex or heap-allocated types.
848 ///
849 /// # Examples
850 ///
851 /// ```
852 /// # use hvec::hvec;
853 /// let list_a = hvec![1_u8, 2_isize];
854 /// let list_b = hvec![1_u8, 2_isize];
855 ///
856 /// let list_c = hvec![1_u8, "Hello".to_string()];
857 /// let list_d = hvec![1_u8, "Hello".to_string()];
858 ///
859 /// // Numbers can be correctly compared as bytes
860 /// assert!(list_a.bytes_eq(&list_b));
861 ///
862 /// // Strings contain pointers so identical strings may differ in bytes
863 /// assert!(!list_c.bytes_eq(&list_d));
864 /// ```
865 pub fn bytes_eq(&self, other: &HarrenVec) -> bool {
866 self.types == other.types && self.indices == other.indices && self.backing == other.backing
867 }
868}
869
870#[cfg(not(feature = "no_drop"))]
871impl Drop for HarrenVec {
872 fn drop(&mut self) {
873 self.clear();
874 }
875}
876
877/// An [`Iterator`]-like structure for taking
878/// ownership of the elements of a [`HarrenVec`].
879///
880/// (Note that if the `no_drop` feature is enabled, then
881/// this iterator will not call the destructors of any of its contents
882/// when dropped. Instead you should use the `next` method to ensure
883/// you are consuming and dropping each value.
884///
885/// If the contents do not have a [`Drop`] implementation, this is not a
886/// concern.)
887#[derive(Debug)]
888pub struct HarrenIter {
889 cursor: usize,
890 vec: HarrenVec,
891}
892
893impl HarrenIter {
894 /// Checks the type of the next item in the iterator
895 /// without actually advancing it.
896 ///
897 /// # Examples
898 /// ```
899 /// use std::any::TypeId;
900 /// use hvec::hvec;
901 ///
902 /// let list = hvec![1_u64, 2_i32];
903 /// let mut iter = list.into_iter();
904 /// assert_eq!(iter.peek_type(), Some(TypeId::of::<u64>()));
905 /// ```
906 pub fn peek_type(&self) -> Option<TypeId> {
907 self.vec.types.get(self.cursor).copied()
908 }
909
910 /// Advances the iterator and returns the next item if
911 /// one exists - or else None.
912 ///
913 /// # Panics
914 ///
915 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
916 ///
917 /// This method will panic if the actual type of the item
918 /// differs from the `T` that this method was called with.
919 ///
920 /// # Examples
921 /// ```
922 /// use hvec::hvec;
923 ///
924 /// let list = hvec![1_u64, 2_i32];
925 /// let mut iter = list.into_iter();
926 /// assert_eq!(iter.next::<u64>(), Some(1_u64));
927 /// assert_eq!(iter.next::<i32>(), Some(2_i32));
928 /// assert_eq!(iter.next::<()>(), None);
929 /// ```
930 #[allow(clippy::should_implement_trait)]
931 pub fn next<T: 'static>(&mut self) -> Option<T> {
932 // TODO: Messy checking this twice
933 if self.is_empty() {
934 return None;
935 }
936
937 #[cfg(feature = "type_assertions")]
938 {
939 let type_id = self.vec.types[self.cursor];
940 assert_eq!(type_id, TypeId::of::<T>());
941 }
942
943 unsafe { self.next_unchecked() }
944 }
945
946 /// See [`Self::next`]. Does not panic if the type doesn't match.
947 ///
948 /// # Safety
949 ///
950 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
951 pub unsafe fn next_unchecked<T: 'static>(&mut self) -> Option<T> {
952 if self.is_empty() {
953 return None;
954 }
955
956 let index = self.vec.indices[self.cursor];
957 let result = unsafe { self.vec.take_at::<T>(index) };
958 self.cursor += 1;
959 Some(result)
960 }
961
962 /// Returns true if there are no more elements in the
963 /// iterator.
964 pub fn is_empty(&self) -> bool {
965 self.cursor >= self.vec.len()
966 }
967}
968
969#[cfg(not(feature = "no_drop"))]
970impl Drop for HarrenIter {
971 fn drop(&mut self) {
972 if !self.is_empty() {
973 for i in self.cursor..self.vec.len() {
974 self.vec.drop_item(i);
975 }
976 }
977 self.vec.clear_without_drop();
978 }
979}
980
981/// An [`Iterator`]-like structure for immutably borrowing
982/// the elements of a [`HarrenVec`].
983#[derive(Debug)]
984pub struct HarrenRefIter<'a> {
985 cursor: usize,
986 vec: &'a HarrenVec,
987}
988
989impl HarrenRefIter<'_> {
990 /// Checks the type of the next item in the iterator
991 /// without actually advancing it.
992 ///
993 /// # Examples
994 /// ```
995 /// use std::any::TypeId;
996 /// use hvec::hvec;
997 ///
998 /// let list = hvec![1_u64, 2_i32];
999 /// let mut iter = list.into_iter();
1000 /// assert_eq!(iter.peek_type(), Some(TypeId::of::<u64>()));
1001 /// ```
1002 pub fn peek_type(&self) -> Option<TypeId> {
1003 self.vec.types.get(self.cursor).copied()
1004 }
1005
1006 /// Advances the iterator and returns the next item if
1007 /// one exists - or else None.
1008 ///
1009 /// # Panics
1010 ///
1011 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
1012 ///
1013 /// This method will panic if the actual type of the item
1014 /// differs from the `T` that this method was called with.
1015 ///
1016 /// # Examples
1017 /// ```
1018 /// use hvec::hvec;
1019 ///
1020 /// let list = hvec![1_u64, 2_i32];
1021 /// let mut iter = list.into_iter();
1022 /// assert_eq!(iter.next::<u64>(), Some(1_u64));
1023 /// assert_eq!(iter.next::<i32>(), Some(2_i32));
1024 /// assert_eq!(iter.next::<()>(), None);
1025 /// ```
1026 #[allow(clippy::should_implement_trait)]
1027 pub fn next<T: 'static>(&mut self) -> Option<&T> {
1028 // TODO: Messy checking this twice
1029 if self.is_empty() {
1030 return None;
1031 }
1032
1033 #[cfg(feature = "type_assertions")]
1034 {
1035 let type_id = self.vec.types[self.cursor];
1036 assert_eq!(type_id, TypeId::of::<T>());
1037 }
1038
1039 unsafe { self.next_unchecked() }
1040 }
1041
1042 /// See [`Self::next`]. Does not panic if the type doesn't match.
1043 ///
1044 /// # Safety
1045 ///
1046 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
1047 pub unsafe fn next_unchecked<T: 'static>(&mut self) -> Option<&T> {
1048 if self.is_empty() {
1049 return None;
1050 }
1051
1052 let index = self.vec.indices[self.cursor];
1053 let result = unsafe { self.vec.ref_at::<T>(index) };
1054 self.cursor += 1;
1055 Some(result)
1056 }
1057
1058 /// Returns true if there are no more elements in the
1059 /// iterator.
1060 pub fn is_empty(&self) -> bool {
1061 self.cursor >= self.vec.len()
1062 }
1063}
1064
1065/// An [`Iterator`]-like structure for mutably borrowing
1066/// the elements of a [`HarrenVec`].
1067#[derive(Debug)]
1068pub struct HarrenMutIter<'a> {
1069 cursor: usize,
1070 vec: &'a mut HarrenVec,
1071}
1072
1073impl HarrenMutIter<'_> {
1074 /// Checks the type of the next item in the iterator
1075 /// without actually advancing it.
1076 ///
1077 /// # Examples
1078 /// ```
1079 /// use std::any::TypeId;
1080 /// use hvec::hvec;
1081 ///
1082 /// let list = hvec![1_u64, 2_i32];
1083 /// let mut iter = list.into_iter();
1084 /// assert_eq!(iter.peek_type(), Some(TypeId::of::<u64>()));
1085 /// ```
1086 pub fn peek_type(&self) -> Option<TypeId> {
1087 self.vec.types.get(self.cursor).copied()
1088 }
1089
1090 /// Advances the iterator and returns the next item if
1091 /// one exists - or else None.
1092 ///
1093 /// # Panics
1094 ///
1095 /// (This method can only panic if the `type_assertions` feature flag is enabled.)
1096 ///
1097 /// This method will panic if the actual type of the item
1098 /// differs from the `T` that this method was called with.
1099 ///
1100 /// # Examples
1101 /// ```
1102 /// use hvec::hvec;
1103 ///
1104 /// let list = hvec![1_u64, 2_i32];
1105 /// let mut iter = list.into_iter();
1106 /// assert_eq!(iter.next::<u64>(), Some(1_u64));
1107 /// assert_eq!(iter.next::<i32>(), Some(2_i32));
1108 /// assert_eq!(iter.next::<()>(), None);
1109 /// ```
1110 #[allow(clippy::should_implement_trait)]
1111 pub fn next<T: 'static>(&mut self) -> Option<&mut T> {
1112 // TODO: Messy checking this twice
1113 if self.is_empty() {
1114 return None;
1115 }
1116
1117 #[cfg(feature = "type_assertions")]
1118 {
1119 let type_id = self.vec.types[self.cursor];
1120 assert_eq!(type_id, TypeId::of::<T>());
1121 }
1122
1123 unsafe { self.next_unchecked() }
1124 }
1125
1126 /// See [`Self::next`]. Does not panic if the type doesn't match.
1127 ///
1128 /// # Safety
1129 ///
1130 /// This method is only safe if the bytes can be safely interpreted as a struct of type `T`.
1131 pub unsafe fn next_unchecked<T: 'static>(&mut self) -> Option<&mut T> {
1132 if self.is_empty() {
1133 return None;
1134 }
1135
1136 let index = self.vec.indices[self.cursor];
1137 let result = unsafe { self.vec.mut_ref_at::<T>(index) };
1138 self.cursor += 1;
1139 Some(result)
1140 }
1141
1142 /// Returns true if there are no more elements in the
1143 /// iterator.
1144 pub fn is_empty(&self) -> bool {
1145 self.cursor >= self.vec.len()
1146 }
1147}
1148
1149/// Creates a [`HarrenVec`] containing the arguments.
1150///
1151/// # Examples
1152/// ```
1153/// use hvec::hvec;
1154///
1155/// let list_a = hvec![];
1156/// let list_b = hvec![1_u64; 2];
1157/// let list_c = hvec![1_u64, 2_i64, 3_u8];
1158///
1159/// assert!(list_a.len() == 0);
1160/// assert!(list_b.len() == 2);
1161/// assert!(list_c.len() == 3);
1162/// ```
1163#[macro_export]
1164macro_rules! hvec {
1165 () => { $crate::HarrenVec::new() };
1166 ($elem : expr ; $n : expr) => {{
1167 let mut vec = $crate::HarrenVec::new();
1168 for _ in 0..($n) {
1169 vec.push(($elem).clone());
1170 }
1171 vec
1172 }};
1173 ($($x : expr), + $(,) ?) => {{
1174 let mut vec = $crate::HarrenVec::new();
1175 $(vec.push($x);)*
1176 vec
1177 }};
1178}
1179
1180#[cfg(test)]
1181mod tests {
1182 use super::*;
1183
1184 #[test]
1185 fn construction_and_equality() {
1186 let macro_created = hvec![1_usize, 2_u8, [100_u32; 5]];
1187 let mut default = HVec::default();
1188 let mut with_cap = HVec::with_capacity(5, 64);
1189
1190 {
1191 default.push(1_usize);
1192 default.push(2_u8);
1193 default.push([100_u32; 5]);
1194 with_cap.push(1_usize);
1195 with_cap.push(2_u8);
1196 with_cap.push([100_u32; 5]);
1197 }
1198
1199 assert!(macro_created.bytes_eq(&default));
1200 assert!(default.bytes_eq(&with_cap));
1201 assert!(with_cap.bytes_eq(¯o_created));
1202 }
1203
1204 #[test]
1205 fn macro_forms() {
1206 assert!(hvec![].bytes_eq(&HVec::default()));
1207 assert!(hvec![1_u8, 1_u8].bytes_eq(&hvec![1_u8; 2]));
1208 }
1209
1210 #[test]
1211 fn bytes_eq_fails_for_strings() {
1212 let a = hvec!["Hello".to_string()];
1213 let b = hvec!["Hello".to_string()];
1214 assert!(!a.bytes_eq(&b));
1215 }
1216
1217 #[test]
1218 fn capacity() {
1219 let mut list = HVec::with_capacity(2, 16);
1220 assert!(list.item_capacity() >= 2);
1221 assert!(list.byte_capacity() >= 16);
1222
1223 list.push(1_u64);
1224 list.push(2_i64);
1225 list.push(3_u128);
1226
1227 assert!(list.item_capacity() >= 3);
1228 assert!(list.byte_capacity() >= 32);
1229 }
1230
1231 #[test]
1232 fn new_reserve() {
1233 let mut list = HVec::new();
1234 assert!(list.item_capacity() == 0);
1235 assert!(list.byte_capacity() == 0);
1236
1237 list.reserve(4, 64);
1238 assert!(list.item_capacity() >= 4);
1239 assert!(list.byte_capacity() >= 64);
1240 }
1241
1242 #[test]
1243 fn clear_truncate() {
1244 let mut list = hvec![1_u8, 2_i16, 3_u32, 4_i64];
1245 assert!(!list.is_empty());
1246 assert_eq!(list.len(), 4);
1247
1248 list.truncate(2);
1249 assert_eq!(list.len(), 2);
1250 list.clear();
1251 assert_eq!(list.len(), 0);
1252
1253 assert!(list.is_empty());
1254 }
1255
1256 #[test]
1257 fn peek() {
1258 let list_a = hvec![11_u8, 22_i16, 33_u32];
1259 let list_b = hvec![11_u8, 22_i16];
1260 let list_c = hvec![11_u8];
1261 let list_d = hvec![];
1262
1263 assert_eq!(list_a.peek_type(), Some(TypeId::of::<u32>()));
1264 assert_eq!(list_b.peek_type(), Some(TypeId::of::<i16>()));
1265 assert_eq!(list_c.peek_type(), Some(TypeId::of::<u8>()));
1266 assert_eq!(list_d.peek_type(), None);
1267
1268 let (_, p_a) = list_a.peek_ptr().unwrap();
1269 let (_, p_b) = list_b.peek_ptr().unwrap();
1270 let (_, p_c) = list_c.peek_ptr().unwrap();
1271
1272 unsafe {
1273 assert_eq!(*(p_a as *const u32), 33);
1274 assert_eq!(*(p_b as *const i16), 22);
1275 assert_eq!(*(p_c as *const u8), 11);
1276 }
1277 }
1278
1279 #[test]
1280 fn append() {
1281 let mut a = hvec![1_u32, 2_u64, 3_u128];
1282 let mut b = hvec![4_i32, 5_i64, 6_i128];
1283 a.append(&mut b);
1284
1285 assert!(a.len() == 6);
1286 assert!(b.is_empty());
1287
1288 let mut iter = a.into_iter();
1289 assert_eq!(iter.next::<u32>(), Some(1_u32));
1290 assert_eq!(iter.next::<u64>(), Some(2_u64));
1291 assert_eq!(iter.next::<u128>(), Some(3_u128));
1292 assert_eq!(iter.next::<i32>(), Some(4_i32));
1293 assert_eq!(iter.next::<i64>(), Some(5_i64));
1294 assert_eq!(iter.next::<i128>(), Some(6_i128));
1295 assert_eq!(iter.next::<()>(), None);
1296 }
1297
1298 #[test]
1299 fn push_peek_pop() {
1300 let mut list = hvec![];
1301 list.push(1_usize);
1302 list.push(2_u8);
1303 list.push("Hello".to_string());
1304
1305 assert_eq!(list.peek::<String>().unwrap(), "Hello");
1306 assert_eq!(list.pop::<String>().unwrap(), "Hello");
1307 assert_eq!(list.peek::<u8>(), Some(&2));
1308 assert_eq!(list.pop::<u8>(), Some(2));
1309 assert_eq!(list.peek::<usize>(), Some(&1));
1310 assert_eq!(list.pop::<usize>(), Some(1));
1311 }
1312
1313 #[test]
1314 fn first_last_get() {
1315 let a = hvec![1_u8, 2_isize, "3".to_string()];
1316 assert_eq!(a.first::<u8>(), Some(&1));
1317 assert_eq!(a.get::<isize>(1), Some(&2));
1318 assert_eq!(a.last::<String>(), Some(&"3".to_string()));
1319 }
1320
1321 #[test]
1322 fn first_last_get_mut() {
1323 let mut a = hvec![1_u8, 2_isize, "3".to_string()];
1324
1325 let target = a.first_mut::<u8>().unwrap();
1326 *target = 10;
1327
1328 let target = a.get_mut::<isize>(1).unwrap();
1329 *target = 20;
1330
1331 let target = a.last_mut::<String>().unwrap();
1332 *target = "30".to_string();
1333
1334 assert_eq!(a.first::<u8>(), Some(&10));
1335 assert_eq!(a.get::<isize>(1), Some(&20));
1336 assert_eq!(a.last::<String>(), Some(&"30".to_string()));
1337 }
1338
1339 #[test]
1340 fn contains() {
1341 let a = hvec![1_u8, 2_isize, "3".to_string()];
1342 assert!(a.contains::<u8>(&1));
1343 assert!(a.contains::<isize>(&2));
1344 assert!(a.contains::<String>(&"3".to_string()));
1345 }
1346
1347 #[test]
1348 #[should_panic]
1349 fn wrong_first_panics() {
1350 let a = hvec![1_usize];
1351 a.first::<u8>();
1352 }
1353
1354 #[test]
1355 #[should_panic]
1356 fn wrong_last_panics() {
1357 let a = hvec![1_usize];
1358 a.last::<u8>();
1359 }
1360
1361 #[test]
1362 #[should_panic]
1363 fn wrong_get_panics() {
1364 let a = hvec![1_usize];
1365 a.get::<u8>(0);
1366 }
1367
1368 #[test]
1369 #[should_panic]
1370 fn wrong_pop_panics() {
1371 let mut a = hvec![1_usize];
1372 a.pop::<u8>();
1373 }
1374
1375 #[test]
1376 fn into_iter() {
1377 let mut list = HarrenVec::new();
1378 list.push(1_usize);
1379 list.push(2_u8);
1380 list.push("Hello".to_string());
1381
1382 let mut items = list.into_iter();
1383 assert_eq!(items.peek_type(), Some(TypeId::of::<usize>()));
1384 assert_eq!(items.next::<usize>(), Some(1));
1385 assert_eq!(items.next::<u8>(), Some(2));
1386 assert_eq!(items.next::<String>(), Some("Hello".to_string()));
1387 }
1388
1389 #[test]
1390 fn iter() {
1391 let mut list = HarrenVec::new();
1392 list.push(1_usize);
1393 list.push(2_u8);
1394 list.push("Hello".to_string());
1395
1396 let mut items = list.iter();
1397 assert_eq!(items.peek_type(), Some(TypeId::of::<usize>()));
1398 assert_eq!(items.next::<usize>(), Some(&1));
1399 assert_eq!(items.next::<u8>(), Some(&2));
1400 assert_eq!(items.next::<String>(), Some(&"Hello".to_string()));
1401 }
1402
1403 #[test]
1404 fn iter_mut() {
1405 let mut list = HarrenVec::new();
1406 list.push(1_usize);
1407 list.push(2_u8);
1408 list.push("Hello".to_string());
1409
1410 let mut items = list.iter_mut();
1411 assert_eq!(items.peek_type(), Some(TypeId::of::<usize>()));
1412 assert_eq!(items.next::<usize>(), Some(&mut 1));
1413 assert_eq!(items.next::<u8>(), Some(&mut 2));
1414 assert_eq!(items.next::<String>(), Some(&mut "Hello".to_string()));
1415 }
1416
1417 #[test]
1418 fn extra_props() {
1419 struct Entry {
1420 id: usize,
1421 extra: bool,
1422 }
1423
1424 struct Extra {
1425 info: String,
1426 }
1427
1428 let mut log = String::new();
1429
1430 let mut list = HarrenVec::new();
1431 list.push(Entry {
1432 id: 0,
1433 extra: false,
1434 });
1435 list.push(Entry { id: 1, extra: true });
1436 list.push(Extra {
1437 info: "Hello".into(),
1438 });
1439 list.push(Entry {
1440 id: 2,
1441 extra: false,
1442 });
1443
1444 let mut items = list.into_iter();
1445 while let Some(entry) = items.next::<Entry>() {
1446 log.push_str(&entry.id.to_string());
1447 if entry.extra {
1448 let extra = items.next::<Extra>().unwrap();
1449 log.push_str(&extra.info);
1450 }
1451 }
1452
1453 assert_eq!(log, "01Hello2");
1454 }
1455}
1456
1457#[cfg(all(test, feature = "no_drop"))]
1458mod dropless_tests {
1459 use super::*;
1460
1461 use std::sync::{
1462 Arc,
1463 atomic::{AtomicUsize, Ordering},
1464 };
1465
1466 struct DropCounter(Arc<AtomicUsize>);
1467
1468 impl Drop for DropCounter {
1469 fn drop(&mut self) {
1470 self.0.fetch_add(1, Ordering::Relaxed);
1471 }
1472 }
1473
1474 #[test]
1475 fn contents_not_dropped_when_vec_dropped() {
1476 let count = Arc::new(AtomicUsize::new(0));
1477 let counter = DropCounter(Arc::clone(&count));
1478
1479 {
1480 let mut list = HarrenVec::new();
1481 list.push(counter);
1482 }
1483
1484 assert_eq!(count.load(Ordering::Relaxed), 0);
1485 }
1486}
1487
1488#[cfg(all(test, not(feature = "no_drop")))]
1489mod droptests {
1490 use super::*;
1491
1492 use std::sync::{
1493 Arc,
1494 atomic::{AtomicUsize, Ordering},
1495 };
1496
1497 struct DropCounter(Arc<AtomicUsize>);
1498
1499 impl Drop for DropCounter {
1500 fn drop(&mut self) {
1501 self.0.fetch_add(1, Ordering::Relaxed);
1502 }
1503 }
1504
1505 #[test]
1506 fn contents_dropped_when_vec_dropped() {
1507 let count = Arc::new(AtomicUsize::new(0));
1508 let counter = DropCounter(Arc::clone(&count));
1509
1510 {
1511 let mut list = HarrenVec::new();
1512 list.push(counter);
1513 }
1514
1515 assert_eq!(count.load(Ordering::Relaxed), 1);
1516 }
1517}