pub struct SeqVec<T: Storable, E: Endianness, B: AsRef<[u64]> = Vec<u64>> { /* private fields */ }Expand description
A compressed, indexed vector of integer sequences.
SeqVec stores multiple sequences of integers in a single compressed
bitstream, with an auxiliary index for O(1) access to each sequence by
its rank. This is ideal for representing collections of variable-length
sequences with minimal memory overhead.
See the module-level documentation for detailed usage information.
§Type Parameters
T- The element type (e.g.,u32,i16). Must implementStorable.E- TheEndiannessof the underlying bitstream (LEorBE).B- The backing buffer type, enabling owned (Vec<u64>) or borrowed (&[u64]) storage for zero-copy operations.
Implementations§
Source§impl<T: Storable + 'static, E: Endianness> SeqVec<T, E, Vec<u64>>
impl<T: Storable + 'static, E: Endianness> SeqVec<T, E, Vec<u64>>
Sourcepub fn builder() -> SeqVecBuilder<T, E>
pub fn builder() -> SeqVecBuilder<T, E>
Creates a builder for constructing a SeqVec with custom settings.
This is the most flexible way to create a SeqVec, allowing
customization of the compression codec and other parameters.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec, Codec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20]];
let vec: LESeqVec<u32> = SeqVec::builder()
.codec(Codec::Zeta { k: Some(3) })
.build(sequences)?;Sourcepub fn from_iter_builder<I, S>(iter: I) -> SeqVecFromIterBuilder<T, E, I>
pub fn from_iter_builder<I, S>(iter: I) -> SeqVecFromIterBuilder<T, E, I>
Creates a builder for constructing a SeqVec from an iterator.
This is useful for large datasets that are generated on the fly. The codec must be specified explicitly since single-pass construction cannot perform data analysis.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec, Codec};
// Generate sequences programmatically
let sequences = (0..50).map(|i| vec![i as u32; i % 5 + 1]);
let vec: LESeqVec<u32> = SeqVec::from_iter_builder(sequences)
.codec(Codec::Gamma)
.build()?;
assert_eq!(vec.num_sequences(), 50);Sourcepub unsafe fn from_raw_parts(
data: Vec<u64>,
bit_offsets: FixedVec<u64, u64, E, Vec<u64>>,
encoding: Codes,
) -> Self
pub unsafe fn from_raw_parts( data: Vec<u64>, bit_offsets: FixedVec<u64, u64, E, Vec<u64>>, encoding: Codes, ) -> Self
Creates a SeqVec from raw parts without validation.
§Arguments
data- The compressed data buffer containing encoded words.bit_offsets- Bit offset index where each offset points to the start of a sequence. Must contain at least 2 elements: the start offset and end sentinel.encoding- The codec specification used to encode the data.
§Safety
This method is unsafe because it does not validate that the data and
bit_offsets are consistent with each other. The caller must ensure:
- The
bit_offsetsarray has at least 2 elements (start and end sentinel). - All offsets are valid bit positions within the
databuffer. - The last offset equals the total number of bits in the compressed data.
Sourcepub unsafe fn from_raw_parts_with_lengths(
data: Vec<u64>,
bit_offsets: FixedVec<u64, u64, E, Vec<u64>>,
seq_lengths: Option<FixedVec<u64, u64, E, Vec<u64>>>,
encoding: Codes,
) -> Self
pub unsafe fn from_raw_parts_with_lengths( data: Vec<u64>, bit_offsets: FixedVec<u64, u64, E, Vec<u64>>, seq_lengths: Option<FixedVec<u64, u64, E, Vec<u64>>>, encoding: Codes, ) -> Self
Creates a SeqVec from raw parts with optional stored sequence lengths.
This method is identical to from_raw_parts but
allows providing pre-computed per-sequence lengths for faster random access.
§Arguments
data- The compressed data buffer.bit_offsets- Bit offset boundaries for each sequence.seq_lengths- Optional per-sequence lengths. If provided, must have length equal to the number of sequences (offsets.len() - 1).encoding- The codec specification used to encode the data.
§Safety
The caller must ensure that data, bit_offsets, and seq_lengths
(if present) are consistent with each other and the codec.
Source§impl<T, E, B> SeqVec<T, E, B>where
T: Storable + Send + Sync,
E: Endianness + Send + Sync,
B: AsRef<[u64]> + Send + Sync,
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible> + Send,
impl<T, E, B> SeqVec<T, E, B>where
T: Storable + Send + Sync,
E: Endianness + Send + Sync,
B: AsRef<[u64]> + Send + Sync,
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible> + Send,
Sourcepub fn par_iter(&self) -> impl ParallelIterator<Item = Vec<T>> + '_
pub fn par_iter(&self) -> impl ParallelIterator<Item = Vec<T>> + '_
Returns a parallel iterator over all sequences, materializing each as Vec<T>.
This method uses Rayon to decompress and collect all sequences in
parallel. Each sequence is fully decoded into a Vec<T> by its
assigned thread before being yielded.
§Performance
Parallelization is beneficial when the dataset contains enough sequences and those sequences are sufficiently large to amortize thread overhead.
For consumptive operations (sum, count, fold) where the decoded data
is not retained, prefer par_for_each which
avoids allocation overhead.
For small datasets or very fast codecs, the sequential iter
method may be faster due to better cache locality.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
use rayon::prelude::*;
let sequences: &[&[u32]] = &[
&[1, 2, 3],
&[10, 20],
&[100, 200, 300],
];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Collect all sequences in parallel
let all_sequences: Vec<Vec<u32>> = vec.par_iter().collect();
assert_eq!(all_sequences.len(), 3);
assert_eq!(all_sequences[0], vec![1, 2, 3]);Sourcepub fn par_for_each<F, R>(&self, f: F) -> Vec<R>
pub fn par_for_each<F, R>(&self, f: F) -> Vec<R>
Applies a function to each sequence in parallel without materialization.
Unlike par_iter, this method does not allocate a
Vec<T> for each sequence. Instead, the closure receives a streaming
SeqIter directly, enabling zero-allocation parallel processing.
§Performance
This method is optimal when:
- The operation is purely consumptive (fold, sum, count, predicate check)
- Memory allocation overhead is significant relative to decode time
- Sequences are short enough that materialization cost matters
For operations that need to retain sequence data (collect, sort, store),
use par_iter instead.
§Type Parameters
F: Closure type that processes aSeqIterand produces a resultR: Result type produced by the closure, must beSend
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20], &[100]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Sum each sequence without allocating intermediate Vecs
let sums: Vec<u64> = vec.par_for_each(|seq| seq.map(|v| v as u64).sum());
assert_eq!(sums, vec![6, 30, 100]);
// Count elements per sequence
let counts: Vec<usize> = vec.par_for_each(|seq| seq.count());
assert_eq!(counts, vec![3, 2, 1]);
// Check if any sequence contains a value > 50
let has_large: Vec<bool> = vec.par_for_each(|mut seq| seq.any(|v| v > 50));
assert_eq!(has_large, vec![false, false, true]);§Comparison with par_iter
use compressed_intvec::seq::{SeqVec, LESeqVec};
use rayon::prelude::*;
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// par_iter: allocates Vec<T> per sequence, then sums
let sums_alloc: Vec<u64> = vec
.par_iter()
.map(|s| s.iter().map(|&v| v as u64).sum())
.collect();
// par_for_each: zero allocation, sums directly from iterator
let sums_noalloc: Vec<u64> = vec.par_for_each(|seq| seq.map(|v| v as u64).sum());
assert_eq!(sums_alloc, sums_noalloc);Sourcepub fn par_for_each_reduce<F, R, ID, OP>(&self, f: F, identity: ID, op: OP) -> R
pub fn par_for_each_reduce<F, R, ID, OP>(&self, f: F, identity: ID, op: OP) -> R
Applies a function to each sequence in parallel and reduces results.
This is a convenience method combining par_for_each
with a parallel reduction. Useful when the final result is a single
aggregated value rather than a collection.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20], &[100]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Total sum across all sequences
let total: u64 = vec.par_for_each_reduce(
|seq| seq.map(|v| v as u64).sum::<u64>(),
|| 0u64,
|a, b| a + b,
);
assert_eq!(total, 136); // 6 + 30 + 100
// Maximum element across all sequences
let max: u32 = vec.par_for_each_reduce(
|seq| seq.max().unwrap_or(0),
|| 0u32,
|a, b| a.max(b),
);
assert_eq!(max, 100);Sourcepub fn par_into_vecs(self) -> Vec<Vec<T>>
pub fn par_into_vecs(self) -> Vec<Vec<T>>
Consumes the SeqVec and decodes all sequences into separate vectors
in parallel.
This method is a parallel version of into_vecs,
leveraging Rayon to decompress multiple sequences concurrently. Each
sequence is fully decompressed by its assigned thread.
§Performance
Parallelization is beneficial when:
- The dataset is large enough to amortize thread overhead
- Sequences are reasonably sized
For small datasets or very fast codecs, the sequential
into_vecs method may be faster due to
better cache locality.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[
&[1, 2, 3],
&[10, 20],
&[100, 200, 300],
];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Decode all sequences in parallel
let all_sequences: Vec<Vec<u32>> = vec.par_into_vecs();
assert_eq!(all_sequences.len(), 3);
assert_eq!(all_sequences[0], vec![1, 2, 3]);
assert_eq!(all_sequences[1], vec![10, 20]);Sourcepub fn par_decode_many(
&self,
indices: &[usize],
) -> Result<Vec<Vec<T>>, SeqVecError>
pub fn par_decode_many( &self, indices: &[usize], ) -> Result<Vec<Vec<T>>, SeqVecError>
Retrieves multiple sequences in parallel.
This method uses Rayon to parallelize the retrieval of multiple sequences by index. It is particularly useful when accessing a large subset of sequences that are not contiguous.
§Errors
Returns SeqVecError::IndexOutOfBounds if any index is out of bounds.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[
&[1, 2, 3],
&[10, 20],
&[100, 200, 300],
&[1000],
];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let indices = [3, 0, 2];
let sequences = vec.par_decode_many(&indices)?;
assert_eq!(sequences.len(), 3);
assert_eq!(sequences[0], vec![1000]); // Index 3
assert_eq!(sequences[1], vec![1, 2, 3]); // Index 0
assert_eq!(sequences[2], vec![100, 200, 300]); // Index 2Sourcepub unsafe fn par_decode_many_unchecked(&self, indices: &[usize]) -> Vec<Vec<T>>
pub unsafe fn par_decode_many_unchecked(&self, indices: &[usize]) -> Vec<Vec<T>>
Retrieves multiple sequences in parallel without bounds checking.
§Safety
Calling this method with any out-of-bounds index in the indices slice
is undefined behavior. In debug builds, assertions will panic.
Sourcepub fn par_for_each_many<F, R>(
&self,
indices: &[usize],
f: F,
) -> Result<Vec<R>, SeqVecError>
pub fn par_for_each_many<F, R>( &self, indices: &[usize], f: F, ) -> Result<Vec<R>, SeqVecError>
Applies a function to selected sequences in parallel without materialization.
This is the sparse-access equivalent of par_for_each,
allowing zero-allocation processing of a subset of sequences by index.
§Errors
Returns SeqVecError::IndexOutOfBounds if any index is out of bounds.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20], &[100], &[1000, 2000]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Sum only sequences at indices 0 and 2
let sums = vec.par_for_each_many(&[0, 2], |seq| seq.map(|v| v as u64).sum::<u64>())?;
assert_eq!(sums, vec![6, 100]);Source§impl<T: Storable + 'static, E: Endianness> SeqVec<T, E, Vec<u64>>
impl<T: Storable + 'static, E: Endianness> SeqVec<T, E, Vec<u64>>
Sourcepub fn from_slices<S: AsRef<[T]>>(sequences: &[S]) -> Result<Self, SeqVecError>where
BufBitWriter<E, MemWordWriterVec<u64, Vec<u64>>>: BitWrite<E, Error = Infallible> + CodesWrite<E>,
pub fn from_slices<S: AsRef<[T]>>(sequences: &[S]) -> Result<Self, SeqVecError>where
BufBitWriter<E, MemWordWriterVec<u64, Vec<u64>>>: BitWrite<E, Error = Infallible> + CodesWrite<E>,
Creates a SeqVec from a slice of slices using default settings.
This method uses Codec::Auto to select an optimal codec
based on the data distribution.
§Errors
Returns a SeqVecError if codec resolution or encoding fails.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20], &[100]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
assert_eq!(vec.num_sequences(), 3);Sourcepub fn into_vecs(self) -> Vec<Vec<T>>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
pub fn into_vecs(self) -> Vec<Vec<T>>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Consumes the SeqVec and returns all sequences as a Vec<Vec<T>>.
This method decodes the entire compressed data, allocating a separate vector for each sequence. The operation requires time proportional to the total number of elements across all sequences.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[10, 20, 30]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let decoded: Vec<Vec<u32>> = vec.into_vecs();
assert_eq!(decoded, vec![vec![1, 2], vec![10, 20, 30]]);Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>
impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>
Sourcepub fn from_parts(
data: B,
bit_offsets_data: B,
bit_offsets_len: usize,
bit_offsets_num_bits: usize,
encoding: Codes,
) -> Result<Self, SeqVecError>
pub fn from_parts( data: B, bit_offsets_data: B, bit_offsets_len: usize, bit_offsets_num_bits: usize, encoding: Codes, ) -> Result<Self, SeqVecError>
Creates a SeqVec from raw components for zero-copy views.
This constructor is intended for advanced use cases such as memory-mapping
a pre-built SeqVec from disk or creating a borrowed view.
§Arguments
data- The compressed bitstream buffer.bit_offsets_data- The buffer containing the bit offsets index.bit_offsets_len- Number of entries in the bit offsets index (N+1).bit_offsets_num_bits- Bit width of each entry in the offsets index.encoding- The codec used for compression.
§Errors
Returns SeqVecError::InvalidParameters if:
bit_offsets_lenis zero (must have at least the sentinel entry).- The underlying
FixedVecconstruction fails.
§Safety Considerations
The caller must ensure that:
datacontains valid compressed data encoded withencoding. Invalid data will cause panics or incorrect results during decoding.bit_offsets_datacontains monotonically increasing bit positions. Unsorted offsets will cause out-of-order or corrupted sequence retrieval.- The sentinel value (final bit offset) does not exceed the total bits
in
data. Violations cause panics during decoding. - All bit positions fall within valid boundaries of the bitstream.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
use compressed_intvec::fixed::FixedVec;
use dsi_bitstream::prelude::LE;
use dsi_bitstream::impls::{BufBitWriter, MemWordWriterVec};
use dsi_bitstream::prelude::{BitWrite, CodesWrite};
// Create a simple vector using high-level API
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// In a real zero-copy scenario, these would come from disk/memory-map
let data = vec.as_limbs().to_vec();
let offsets_ref = vec.bit_offsets_ref();
// Verify structure is sound before reconstruction
assert_eq!(vec.num_sequences(), 2);Sourcepub fn from_parts_with_lengths(
data: B,
bit_offsets_data: B,
bit_offsets_len: usize,
bit_offsets_num_bits: usize,
seq_lengths: Option<FixedVec<u64, u64, E, Vec<u64>>>,
encoding: Codes,
) -> Result<Self, SeqVecError>
pub fn from_parts_with_lengths( data: B, bit_offsets_data: B, bit_offsets_len: usize, bit_offsets_num_bits: usize, seq_lengths: Option<FixedVec<u64, u64, E, Vec<u64>>>, encoding: Codes, ) -> Result<Self, SeqVecError>
Creates a SeqVec from raw components with optional stored lengths.
Use this variant when you have pre-computed sequence lengths from an
earlier encoding. The seq_lengths parameter must be consistent with
bit_offsets when provided (element count must equal num_sequences()).
§Errors
Returns SeqVecError::InvalidParameters if the number of lengths does
not equal the number of sequences.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
// Typical usage: start with high-level API
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Verify structure
assert!(!vec.has_stored_lengths());
assert_eq!(vec.num_sequences(), 2);Sourcepub unsafe fn from_parts_unchecked(
data: B,
bit_offsets: FixedVec<u64, u64, E, B>,
encoding: Codes,
) -> Self
pub unsafe fn from_parts_unchecked( data: B, bit_offsets: FixedVec<u64, u64, E, B>, encoding: Codes, ) -> Self
Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>
impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>
Sourcepub fn num_sequences(&self) -> usize
pub fn num_sequences(&self) -> usize
Returns the number of sequences stored.
This is O(1) as it is derived from the bit offsets index length.
Sourcepub fn bit_offsets_ref(&self) -> &FixedVec<u64, u64, E, B>
pub fn bit_offsets_ref(&self) -> &FixedVec<u64, u64, E, B>
Returns a reference to the bit offsets index.
Sourcepub fn has_stored_lengths(&self) -> bool
pub fn has_stored_lengths(&self) -> bool
Returns true if explicit sequence lengths were stored at construction time.
Sourcepub fn sequence_len(&self, index: usize) -> Option<usize>
pub fn sequence_len(&self, index: usize) -> Option<usize>
Returns the length of sequence index if explicit lengths are stored.
Returns None if index is out of bounds or if lengths were not
stored at construction time. Use has_stored_lengths
to distinguish between these cases.
If lengths are stored, this query completes in O(1) time. Otherwise,
determining sequence length requires full iteration. Store lengths at
construction time via SeqVecBuilder::store_lengths
when O(1) length queries are needed.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[10, 20]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Without storing lengths, returns None
assert_eq!(vec.sequence_len(0), None);
assert!(!vec.has_stored_lengths());Sourcepub fn total_bits(&self) -> u64
pub fn total_bits(&self) -> u64
Returns the total number of bits in the compressed data.
This is the sentinel value at the end of the bit offsets index.
Sourcepub fn sequence_start_bit(&self, index: usize) -> Option<u64>
pub fn sequence_start_bit(&self, index: usize) -> Option<u64>
Returns the bit offset where sequence index starts in the compressed data.
Returns None if index >= num_sequences(). This is useful for
understanding the compression footprint or verifying sequence boundaries.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// First sequence always starts at bit 0
assert_eq!(vec.sequence_start_bit(0), Some(0));
// Second sequence starts after the first
assert!(vec.sequence_start_bit(1).is_some());
// Out of bounds
assert_eq!(vec.sequence_start_bit(2), None);Sourcepub unsafe fn sequence_start_bit_unchecked(&self, index: usize) -> u64
pub unsafe fn sequence_start_bit_unchecked(&self, index: usize) -> u64
Returns the bit offset where sequence index starts, without bounds checking.
§Safety
The caller must ensure index < num_sequences().
Sourcepub unsafe fn sequence_end_bit_unchecked(&self, index: usize) -> u64
pub unsafe fn sequence_end_bit_unchecked(&self, index: usize) -> u64
Returns the bit offset immediately after sequence index ends.
This is equivalent to the start bit of the next sequence, or the total bit length for the final sequence. Useful for calculating per-sequence compression footprint.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let start = vec.sequence_start_bit(0).unwrap();
let end = unsafe { vec.sequence_end_bit_unchecked(0) };
println!("Sequence 0 occupies {} bits", end - start);§Safety
The caller must ensure index < num_sequences().
Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Sourcepub fn get(&self, index: usize) -> Option<SeqIter<'_, T, E>>
pub fn get(&self, index: usize) -> Option<SeqIter<'_, T, E>>
Returns an iterator over the elements of sequence index.
Returns None if index >= num_sequences().
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2, 3], &[4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let first: Vec<u32> = vec.get(0).unwrap().collect();
assert_eq!(first, vec![1, 2, 3]);Sourcepub unsafe fn get_unchecked(&self, index: usize) -> SeqIter<'_, T, E> ⓘ
pub unsafe fn get_unchecked(&self, index: usize) -> SeqIter<'_, T, E> ⓘ
Returns an iterator over the elements of sequence index without
bounds checking.
§Safety
Calling this method with index >= num_sequences() is undefined behavior.
Sourcepub fn decode_vec(&self, index: usize) -> Option<Vec<T>>
pub fn decode_vec(&self, index: usize) -> Option<Vec<T>>
Returns the elements of sequence index as a newly allocated Vec.
Returns None if index >= num_sequences().
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[10, 20, 30]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
assert_eq!(vec.decode_vec(0), Some(vec![10, 20, 30]));
assert_eq!(vec.decode_vec(1), None);Sourcepub unsafe fn decode_vec_unchecked(&self, index: usize) -> Vec<T>
pub unsafe fn decode_vec_unchecked(&self, index: usize) -> Vec<T>
Returns the elements of sequence index as a newly allocated Vec
without bounds checking.
§Safety
Calling this method with index >= num_sequences() is undefined behavior.
Sourcepub fn decode_into(&self, index: usize, buf: &mut Vec<T>) -> Option<usize>
pub fn decode_into(&self, index: usize, buf: &mut Vec<T>) -> Option<usize>
Decodes sequence index into the provided buffer.
The buffer is cleared before use. Returns the number of elements
decoded, or None if index >= num_sequences().
This method is more efficient than decode_vec when
reusing a buffer across multiple calls.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let mut buf = Vec::new();
assert_eq!(vec.decode_into(0, &mut buf), Some(2));
assert_eq!(buf, vec![1, 2]);
// Buffer is reused (cleared internally).
assert_eq!(vec.decode_into(1, &mut buf), Some(3));
assert_eq!(buf, vec![3, 4, 5]);Sourcepub unsafe fn decode_into_unchecked(
&self,
index: usize,
buf: &mut Vec<T>,
) -> usize
pub unsafe fn decode_into_unchecked( &self, index: usize, buf: &mut Vec<T>, ) -> usize
Decodes sequence index into the provided buffer without bounds checking.
§Safety
Calling this method with index >= num_sequences() is undefined behavior.
Sourcepub fn iter(&self) -> SeqVecIter<'_, T, E, B> ⓘ
pub fn iter(&self) -> SeqVecIter<'_, T, E, B> ⓘ
Returns an iterator over all sequences.
Each element of the returned iterator is a SeqIter for the
corresponding sequence.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3], &[4, 5, 6]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
for (i, seq) in vec.iter().enumerate() {
println!("Sequence {}: {:?}", i, seq.collect::<Vec<_>>());
}Sourcepub fn reader(&self) -> SeqVecReader<'_, T, E, B>
pub fn reader(&self) -> SeqVecReader<'_, T, E, B>
Creates a reusable reader for convenient random access to sequences.
The returned SeqVecReader provides a convenient interface for
performing multiple sequence retrievals. While the current implementation
is a thin wrapper, it serves as a natural extension point for future
optimizations such as position tracking or caching.
§Performance Considerations
- Zero-copy iteration: Returned iterators borrow directly from the compressed data without intermediate allocations.
- Stateless operation: Each call to
getis independent and creates a freshSeqIter. - Convenience methods: The reader provides
decode_vecanddecode_intofor common patterns.
§When to Use
Use a reader when:
- You prefer a consistent interface for multiple accesses.
- You want to use convenience methods like
decode_vecordecode_into. - Future stateful optimizations would benefit your access pattern.
For single queries or simple iteration, direct calls to get
or iter are equally efficient.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let mut reader = vec.reader();
// Perform multiple random accesses efficiently
assert_eq!(reader.decode_vec(2), Some(vec![6]));
assert_eq!(reader.decode_vec(0), Some(vec![1, 2]));
if let Some(seq) = reader.decode_vec(1) {
for value in seq {
assert!(value <= 5);
}
}Sourcepub fn slice(
&self,
start: usize,
len: usize,
) -> Option<SeqVecSlice<'_, T, E, B>>
pub fn slice( &self, start: usize, len: usize, ) -> Option<SeqVecSlice<'_, T, E, B>>
Creates a zero-copy slice of a contiguous range of sequences.
The slice provides a view into len sequences starting at start,
without copying the underlying compressed data.
§Arguments
start- The index of the first sequence in the slice.len- The number of sequences to include in the slice.
§Returns
Returns Some(SeqVecSlice) if the range is valid, or None if
start + len exceeds the number of sequences.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1, 2], &[3, 4, 5], &[6], &[7, 8]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
// Create a slice of sequences 1 and 2
let slice = vec.slice(1, 2).unwrap();
assert_eq!(slice.len(), 2);
// Index 0 of the slice refers to sequence 1 of the original vector
let seq: Vec<u32> = slice.get(0).unwrap().collect();
assert_eq!(seq, vec![3, 4, 5]);Sourcepub fn split_at(&self, mid: usize) -> Option<SeqVecSlicePair<'_, T, E, B>>
pub fn split_at(&self, mid: usize) -> Option<SeqVecSlicePair<'_, T, E, B>>
Splits the vector into two slices at the specified index.
Returns a tuple of two slices: the first contains sequences [0, mid)
and the second contains sequences [mid, len).
§Returns
Returns Some((left_slice, right_slice)) if mid <= num_sequences(),
or None if mid is out of bounds.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[&[1], &[2], &[3], &[4]];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let (left, right) = vec.split_at(2).unwrap();
assert_eq!(left.len(), 2);
assert_eq!(right.len(), 2);
assert_eq!(left.decode_vec(0), Some(vec![1]));
assert_eq!(right.decode_vec(0), Some(vec![3]));Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<T: Storable, E: Endianness, B: AsRef<[u64]>> SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Sourcepub fn decode_many(&self, indices: &[usize]) -> Result<Vec<Vec<T>>, SeqVecError>
pub fn decode_many(&self, indices: &[usize]) -> Result<Vec<Vec<T>>, SeqVecError>
Retrieves multiple sequences by their indices.
This method decodes the requested sequences in sorted order for efficient sequential access to the bitstream, then returns them in the order corresponding to the input indices.
§Arguments
indices- A slice of sequence indices to retrieve.
§Returns
Ok(Vec<Vec<T>>)containing the sequences in the order ofindices.Err(SeqVecError::IndexOutOfBounds(idx))if any index is out of bounds.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[
&[1, 2, 3],
&[10, 20],
&[100, 200, 300],
&[1000],
];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let indices = [3, 0, 2];
let sequences = vec.decode_many(&indices)?;
assert_eq!(sequences, vec![
vec![1000],
vec![1, 2, 3],
vec![100, 200, 300],
]);Sourcepub unsafe fn decode_many_unchecked(&self, indices: &[usize]) -> Vec<Vec<T>>
pub unsafe fn decode_many_unchecked(&self, indices: &[usize]) -> Vec<Vec<T>>
Retrieves multiple sequences without bounds checking.
§Safety
Calling this method with any out-of-bounds index is undefined behavior.
Sourcepub fn decode_many_into(
&self,
indices: &[usize],
output: &mut Vec<Vec<T>>,
) -> Result<(), SeqVecError>
pub fn decode_many_into( &self, indices: &[usize], output: &mut Vec<Vec<T>>, ) -> Result<(), SeqVecError>
Decodes multiple sequences into a caller-provided output vector.
The output vector is cleared and resized to match indices.len(). Each
sequence is decoded into its corresponding slot, maintaining the order
specified by indices. This is more efficient than calling
decode_vec repeatedly, as the decoding process
traverses the compressed data in sorted order for better cache locality.
§Errors
Returns SeqVecError::IndexOutOfBounds if any index is out of bounds.
§Examples
use compressed_intvec::seq::{SeqVec, LESeqVec};
let sequences: &[&[u32]] = &[
&[1, 2],
&[10, 20],
&[100, 200, 300],
];
let vec: LESeqVec<u32> = SeqVec::from_slices(sequences)?;
let indices = [2, 0, 1];
let mut output = Vec::new();
vec.decode_many_into(&indices, &mut output)?;
assert_eq!(output, vec![
vec![100, 200, 300],
vec![1, 2],
vec![10, 20],
]);Sourcepub unsafe fn decode_many_into_unchecked(
&self,
indices: &[usize],
output: &mut [Vec<T>],
)
pub unsafe fn decode_many_into_unchecked( &self, indices: &[usize], output: &mut [Vec<T>], )
Decodes multiple sequences into a caller-provided output slice without bounds checking.
§Safety
Calling this method with any out-of-bounds index is undefined behavior.
Trait Implementations§
Source§impl<T: Clone + Storable, E: Clone + Endianness, B: Clone + AsRef<[u64]>> Clone for SeqVec<T, E, B>
impl<T: Clone + Storable, E: Clone + Endianness, B: Clone + AsRef<[u64]>> Clone for SeqVec<T, E, B>
Source§impl<T: Debug + Storable, E: Debug + Endianness, B: Debug + AsRef<[u64]>> Debug for SeqVec<T, E, B>
impl<T: Debug + Storable, E: Debug + Endianness, B: Debug + AsRef<[u64]>> Debug for SeqVec<T, E, B>
Source§impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> IntoIterator for &'a SeqVec<T, E, B>where
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<'a, T: Storable, E: Endianness, B: AsRef<[u64]>> IntoIterator for &'a SeqVec<T, E, B>where
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Source§impl<T: Storable + 'static, E: Endianness + 'static> IntoIterator for SeqVec<T, E, Vec<u64>>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<T: Storable + 'static, E: Endianness + 'static> IntoIterator for SeqVec<T, E, Vec<u64>>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]> + MemDbgImpl + FlatType> MemDbgImpl for SeqVec<T, E, B>
impl<T: Storable, E: Endianness, B: AsRef<[u64]> + MemDbgImpl + FlatType> MemDbgImpl for SeqVec<T, E, B>
fn _mem_dbg_rec_on( &self, writer: &mut impl Write, total_size: usize, max_depth: usize, prefix: &mut String, _is_last: bool, flags: DbgFlags, _dbg_refs: &mut HashSet<usize>, ) -> Result
fn _mem_dbg_depth_on( &self, writer: &mut impl Write, total_size: usize, max_depth: usize, prefix: &mut String, field_name: Option<&str>, is_last: bool, padded_size: usize, flags: DbgFlags, dbg_refs: &mut HashSet<usize>, ) -> Result<(), Error>
Source§fn _mem_dbg_depth_on_impl(
&self,
writer: &mut impl Write,
total_size: usize,
max_depth: usize,
prefix: &mut String,
field_name: Option<&str>,
is_last: bool,
padded_size: usize,
flags: DbgFlags,
dbg_refs: &mut HashSet<usize>,
ref_display: RefDisplay,
) -> Result<(), Error>
fn _mem_dbg_depth_on_impl( &self, writer: &mut impl Write, total_size: usize, max_depth: usize, prefix: &mut String, field_name: Option<&str>, is_last: bool, padded_size: usize, flags: DbgFlags, dbg_refs: &mut HashSet<usize>, ref_display: RefDisplay, ) -> Result<(), Error>
Source§impl<T: Storable, E: Endianness, B: AsRef<[u64]> + MemSize + FlatType> MemSize for SeqVec<T, E, B>
impl<T: Storable, E: Endianness, B: AsRef<[u64]> + MemSize + FlatType> MemSize for SeqVec<T, E, B>
Source§impl<'a, T, E, B> PartialEq<&SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<'a, T, E, B> PartialEq<&SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Source§impl<'a, T, E, B> PartialEq<SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<'a, T, E, B> PartialEq<SeqVec<T, E, B>> for SeqVecSlice<'a, T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Source§impl<'a, T, E, B> PartialEq<SeqVecSlice<'a, T, E, B>> for SeqVec<T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<'a, T, E, B> PartialEq<SeqVecSlice<'a, T, E, B>> for SeqVec<T, E, B>where
T: Storable + PartialEq,
E: Endianness,
B: AsRef<[u64]>,
for<'b> BufBitReader<E, MemWordReader<u64, &'b [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Source§impl<T: Storable + PartialEq, E: Endianness, B: AsRef<[u64]>> PartialEq for SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
impl<T: Storable + PartialEq, E: Endianness, B: AsRef<[u64]>> PartialEq for SeqVec<T, E, B>where
for<'a> BufBitReader<E, MemWordReader<u64, &'a [u64], true>, DefaultReadParams>: BitRead<E, Error = Infallible> + CodesRead<E> + BitSeek<Error = Infallible>,
Auto Trait Implementations§
impl<T, E, B> Freeze for SeqVec<T, E, B>where
B: Freeze,
impl<T, E, B> RefUnwindSafe for SeqVec<T, E, B>
impl<T, E, B> Send for SeqVec<T, E, B>
impl<T, E, B> Sync for SeqVec<T, E, B>
impl<T, E, B> Unpin for SeqVec<T, E, B>
impl<T, E, B> UnsafeUnpin for SeqVec<T, E, B>where
B: UnsafeUnpin,
impl<T, E, B> UnwindSafe for SeqVec<T, E, B>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
impl<T, U> CastableInto<U> for Twhere
U: CastableFrom<T>,
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> DowncastableFrom<T> for T
impl<T> DowncastableFrom<T> for T
Source§fn downcast_from(value: T) -> T
fn downcast_from(value: T) -> T
Source§impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
impl<T, U> DowncastableInto<U> for Twhere
U: DowncastableFrom<T>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> MemDbg for Twhere
T: MemDbgImpl,
impl<T> MemDbg for Twhere
T: MemDbgImpl,
Source§fn mem_dbg(&self, flags: DbgFlags) -> Result<(), Error>
fn mem_dbg(&self, flags: DbgFlags) -> Result<(), Error>
Source§fn mem_dbg_on(
&self,
writer: &mut impl Write,
flags: DbgFlags,
) -> Result<(), Error>
fn mem_dbg_on( &self, writer: &mut impl Write, flags: DbgFlags, ) -> Result<(), Error>
core::fmt::Write debug info about the structure memory
usage, expanding all levels of nested structures.Source§fn mem_dbg_depth(&self, max_depth: usize, flags: DbgFlags) -> Result<(), Error>
fn mem_dbg_depth(&self, max_depth: usize, flags: DbgFlags) -> Result<(), Error>
mem_dbg, but expanding only up to max_depth
levels of nested structures.Source§fn mem_dbg_depth_on(
&self,
writer: &mut impl Write,
max_depth: usize,
flags: DbgFlags,
) -> Result<(), Error>
fn mem_dbg_depth_on( &self, writer: &mut impl Write, max_depth: usize, flags: DbgFlags, ) -> Result<(), Error>
core::fmt::Write debug info about the structure memory
usage as mem_dbg_on, but expanding only up to
max_depth levels of nested structures.