noodles_sam/record/
quality_scores.rs1use std::io;
4
5#[derive(Debug, Eq, PartialEq)]
7pub struct QualityScores<'a>(&'a [u8]);
8
9impl<'a> QualityScores<'a> {
10 pub fn new(buf: &'a [u8]) -> Self {
19 Self(buf)
20 }
21
22 pub fn is_empty(&self) -> bool {
36 self.0.is_empty()
37 }
38
39 pub fn len(&self) -> usize {
49 self.0.len()
50 }
51}
52
53impl crate::alignment::record::QualityScores for QualityScores<'_> {
54 fn is_empty(&self) -> bool {
55 self.is_empty()
56 }
57
58 fn len(&self) -> usize {
59 self.len()
60 }
61
62 fn iter(&self) -> Box<dyn Iterator<Item = io::Result<u8>> + '_> {
63 const OFFSET: u8 = b'!';
64
65 Box::new(self.as_ref().iter().map(|&b| {
66 b.checked_sub(OFFSET)
67 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid score"))
68 }))
69 }
70}
71
72impl AsRef<[u8]> for QualityScores<'_> {
73 fn as_ref(&self) -> &[u8] {
74 self.0
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use crate::alignment::record::QualityScores as _;
81
82 use super::*;
83
84 #[test]
85 fn test_iter() -> io::Result<()> {
86 let quality_scores = QualityScores::new(b"NDLS");
87
88 assert_eq!(
89 quality_scores.iter().collect::<io::Result<Vec<_>>>()?,
90 [45, 35, 43, 50]
91 );
92
93 let quality_scores = QualityScores::new(&[0x00]);
94
95 assert!(matches!(
96 quality_scores.iter().collect::<io::Result<Vec<_>>>(),
97 Err(e) if e.kind() == io::ErrorKind::InvalidData
98 ));
99
100 Ok(())
101 }
102}