noodles_sam/io/writer/record/
cigar.rs1use std::io::{self, Write};
2
3use crate::{
4 alignment::record::{
5 cigar::{op::Kind, Op},
6 Cigar,
7 },
8 io::writer::num,
9};
10
11pub fn write_cigar<W, C>(writer: &mut W, cigar: &C) -> io::Result<()>
36where
37 W: Write,
38 C: Cigar,
39{
40 use super::MISSING;
41
42 if cigar.is_empty() {
43 writer.write_all(&[MISSING])?;
44 } else {
45 for result in cigar.iter() {
46 let op = result?;
47 write_op(writer, op)?;
48 }
49 }
50
51 Ok(())
52}
53
54fn write_op<W>(writer: &mut W, op: Op) -> io::Result<()>
55where
56 W: Write,
57{
58 num::write_usize(writer, op.len())?;
59 write_kind(writer, op.kind())?;
60 Ok(())
61}
62
63fn write_kind<W>(writer: &mut W, kind: Kind) -> io::Result<()>
64where
65 W: Write,
66{
67 let c = match kind {
68 Kind::Match => b'M',
69 Kind::Insertion => b'I',
70 Kind::Deletion => b'D',
71 Kind::Skip => b'N',
72 Kind::SoftClip => b'S',
73 Kind::HardClip => b'H',
74 Kind::Pad => b'P',
75 Kind::SequenceMatch => b'=',
76 Kind::SequenceMismatch => b'X',
77 };
78
79 writer.write_all(&[c])
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::alignment::record_buf::Cigar as CigarBuf;
86
87 #[test]
88 fn test_write_cigar() -> io::Result<()> {
89 fn t(buf: &mut Vec<u8>, cigar: &CigarBuf, expected: &[u8]) -> io::Result<()> {
90 buf.clear();
91 write_cigar(buf, cigar)?;
92 assert_eq!(buf, expected);
93 Ok(())
94 }
95
96 let mut buf = Vec::new();
97
98 let cigar = CigarBuf::default();
99 t(&mut buf, &cigar, b"*")?;
100
101 let cigar = [Op::new(Kind::Match, 4)].into_iter().collect();
102 t(&mut buf, &cigar, b"4M")?;
103
104 let cigar: CigarBuf = [Op::new(Kind::Match, 4), Op::new(Kind::HardClip, 2)]
105 .into_iter()
106 .collect();
107 t(&mut buf, &cigar, b"4M2H")?;
108
109 Ok(())
110 }
111
112 #[test]
113 fn test_write_op() -> io::Result<()> {
114 let mut buf = Vec::new();
115
116 buf.clear();
117 write_op(&mut buf, Op::new(Kind::Match, 1))?;
118 assert_eq!(buf, b"1M");
119
120 buf.clear();
121 write_op(&mut buf, Op::new(Kind::Match, 1 << 28))?;
122 assert_eq!(buf, b"268435456M");
123
124 Ok(())
125 }
126
127 #[test]
128 fn test_write_kind() -> io::Result<()> {
129 fn t(buf: &mut Vec<u8>, kind: Kind, expected: &[u8]) -> io::Result<()> {
130 buf.clear();
131 write_kind(buf, kind)?;
132 assert_eq!(buf, expected);
133 Ok(())
134 }
135
136 let mut buf = Vec::new();
137
138 t(&mut buf, Kind::Match, b"M")?;
139 t(&mut buf, Kind::Insertion, b"I")?;
140 t(&mut buf, Kind::Deletion, b"D")?;
141 t(&mut buf, Kind::Skip, b"N")?;
142 t(&mut buf, Kind::SoftClip, b"S")?;
143 t(&mut buf, Kind::HardClip, b"H")?;
144 t(&mut buf, Kind::Pad, b"P")?;
145 t(&mut buf, Kind::SequenceMatch, b"=")?;
146 t(&mut buf, Kind::SequenceMismatch, b"X")?;
147
148 Ok(())
149 }
150}