From 73b8257841d8eaa9806e5421cca2394eb16610ae Mon Sep 17 00:00:00 2001 From: Igor Martayan Date: Thu, 8 Jan 2026 16:30:03 +0100 Subject: [PATCH 1/2] Add PackedSeqVecBase::from_raw_parts --- src/packed_seq.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/packed_seq.rs b/src/packed_seq.rs index b0eb1d4..68cb956 100644 --- a/src/packed_seq.rs +++ b/src/packed_seq.rs @@ -1371,6 +1371,21 @@ where } } +impl PackedSeqVecBase +where + Bits: SupportedBits, +{ + /// Creates a `SeqVec` from a vector of packed bytes and a length in bp. + /// + /// The vector should have at least 16 bytes of padding after `len`. + /// Otherwise, the vector will be resized to be padded with zeros. + pub fn from_raw_parts(mut seq: Vec, len: usize) -> Self { + assert!(len <= seq.len() * Self::C8); + seq.resize(len.div_ceil(Self::C8) + PADDING, 0); + Self { seq, len } + } +} + impl PackedSeqVecBase<1> { pub fn with_len(n: usize) -> Self { Self { From 8bdd6fa56b088862d121cfbcc0e4f99efedd11c7 Mon Sep 17 00:00:00 2001 From: Igor Martayan Date: Thu, 8 Jan 2026 18:13:02 +0100 Subject: [PATCH 2/2] Add PackedSeqBase::from_raw_parts --- src/packed_seq.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/packed_seq.rs b/src/packed_seq.rs index 68cb956..3d17757 100644 --- a/src/packed_seq.rs +++ b/src/packed_seq.rs @@ -138,7 +138,7 @@ pub struct PackedSeqVecBase where Bits: SupportedBits, { - /// NOTE: We maintain the invariant that this has at least 16 bytes padding + /// NOTE: We maintain the invariant that this has at least 48 bytes of padding /// at the end after `len` finishes. /// This ensures that `read_unaligned` in `as_64` works OK. pub(crate) seq: Vec, @@ -369,10 +369,19 @@ pub const fn rev_u128(word: u128, len: usize) -> u128 { // ====================================================================== -impl PackedSeqBase<'_, B> +impl<'s, const B: usize> PackedSeqBase<'s, B> where Bits: SupportedBits, { + /// Creates a `Seq` from a slice of packed bytes, an offset in bp and a length in bp. + /// + /// The slice should have at least 48 bytes of padding after `offset + len`. + /// Otherwise, the function will panic. + pub fn from_raw_parts(seq: &'s [u8], offset: usize, len: usize) -> Self { + assert!(offset + len + PADDING * Self::C8 <= seq.len() * Self::C8); + Self { seq, offset, len } + } + /// Shrink `seq` to only just cover the data. #[inline(always)] pub fn normalize(&self) -> Self { @@ -467,7 +476,7 @@ where let mask = u64::MAX >> (64 - B * self.len()); // The unaligned read is OK, because we ensure that the underlying `PackedSeqVecBase::seq` always - // has at least 16 bytes (the size of a u128) of padding at the end. + // has at least 48 bytes of padding at the end. if self.len() <= Self::K64 { let x = unsafe { (self.seq.as_ptr() as *const u64).read_unaligned() }; (x >> (B * self.offset)) & mask @@ -500,7 +509,7 @@ where let mask = u128::MAX >> (128 - B * self.len()); // The unaligned read is OK, because we ensure that the underlying `PackedSeqVecBase::seq` always - // has at least 16 bytes (the size of a u128) of padding at the end. + // has at least 48 bytes of padding at the end. let x = unsafe { (self.seq.as_ptr() as *const u128).read_unaligned() }; (x >> (B * self.offset)) & mask } @@ -1377,7 +1386,7 @@ where { /// Creates a `SeqVec` from a vector of packed bytes and a length in bp. /// - /// The vector should have at least 16 bytes of padding after `len`. + /// The vector should have at least 48 bytes of padding after `len`. /// Otherwise, the vector will be resized to be padded with zeros. pub fn from_raw_parts(mut seq: Vec, len: usize) -> Self { assert!(len <= seq.len() * Self::C8);