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(&macro_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}