pub mod direct_reader;
pub mod pool;
pub mod reader;
pub mod split_writer;
pub mod writer;
pub use direct_reader::{DirectFastqReader, DirectPairedFastqReader};
pub use pool::{BatchPool, FixedBatch, ReadPool};
pub use reader::{create_stdin_reader, FastqReader, PairedFastqReader};
pub use split_writer::{PairedSplitWriter, SplitWriter};
pub use writer::{create_stdout_writer, CompressionType, FastqWriter, PairedFastqWriter, StdoutFastqWriter};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OwnedRecord {
pub name: Vec<u8>,
pub seq: Vec<u8>,
pub qual: Vec<u8>,
}
impl OwnedRecord {
pub fn new(name: Vec<u8>, seq: Vec<u8>, qual: Vec<u8>) -> Self {
Self { name, seq, qual }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
name: Vec::with_capacity(capacity / 4), seq: Vec::with_capacity(capacity),
qual: Vec::with_capacity(capacity),
}
}
#[inline]
pub fn clear(&mut self) {
self.name.clear();
self.seq.clear();
self.qual.clear();
}
#[inline]
pub fn set_from(&mut self, name: &[u8], seq: &[u8], qual: &[u8]) {
self.name.clear();
self.name.extend_from_slice(name);
self.seq.clear();
self.seq.extend_from_slice(seq);
self.qual.clear();
self.qual.extend_from_slice(qual);
}
#[inline]
pub fn len(&self) -> usize {
self.seq.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.seq.is_empty()
}
pub fn name_str(&self) -> std::borrow::Cow<'_, str> {
String::from_utf8_lossy(&self.name)
}
pub fn seq_str(&self) -> std::borrow::Cow<'_, str> {
String::from_utf8_lossy(&self.seq)
}
pub fn qual_str(&self) -> std::borrow::Cow<'_, str> {
String::from_utf8_lossy(&self.qual)
}
#[inline]
pub fn seq(&self) -> &[u8] {
&self.seq
}
#[inline]
pub fn qual(&self) -> &[u8] {
&self.qual
}
#[inline]
pub fn id(&self) -> &[u8] {
&self.name
}
#[inline]
pub fn append_slices_to_buffer(buffer: &mut Vec<u8>, name: &[u8], seq: &[u8], qual: &[u8]) {
buffer.push(b'@');
buffer.extend_from_slice(name);
buffer.push(b'\n');
buffer.extend_from_slice(seq);
buffer.extend_from_slice(b"\n+\n");
buffer.extend_from_slice(qual);
buffer.push(b'\n');
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_owned_record_creation() {
let record = OwnedRecord::new(
b"read1".to_vec(),
b"ACGT".to_vec(),
b"IIII".to_vec(),
);
assert_eq!(record.name, b"read1");
assert_eq!(record.seq, b"ACGT");
assert_eq!(record.qual, b"IIII");
}
#[test]
fn test_owned_record_len() {
let record = OwnedRecord::new(
b"read1".to_vec(),
b"ACGTACGT".to_vec(),
b"IIIIIIII".to_vec(),
);
assert_eq!(record.len(), 8);
assert!(!record.is_empty());
}
#[test]
fn test_owned_record_empty() {
let record = OwnedRecord::new(Vec::new(), Vec::new(), Vec::new());
assert!(record.is_empty());
assert_eq!(record.len(), 0);
}
#[test]
fn test_owned_record_string_conversion() {
let record = OwnedRecord::new(
b"read1".to_vec(),
b"ACGT".to_vec(),
b"IIII".to_vec(),
);
assert_eq!(record.name_str(), "read1");
assert_eq!(record.seq_str(), "ACGT");
assert_eq!(record.qual_str(), "IIII");
}
#[test]
fn test_owned_record_clone() {
let record = OwnedRecord::new(
b"read1".to_vec(),
b"ACGT".to_vec(),
b"IIII".to_vec(),
);
let cloned = record.clone();
assert_eq!(record, cloned);
}
#[test]
fn test_owned_record_with_capacity() {
let record = OwnedRecord::with_capacity(256);
assert!(record.is_empty());
assert!(record.seq.capacity() >= 256);
assert!(record.qual.capacity() >= 256);
assert!(record.name.capacity() >= 64); }
#[test]
fn test_owned_record_clear() {
let mut record = OwnedRecord::new(
b"read1".to_vec(),
b"ACGT".to_vec(),
b"IIII".to_vec(),
);
let name_cap = record.name.capacity();
let seq_cap = record.seq.capacity();
let qual_cap = record.qual.capacity();
record.clear();
assert!(record.is_empty());
assert!(record.name.is_empty());
assert!(record.qual.is_empty());
assert!(record.name.capacity() >= name_cap);
assert!(record.seq.capacity() >= seq_cap);
assert!(record.qual.capacity() >= qual_cap);
}
#[test]
fn test_owned_record_set_from() {
let mut record = OwnedRecord::with_capacity(256);
record.set_from(b"read1", b"ACGTACGT", b"IIIIIIII");
assert_eq!(record.name, b"read1");
assert_eq!(record.seq, b"ACGTACGT");
assert_eq!(record.qual, b"IIIIIIII");
record.set_from(b"read2", b"GGGG", b"HHHH");
assert_eq!(record.name, b"read2");
assert_eq!(record.seq, b"GGGG");
assert_eq!(record.qual, b"HHHH");
assert!(record.seq.capacity() >= 8);
}
#[test]
fn test_owned_record_set_from_preserves_capacity() {
let mut record = OwnedRecord::with_capacity(1024);
let initial_cap = record.seq.capacity();
record.set_from(b"x", b"ACGT", b"IIII");
assert!(record.seq.capacity() >= initial_cap);
}
}