noodles_sam/record/
data.rs1pub mod field;
4
5use std::{fmt, io, iter};
6
7use self::field::parse_field;
8use crate::alignment::record::data::field::{Tag, Value};
9
10pub struct Data<'a>(&'a [u8]);
12
13impl<'a> Data<'a> {
14 pub(super) fn new(buf: &'a [u8]) -> Self {
15 Self(buf)
16 }
17
18 pub fn is_empty(&self) -> bool {
20 self.0.is_empty()
21 }
22
23 pub fn iter(&self) -> impl Iterator<Item = io::Result<(Tag, Value<'_>)>> + '_ {
25 let mut src = self.0;
26
27 iter::from_fn(move || {
28 if src.is_empty() {
29 None
30 } else {
31 Some(parse_field(&mut src))
32 }
33 })
34 }
35}
36
37impl fmt::Debug for Data<'_> {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 let mut formatter = f.debug_map();
40
41 for result in self.iter() {
42 let (tag, value) = result.map_err(|_| fmt::Error)?;
43 formatter.entry(&tag, &value);
44 }
45
46 formatter.finish()
47 }
48}
49
50impl crate::alignment::record::Data for Data<'_> {
51 fn is_empty(&self) -> bool {
52 self.is_empty()
53 }
54
55 fn get(&self, tag: &Tag) -> Option<io::Result<Value<'_>>> {
56 for result in self.iter() {
57 match result {
58 Ok((t, value)) => {
59 if &t == tag {
60 return Some(Ok(value));
61 }
62 }
63 Err(e) => return Some(Err(e)),
64 }
65 }
66
67 None
68 }
69
70 fn iter(&self) -> Box<dyn Iterator<Item = io::Result<(Tag, Value<'_>)>> + '_> {
71 Box::new(self.iter())
72 }
73}
74
75impl AsRef<[u8]> for Data<'_> {
76 fn as_ref(&self) -> &[u8] {
77 self.0
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_iter() -> io::Result<()> {
87 let data = Data::new(b"");
88 assert!(data.iter().next().is_none());
89
90 let data = Data::new(b"NH:i:1");
91 let actual: Vec<_> = data.iter().collect::<io::Result<_>>()?;
92
93 assert_eq!(actual.len(), 1);
94
95 let (actual_tag, actual_value) = &actual[0];
96 assert_eq!(actual_tag, &Tag::ALIGNMENT_HIT_COUNT);
97 assert!(matches!(actual_value, Value::Int32(1)));
98
99 Ok(())
100 }
101}