noodles_sam/record/quality_scores.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//! Raw SAM record quality scores.
use std::io;
/// Raw SAM record quality scores.
#[derive(Debug, Eq, PartialEq)]
pub struct QualityScores<'a>(&'a [u8]);
impl<'a> QualityScores<'a> {
/// Creates raw SAM record quality scores.
///
/// # Examples
///
/// ```
/// use noodles_sam::record::QualityScores;
/// let quality_scores = QualityScores::new(b"NDLS");
/// ```
pub fn new(buf: &'a [u8]) -> Self {
Self(buf)
}
/// Returns whether there are any scores.
///
/// # Examples
///
/// ```
/// use noodles_sam::record::QualityScores;
///
/// let quality_scores = QualityScores::new(b"");
/// assert!(quality_scores.is_empty());
///
/// let quality_scores = QualityScores::new(b"NDLS");
/// assert!(!quality_scores.is_empty());
/// ```
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Returns the number of scores.
///
/// # Examples
///
/// ```
/// use noodles_sam::record::QualityScores;
/// let quality_scores = QualityScores::new(b"NDLS");
/// assert_eq!(quality_scores.len(), 4);
/// ```
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<'a> crate::alignment::record::QualityScores for QualityScores<'a> {
fn is_empty(&self) -> bool {
self.is_empty()
}
fn len(&self) -> usize {
self.len()
}
fn iter(&self) -> Box<dyn Iterator<Item = io::Result<u8>> + '_> {
const OFFSET: u8 = b'!';
Box::new(self.as_ref().iter().map(|&b| {
b.checked_sub(OFFSET)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid score"))
}))
}
}
impl<'a> AsRef<[u8]> for QualityScores<'a> {
fn as_ref(&self) -> &[u8] {
self.0
}
}
#[cfg(test)]
mod tests {
use crate::alignment::record::QualityScores as _;
use super::*;
#[test]
fn test_iter() -> io::Result<()> {
let quality_scores = QualityScores::new(b"NDLS");
assert_eq!(
quality_scores.iter().collect::<io::Result<Vec<_>>>()?,
[45, 35, 43, 50]
);
let quality_scores = QualityScores::new(&[0x00]);
assert!(matches!(
quality_scores.iter().collect::<io::Result<Vec<_>>>(),
Err(e) if e.kind() == io::ErrorKind::InvalidData
));
Ok(())
}
}