noodles_sam/io/writer.rs
1//! SAM writer.
2
3mod builder;
4mod header;
5mod num;
6pub mod record;
7
8use std::io::{self, Write};
9
10pub use self::builder::Builder;
11use self::header::write_header;
12pub(crate) use self::record::write_record;
13use crate::{Header, Record};
14
15/// A SAM writer.
16///
17/// The SAM format is comprised of two parts: 1) a header and 2) a list of records.
18///
19/// Each header line is prefixed with an `@` (at sign). The header is optional and may be empty.
20///
21/// SAM records are line-based and follow directly after the header or the start of the file until
22/// EOF.
23///
24/// # Examples
25///
26/// ```
27/// # use std::io;
28/// use noodles_sam as sam;
29///
30/// let mut writer = sam::io::Writer::new(Vec::new());
31///
32/// let header = sam::Header::builder().add_comment("noodles-sam").build();
33/// writer.write_header(&header)?;
34///
35/// let record = sam::Record::default();
36/// writer.write_record(&header, &record)?;
37///
38/// let expected = b"@CO\tnoodles-sam
39/// *\t4\t*\t0\t255\t*\t*\t0\t0\t*\t*
40/// ";
41///
42/// assert_eq!(&writer.get_ref()[..], &expected[..]);
43/// # Ok::<(), io::Error>(())
44/// ```
45pub struct Writer<W>
46where
47 W: Write,
48{
49 inner: W,
50}
51
52impl<W> Writer<W>
53where
54 W: Write,
55{
56 /// Creates a SAM writer.
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use noodles_sam as sam;
62 /// let writer = sam::io::Writer::new(Vec::new());
63 /// ```
64 pub fn new(inner: W) -> Self {
65 Self { inner }
66 }
67
68 /// Returns a reference to the underlying writer.
69 ///
70 /// # Examples
71 ///
72 /// ```
73 /// use noodles_sam as sam;
74 /// let writer = sam::io::Writer::new(Vec::new());
75 /// assert!(writer.get_ref().is_empty());
76 /// ```
77 pub fn get_ref(&self) -> &W {
78 &self.inner
79 }
80
81 /// Returns a mutable reference to the underlying writer.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use noodles_sam as sam;
87 /// let mut writer = sam::io::Writer::new(Vec::new());
88 /// assert!(writer.get_mut().is_empty());
89 /// ```
90 pub fn get_mut(&mut self) -> &mut W {
91 &mut self.inner
92 }
93
94 /// Returns the underlying writer.
95 ///
96 /// # Examples
97 ///
98 /// ```
99 /// use noodles_sam as sam;
100 /// let writer = sam::io::Writer::new(Vec::new());
101 /// assert!(writer.into_inner().is_empty());
102 /// ```
103 pub fn into_inner(self) -> W {
104 self.inner
105 }
106
107 /// Writes a SAM header.
108 ///
109 /// The SAM header is optional, though recommended to include. A call to this method can be
110 /// omitted if it is empty.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// # use std::io;
116 /// use noodles_sam as sam;
117 /// let mut writer = sam::io::Writer::new(Vec::new());
118 /// let header = sam::Header::builder().add_comment("noodles-sam").build();
119 /// writer.write_header(&header)?;
120 /// assert_eq!(writer.get_ref(), b"@CO\tnoodles-sam\n");
121 /// # Ok::<(), io::Error>(())
122 /// ```
123 pub fn write_header(&mut self, header: &Header) -> io::Result<()> {
124 write_header(&mut self.inner, header)
125 }
126
127 /// Writes a SAM record.
128 ///
129 /// # Examples
130 ///
131 /// ```
132 /// # use std::io;
133 /// use noodles_sam as sam;
134 ///
135 /// let mut writer = sam::io::Writer::new(Vec::new());
136 ///
137 /// let header = sam::Header::default();
138 /// let record = sam::Record::default();
139 /// writer.write_record(&header, &record)?;
140 ///
141 /// assert_eq!(writer.get_ref(), b"*\t4\t*\t0\t255\t*\t*\t0\t0\t*\t*\n");
142 /// # Ok::<(), io::Error>(())
143 /// ```
144 pub fn write_record(&mut self, header: &Header, record: &Record) -> io::Result<()> {
145 write_record(&mut self.inner, header, record)
146 }
147}
148
149impl<W> crate::alignment::io::Write for Writer<W>
150where
151 W: Write,
152{
153 fn write_alignment_header(&mut self, header: &Header) -> io::Result<()> {
154 self.write_header(header)
155 }
156
157 fn write_alignment_record(
158 &mut self,
159 header: &Header,
160 record: &dyn crate::alignment::Record,
161 ) -> io::Result<()> {
162 write_record(&mut self.inner, header, record)
163 }
164
165 fn finish(&mut self, _: &Header) -> io::Result<()> {
166 Ok(())
167 }
168}