Skip to main content

compressed_intvec/seq/
slice.rs

1//! Zero-copy slices of a [`SeqVec`].
2//!
3//! This module provides [`SeqVecSlice`], a view into a contiguous portion of a
4//! [`SeqVec`]. Slices are immutable and do not own their data; they borrow it
5//! from the parent [`SeqVec`].
6//!
7//! [`SeqVec`]: crate::seq::SeqVec
8
9use super::{iter::SeqVecBitReader, SeqIter, SeqVec};
10use crate::variable::traits::Storable;
11use dsi_bitstream::prelude::{BitRead, BitSeek, CodesRead, Endianness};
12use std::cmp::Ordering;
13use std::fmt;
14use std::ops::Range;
15
16/// An immutable, zero-copy slice of a [`SeqVec`].
17///
18/// This struct provides a view into a contiguous portion of a [`SeqVec`]
19/// without copying the underlying compressed data. It is created by the
20/// [`slice`] or [`split_at`] methods on a [`SeqVec`].
21///
22/// All operations on a [`SeqVecSlice`] are relative to the start of the slice,
23/// not the parent vector. The slice contains a contiguous range of sequences.
24///
25/// [`SeqVec`]: super::SeqVec
26/// [`slice`]: super::SeqVec::slice
27/// [`split_at`]: super::SeqVec::split_at
28///
29/// # Examples
30///
31/// ```
32/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
33/// use compressed_intvec::seq::{SeqVec, LESeqVec};
34///
35/// let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6], &[7, 8, 9, 10]];
36/// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
37///
38/// // Create a slice of sequences 1 through 2 (indices 1 and 2)
39/// let slice = vec.slice(1, 2).unwrap();
40///
41/// assert_eq!(slice.len(), 2);
42///
43/// // Accessing a sequence within the slice
44/// // Index 0 of the slice corresponds to sequence 1 of the original vector
45/// let seq0: Vec<u32> = slice.get(0).unwrap().collect();
46/// assert_eq!(seq0, vec![3, 4, 5]);
47///
48/// // Iterating over the slice
49/// let all_values: Vec<Vec<u32>> = slice.iter()
50///     .map(|seq| seq.collect())
51///     .collect();
52/// assert_eq!(all_values, vec![vec![3, 4, 5], vec![6]]);
53/// #     Ok(())
54/// # }
55/// ```
56#[derive(Debug, Clone)]
57pub struct SeqVecSlice<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> {
58    /// A reference to the parent vector.
59    vec: &'a SeqVec<T, E, B>,
60    /// The starting sequence index within the parent vector.
61    start: usize,
62    /// The number of sequences in the slice.
63    len: usize,
64}
65
66impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVecSlice<'a, T, E, B> {
67    /// Creates a new [`SeqVecSlice`].
68    pub(super) fn new(vec: &'a SeqVec<T, E, B>, range: Range<usize>) -> Self {
69        debug_assert!(
70            range.end <= vec.num_sequences(),
71            "Slice range exceeds vector bounds"
72        );
73        Self {
74            vec,
75            start: range.start,
76            len: range.len(),
77        }
78    }
79
80    /// Returns the number of sequences in the slice.
81    #[inline]
82    pub fn len(&self) -> usize {
83        self.len
84    }
85
86    /// Returns `true` if the slice contains no sequences.
87    #[inline]
88    pub fn is_empty(&self) -> bool {
89        self.len == 0
90    }
91
92    /// Returns an iterator over the elements of the sequence at `index` within
93    /// the slice, or `None` if the index is out of bounds.
94    ///
95    /// The index is relative to the start of the slice.
96    #[inline]
97    pub fn get(&self, index: usize) -> Option<SeqIter<'_, T, E>>
98    where
99        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
100            + CodesRead<E>
101            + BitSeek<Error = core::convert::Infallible>,
102    {
103        if index >= self.len {
104            return None;
105        }
106        // SAFETY: The bounds check above ensures `index` is valid.
107        Some(unsafe { self.get_unchecked(index) })
108    }
109
110    /// Returns an iterator over the elements of the sequence at `index` within
111    /// the slice without bounds checking.
112    ///
113    /// The index is relative to the start of the slice.
114    ///
115    /// # Safety
116    ///
117    /// Calling this method with an out-of-bounds index is undefined behavior.
118    /// The caller must ensure that `index < self.len()`.
119    #[inline(always)]
120    pub unsafe fn get_unchecked(&self, index: usize) -> SeqIter<'_, T, E>
121    where
122        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
123            + CodesRead<E>
124            + BitSeek<Error = core::convert::Infallible>,
125    {
126        debug_assert!(index < self.len, "Index out of bounds");
127        // Translate slice-relative index to parent vector index.
128        let parent_index = self.start + index;
129        unsafe { self.vec.get_unchecked(parent_index) }
130    }
131
132    /// Returns the sequence at `index` as a materialized `Vec<T>`, or `None`
133    /// if the index is out of bounds.
134    ///
135    /// This method fully decodes the sequence and allocates a new vector.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
141    /// use compressed_intvec::seq::{SeqVec, LESeqVec};
142    ///
143    /// let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6]];
144    /// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
145    ///
146    /// let slice = vec.slice(1, 2).unwrap();
147    /// assert_eq!(slice.decode_vec(0), Some(vec![3, 4, 5]));
148    /// assert_eq!(slice.decode_vec(1), Some(vec![6]));
149    /// assert_eq!(slice.decode_vec(2), None); // Out of bounds
150    /// #     Ok(())
151    /// # }
152    /// ```
153    #[inline]
154    pub fn decode_vec(&self, index: usize) -> Option<Vec<T>>
155    where
156        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
157            + CodesRead<E>
158            + BitSeek<Error = core::convert::Infallible>,
159    {
160        let parent_index = self.start.checked_add(index)?;
161        if index >= self.len {
162            return None;
163        }
164        self.vec.decode_vec(parent_index)
165    }
166
167    /// Returns the sequence at `index` as a materialized `Vec<T>` without bounds
168    /// checking.
169    ///
170    /// # Safety
171    ///
172    /// Calling this method with an out-of-bounds index is undefined behavior.
173    #[inline]
174    pub unsafe fn decode_vec_unchecked(&self, index: usize) -> Vec<T>
175    where
176        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
177            + CodesRead<E>
178            + BitSeek<Error = core::convert::Infallible>,
179    {
180        let parent_index = self.start + index;
181        unsafe { self.vec.decode_vec_unchecked(parent_index) }
182    }
183
184    /// Decodes the sequence at `index` into a reusable buffer.
185    ///
186    /// The buffer is cleared and then filled with the decoded sequence elements.
187    /// Returns the number of elements decoded, or `None` if the index is out
188    /// of bounds.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
194    /// use compressed_intvec::seq::{SeqVec, LESeqVec};
195    ///
196    /// let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6]];
197    /// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
198    ///
199    /// let slice = vec.slice(1, 2).unwrap();
200    ///
201    /// let mut buf = Vec::new();
202    /// assert_eq!(slice.decode_into(0, &mut buf), Some(3));
203    /// assert_eq!(buf, vec![3, 4, 5]);
204    ///
205    /// // Buffer is reused (cleared internally).
206    /// assert_eq!(slice.decode_into(1, &mut buf), Some(1));
207    /// assert_eq!(buf, vec![6]);
208    /// #     Ok(())
209    /// # }
210    /// ```
211    #[inline]
212    pub fn decode_into(&self, index: usize, buf: &mut Vec<T>) -> Option<usize>
213    where
214        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
215            + CodesRead<E>
216            + BitSeek<Error = core::convert::Infallible>,
217    {
218        let parent_index = self.start.checked_add(index)?;
219        if index >= self.len {
220            return None;
221        }
222        self.vec.decode_into(parent_index, buf)
223    }
224
225    /// Decodes sequence `index` into the provided buffer without bounds checking.
226    ///
227    /// # Safety
228    ///
229    /// Calling this method with an out-of-bounds index is undefined behavior.
230    #[inline]
231    pub unsafe fn decode_into_unchecked(&self, index: usize, buf: &mut Vec<T>) -> usize
232    where
233        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
234            + CodesRead<E>
235            + BitSeek<Error = core::convert::Infallible>,
236    {
237        let parent_index = self.start + index;
238        unsafe { self.vec.decode_into_unchecked(parent_index, buf) }
239    }
240
241    /// Returns an iterator over the sequences in the slice.
242    pub fn iter(&self) -> SeqVecSliceIter<'_, T, E, B>
243    where
244        for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
245            + CodesRead<E>
246            + BitSeek<Error = core::convert::Infallible>,
247    {
248        SeqVecSliceIter::new(self)
249    }
250}
251
252impl<T, E, B> SeqVecSlice<'_, T, E, B>
253where
254    T: Storable + PartialEq,
255    E: Endianness,
256    B: AsRef<[u64]>,
257    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
258        + CodesRead<E>
259        + BitSeek<Error = core::convert::Infallible>,
260{
261    /// Binary searches this slice for a sequence matching the given elements.
262    ///
263    /// If the sequence is found, returns `Ok(usize)` with the index of the
264    /// matching sequence within the slice. If not found, returns `Err(usize)`
265    /// with the insertion point to maintain order.
266    ///
267    /// The comparison is performed element-by-element with early termination:
268    /// sequences with different lengths or any differing element are ordered
269    /// according to the first difference encountered.
270    ///
271    /// # Performance Note
272    ///
273    /// Each binary search probe **fully decodes a compressed sequence** until a
274    /// difference is found or the sequence ends. For `log(n)` probes, each
275    /// decoding is O(m) where `m` is the sequence length. This is O(m * log n)
276    /// overall.
277    ///
278    /// - If sequences are short or differ early, early termination makes this
279    ///   very efficient.
280    /// - If sequences are very long and similar, decoding cost dominates.
281    /// - To extract a key from each sequence efficiently, use
282    ///   [`binary_search_by_key`](Self::binary_search_by_key) to extract a
283    ///   sortable key from the compressed data (e.g., first element) rather
284    ///   than the full sequence.
285    ///
286    /// # Examples
287    ///
288    /// ```
289    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
290    /// use compressed_intvec::seq::{SeqVec, LESeqVec};
291    ///
292    /// let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6, 7], &[8]];
293    /// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
294    ///
295    /// let slice = vec.slice(0, 4).unwrap();
296    ///
297    /// assert_eq!(slice.binary_search(&[3, 4, 5]), Ok(1));
298    /// assert_eq!(slice.binary_search(&[6, 7]), Ok(2));
299    /// assert_eq!(slice.binary_search(&[5]), Err(2)); // Would be inserted at index 2
300    /// #     Ok(())
301    /// # }
302    /// ```
303    pub fn binary_search(&self, sequence: &[T]) -> Result<usize, usize>
304    where
305        T: Ord,
306    {
307        self.binary_search_by(|probe_iter| {
308            // Compare element-by-element with early exit on first difference.
309            let mut probe_iter = probe_iter.peekable();
310            let mut seq_iter = sequence.iter().peekable();
311
312            loop {
313                match (probe_iter.next(), seq_iter.next()) {
314                    (Some(a), Some(b)) => {
315                        let cmp = a.cmp(b);
316                        if cmp != Ordering::Equal {
317                            return cmp;
318                        }
319                    }
320                    // Probe sequence ended first → Less
321                    (None, Some(_)) => return Ordering::Less,
322                    // Target sequence ended first → Greater
323                    (Some(_), None) => return Ordering::Greater,
324                    // Both ended → Equal
325                    (None, None) => return Ordering::Equal,
326                }
327            }
328        })
329    }
330
331    /// Binary searches this slice with a custom comparison function.
332    ///
333    /// The comparison function receives a [`SeqIter`] for the probe sequence
334    /// and should return the ordering relative to the target.
335    ///
336    /// # Performance Note
337    ///
338    /// The closure receives a [`SeqIter`] for the probe sequence, which may
339    /// require decoding the compressed data. Each probe can involve up to O(m)
340    /// decoding operations where `m` is the sequence length.
341    ///
342    /// - For fast key extraction (first element, hash, etc.), decode only what
343    ///   is needed within the closure and return early.
344    /// - To search by a pre-computed key, use
345    ///   [`binary_search_by_key`](Self::binary_search_by_key) instead, which is
346    ///   optimized for key-based comparisons.
347    /// - For comparisons requiring the full sequence, full decoding is
348    ///   unavoidable: O(m * log n).
349    ///
350    /// [`SeqIter`]: super::iter::SeqIter
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
356    /// use compressed_intvec::seq::{SeqVec, LESeqVec};
357    /// use std::cmp::Ordering;
358    ///
359    /// let sequences: &[&[u32]] = &[&[1], &[1, 2], &[1, 2, 3], &[1, 2, 3, 4]];
360    /// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
361    ///
362    /// let slice = vec.slice(0, 4).unwrap();
363    ///
364    /// // Search by sequence length (decodes all elements)
365    /// let result = slice.binary_search_by(|probe| {
366    ///     let probe_len = probe.count();
367    ///     probe_len.cmp(&3)
368    /// });
369    ///
370    /// assert_eq!(result, Ok(2));
371    ///
372    /// // Search by first element only (early termination)
373    /// let result = slice.binary_search_by(|mut probe| {
374    ///     match probe.next() {
375    ///         Some(first) => first.cmp(&1),
376    ///         None => Ordering::Less,
377    ///     }
378    /// });
379    /// #     Ok(())
380    /// # }
381    /// ```
382    #[inline]
383    pub fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize>
384    where
385        F: FnMut(SeqIter<'_, T, E>) -> Ordering,
386    {
387        let mut low = 0;
388        let mut high = self.len();
389
390        while low < high {
391            let mid = low + (high - low) / 2;
392            // SAFETY: Bounds are checked by the loop invariants and the slice's
393            // construction, so the index is always valid.
394            let cmp = f(unsafe { self.get_unchecked(mid) });
395            match cmp {
396                Ordering::Less => low = mid + 1,
397                Ordering::Equal => return Ok(mid),
398                Ordering::Greater => high = mid,
399            }
400        }
401        Err(low)
402    }
403
404    /// Binary searches this slice with a key extraction function.
405    ///
406    /// # Examples
407    ///
408    /// ```
409    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
410    /// use compressed_intvec::seq::{SeqVec, LESeqVec};
411    ///
412    /// let sequences: &[&[u32]] = &[&[10], &[20], &[30, 40], &[50]];
413    /// let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
414    ///
415    /// let slice = vec.slice(0, 4).unwrap();
416    ///
417    /// // Search by first element
418    /// let result = slice.binary_search_by_key(&30, |mut probe| probe.next().unwrap());
419    /// assert_eq!(result, Ok(2)); // Found sequence [30, 40]
420    /// #     Ok(())
421    /// # }
422    /// ```
423    #[inline]
424    pub fn binary_search_by_key<K, F>(&self, b: &K, mut f: F) -> Result<usize, usize>
425    where
426        F: FnMut(SeqIter<'_, T, E>) -> K,
427        K: Ord,
428    {
429        self.binary_search_by(|probe| f(probe).cmp(b))
430    }
431}
432
433/// An iterator over the sequences of a [`SeqVecSlice`].
434///
435/// This struct is created by the [`iter`] method. Each element of this
436/// iterator is a [`SeqIter`] for a sequence within the slice.
437///
438/// [`iter`]: SeqVecSlice::iter
439/// [`SeqIter`]: super::iter::SeqIter
440pub struct SeqVecSliceIter<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> {
441    slice: &'a SeqVecSlice<'a, T, E, B>,
442    /// Current front index for forward iteration.
443    front: usize,
444    /// Current back index (exclusive) for backward iteration.
445    back: usize,
446}
447
448impl<T: Storable, E: Endianness, B: AsRef<[u64]>> fmt::Debug for SeqVecSliceIter<'_, T, E, B> {
449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450        f.debug_struct("SeqVecSliceIter")
451            .field("remaining", &self.back.saturating_sub(self.front))
452            .finish()
453    }
454}
455
456// --- IntoIterator Implementation ---
457
458impl<'a, T, E, B> IntoIterator for &'a SeqVecSlice<'a, T, E, B>
459where
460    T: Storable,
461    E: Endianness,
462    B: AsRef<[u64]>,
463    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
464        + CodesRead<E>
465        + BitSeek<Error = core::convert::Infallible>,
466{
467    type Item = SeqIter<'a, T, E>;
468    type IntoIter = SeqVecSliceIter<'a, T, E, B>;
469
470    /// Returns an iterator over the sequences in the slice.
471    ///
472    /// This implementation allows slices to be used in `for` loops:
473    ///
474    /// ```no_run
475    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
476    /// # use compressed_intvec::seq::{SeqVec, LESeqVec};
477    /// # let vec: LESeqVec<u32> = SeqVec::from_slices(&[&[1, 2][..], &[3, 4, 5][..]])?;
478    /// # let slice = vec.slice(0, 2).unwrap();
479    /// for seq in &slice {
480    ///     // Process each sequence
481    /// }
482    /// #     Ok(())
483    /// # }
484    /// ```
485    #[inline]
486    fn into_iter(self) -> Self::IntoIter {
487        self.iter()
488    }
489}
490
491impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVecSliceIter<'a, T, E, B> {
492    /// Creates a new iterator for a given [`SeqVecSlice`].
493    fn new(slice: &'a SeqVecSlice<'a, T, E, B>) -> Self {
494        Self {
495            slice,
496            front: 0,
497            back: slice.len(),
498        }
499    }
500}
501
502impl<'a, T, E, B> Iterator for SeqVecSliceIter<'a, T, E, B>
503where
504    T: Storable,
505    E: Endianness,
506    B: AsRef<[u64]>,
507    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
508        + CodesRead<E>
509        + BitSeek<Error = core::convert::Infallible>,
510{
511    type Item = SeqIter<'a, T, E>;
512
513    #[inline]
514    fn next(&mut self) -> Option<Self::Item> {
515        if self.front >= self.back {
516            return None;
517        }
518        let index = self.front;
519        self.front += 1;
520        // SAFETY: The iterator's invariant ensures `index` is in bounds.
521        Some(unsafe { self.slice.get_unchecked(index) })
522    }
523
524    fn size_hint(&self) -> (usize, Option<usize>) {
525        let remaining = self.back.saturating_sub(self.front);
526        (remaining, Some(remaining))
527    }
528
529    #[inline]
530    fn nth(&mut self, n: usize) -> Option<Self::Item> {
531        let remaining = self.back.saturating_sub(self.front);
532        if n >= remaining {
533            self.front = self.back;
534            return None;
535        }
536        self.front += n;
537        self.next()
538    }
539
540    #[inline]
541    fn count(self) -> usize {
542        self.back.saturating_sub(self.front)
543    }
544}
545
546impl<'a, T, E, B> ExactSizeIterator for SeqVecSliceIter<'a, T, E, B>
547where
548    T: Storable,
549    E: Endianness,
550    B: AsRef<[u64]>,
551    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
552        + CodesRead<E>
553        + BitSeek<Error = core::convert::Infallible>,
554{
555    fn len(&self) -> usize {
556        self.back.saturating_sub(self.front)
557    }
558}
559
560impl<'a, T, E, B> std::iter::FusedIterator for SeqVecSliceIter<'a, T, E, B>
561where
562    T: Storable,
563    E: Endianness,
564    B: AsRef<[u64]>,
565    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
566        + CodesRead<E>
567        + BitSeek<Error = core::convert::Infallible>,
568{
569}
570
571impl<'a, T, E, B> DoubleEndedIterator for SeqVecSliceIter<'a, T, E, B>
572where
573    T: Storable,
574    E: Endianness,
575    B: AsRef<[u64]>,
576    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
577        + CodesRead<E>
578        + BitSeek<Error = core::convert::Infallible>,
579{
580    #[inline]
581    fn next_back(&mut self) -> Option<Self::Item> {
582        if self.front >= self.back {
583            return None;
584        }
585        self.back -= 1;
586        // SAFETY: The iterator's invariant ensures `back` is in bounds.
587        Some(unsafe { self.slice.get_unchecked(self.back) })
588    }
589
590    #[inline]
591    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
592        let remaining = self.back.saturating_sub(self.front);
593        if n >= remaining {
594            self.back = self.front;
595            return None;
596        }
597        self.back -= n;
598        self.next_back()
599    }
600}
601
602// --- PartialEq Implementations ---
603
604impl<'a, T, E, B> PartialEq<SeqVecSlice<'a, T, E, B>> for SeqVecSlice<'a, T, E, B>
605where
606    T: Storable + PartialEq,
607    E: Endianness,
608    B: AsRef<[u64]>,
609    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
610        + CodesRead<E>
611        + BitSeek<Error = core::convert::Infallible>,
612{
613    fn eq(&self, other: &SeqVecSlice<'a, T, E, B>) -> bool {
614        if self.len() != other.len() {
615            return false;
616        }
617        self.iter()
618            .zip(other.iter())
619            .all(|(seq_a, seq_b)| seq_a.eq(seq_b))
620    }
621}
622
623impl<'a, T, E, B> Eq for SeqVecSlice<'a, T, E, B>
624where
625    T: Storable + Eq,
626    E: Endianness,
627    B: AsRef<[u64]>,
628    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
629        + CodesRead<E>
630        + BitSeek<Error = core::convert::Infallible>,
631{
632}
633
634impl<'a, T, E, B> PartialEq<SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>
635where
636    T: Storable + PartialEq,
637    E: Endianness,
638    B: AsRef<[u64]>,
639    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
640        + CodesRead<E>
641        + BitSeek<Error = core::convert::Infallible>,
642{
643    fn eq(&self, other: &SeqVec<T, E, B>) -> bool {
644        if self.len() != other.num_sequences() {
645            return false;
646        }
647        self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
648    }
649}
650
651impl<'a, T, E, B> PartialEq<SeqVecSlice<'a, T, E, B>> for SeqVec<T, E, B>
652where
653    T: Storable + PartialEq,
654    E: Endianness,
655    B: AsRef<[u64]>,
656    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
657        + CodesRead<E>
658        + BitSeek<Error = core::convert::Infallible>,
659{
660    fn eq(&self, other: &SeqVecSlice<'a, T, E, B>) -> bool {
661        other.eq(self)
662    }
663}
664
665impl<'a, T, E, B> PartialEq<&SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>
666where
667    T: Storable + PartialEq,
668    E: Endianness,
669    B: AsRef<[u64]>,
670    for<'b> SeqVecBitReader<'b, E>: BitRead<E, Error = core::convert::Infallible>
671        + CodesRead<E>
672        + BitSeek<Error = core::convert::Infallible>,
673{
674    fn eq(&self, other: &&SeqVec<T, E, B>) -> bool {
675        self.eq(*other)
676    }
677}