use std::ops::Range;
use crate::fastq_frame;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RecordRef {
pub name: Range<u32>,
pub seq: Range<u32>,
pub plus: Range<u32>,
pub qual: Range<u32>,
}
#[derive(Debug, Clone, Copy)]
pub struct FastqRecord<'a> {
pub(crate) bytes: &'a [u8],
pub(crate) record: &'a RecordRef,
}
impl<'a> FastqRecord<'a> {
#[inline]
pub fn name(self) -> &'a [u8] {
&self.bytes[to_usize(self.record.name.clone())]
}
#[inline]
pub fn name_without_at(self) -> &'a [u8] {
let name = self.name();
name.strip_prefix(b"@").unwrap_or(name)
}
#[inline]
pub fn id_token(self) -> &'a [u8] {
let name = self.name_without_at();
let end = name
.iter()
.position(u8::is_ascii_whitespace)
.unwrap_or(name.len());
&name[..end]
}
#[inline]
pub fn pair_normalized_id(self) -> &'a [u8] {
strip_pair_suffix(self.id_token())
}
#[inline]
pub fn seq(self) -> &'a [u8] {
&self.bytes[to_usize(self.record.seq.clone())]
}
#[inline]
pub fn plus(self) -> &'a [u8] {
&self.bytes[to_usize(self.record.plus.clone())]
}
#[inline]
pub fn qual(self) -> &'a [u8] {
&self.bytes[to_usize(self.record.qual.clone())]
}
}
#[derive(Debug, Clone, Copy)]
pub struct FastqVisitRecord<'a> {
pub(crate) name: &'a [u8],
pub(crate) seq: &'a [u8],
pub(crate) plus: &'a [u8],
pub(crate) qual: &'a [u8],
}
impl<'a> FastqVisitRecord<'a> {
#[inline]
pub fn name(self) -> &'a [u8] {
self.name
}
#[inline]
pub fn seq(self) -> &'a [u8] {
self.seq
}
#[inline]
pub fn plus(self) -> &'a [u8] {
self.plus
}
#[inline]
pub fn qual(self) -> &'a [u8] {
self.qual
}
}
#[inline]
pub fn strip_pair_suffix(id: &[u8]) -> &[u8] {
fastq_frame::strip_pair_suffix(id)
}
#[inline]
pub(crate) fn to_u32_range(range: Range<usize>) -> Range<u32> {
debug_assert!(u32::try_from(range.end).is_ok());
range.start as u32..range.end as u32
}
#[inline]
fn to_usize(range: Range<u32>) -> Range<usize> {
range.start as usize..range.end as usize
}