noodles_sam/alignment/record/flags.rs
1bitflags::bitflags! {
2 /// Alignment record flags.
3 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
4 pub struct Flags: u16 {
5 /// Read is segmented (`0x01`).
6 const SEGMENTED = 0x01;
7 /// Each segment in the read is properly aligned (`0x02`).
8 #[deprecated(since = "0.54.0", note = "Use `PROPERLY_SEGMENTED` instead.")]
9 const PROPERLY_ALIGNED = 0x02;
10 /// Each segment in the read is properly aligned (`0x02`).
11 const PROPERLY_SEGMENTED = 0x02;
12 /// Read is unmapped (`Ox04`).
13 const UNMAPPED = 0x04;
14 /// The mate is unmapped (`0x08`).
15 const MATE_UNMAPPED = 0x08;
16 /// The sequence is reverse complemented (`0x10`).
17 const REVERSE_COMPLEMENTED = 0x10;
18 /// The sequence of the mate is reverse complemented (`0x20`).
19 const MATE_REVERSE_COMPLEMENTED = 0x20;
20 /// First segment in the read (`0x40`).
21 const FIRST_SEGMENT = 0x40;
22 /// Last segment in the read (`0x80`).
23 const LAST_SEGMENT = 0x80;
24 /// Secondary read (`0x0100`).
25 const SECONDARY = 0x0100;
26 /// Read failed quality checks (`0x0200`).
27 const QC_FAIL = 0x0200;
28 /// PCR or optical duplicate read (`0x0400`).
29 const DUPLICATE = 0x0400;
30 /// Supplementary alignment (`0x0800`).
31 const SUPPLEMENTARY = 0x0800;
32 }
33}
34
35impl Flags {
36 /// Returns whether the `SEGMENTED` flag is set.
37 ///
38 /// # Examples
39 ///
40 /// ```
41 /// use noodles_sam::alignment::record::Flags;
42 /// assert!(Flags::SEGMENTED.is_segmented());
43 /// assert!(!Flags::UNMAPPED.is_segmented());
44 /// ```
45 pub fn is_segmented(self) -> bool {
46 self.contains(Self::SEGMENTED)
47 }
48
49 /// Returns whether the `PROPERLY_ALIGNED` flag is set.
50 ///
51 /// # Examples
52 ///
53 /// ```
54 /// use noodles_sam::alignment::record::Flags;
55 /// assert!(Flags::PROPERLY_ALIGNED.is_properly_aligned());
56 /// assert!(!Flags::UNMAPPED.is_properly_aligned());
57 /// ```
58 #[allow(deprecated)]
59 #[deprecated(since = "0.54.0", note = "Use `Flags::is_properly_segmented` instead.")]
60 pub fn is_properly_aligned(self) -> bool {
61 self.contains(Self::PROPERLY_ALIGNED)
62 }
63
64 /// Returns whether the `PROPERLY_SEGMENTED` flag is set.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use noodles_sam::alignment::record::Flags;
70 /// assert!(Flags::PROPERLY_SEGMENTED.is_properly_segmented());
71 /// assert!(!Flags::UNMAPPED.is_properly_segmented());
72 /// ```
73 pub fn is_properly_segmented(self) -> bool {
74 self.contains(Self::PROPERLY_SEGMENTED)
75 }
76
77 /// Returns whether the `UNMAPPED` flag is set.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use noodles_sam::alignment::record::Flags;
83 /// assert!(Flags::UNMAPPED.is_unmapped());
84 /// assert!(!Flags::SEGMENTED.is_unmapped());
85 /// ```
86 pub fn is_unmapped(self) -> bool {
87 self.contains(Self::UNMAPPED)
88 }
89
90 /// Returns whether the `MATE_UNMAPPED` flag is set.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use noodles_sam::alignment::record::Flags;
96 /// assert!(Flags::MATE_UNMAPPED.is_mate_unmapped());
97 /// assert!(!Flags::UNMAPPED.is_mate_unmapped());
98 /// ```
99 pub fn is_mate_unmapped(self) -> bool {
100 self.contains(Self::MATE_UNMAPPED)
101 }
102
103 /// Returns whether the `REVERSE_COMPLEMENTED` flag is set.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use noodles_sam::alignment::record::Flags;
109 /// assert!(Flags::REVERSE_COMPLEMENTED.is_reverse_complemented());
110 /// assert!(!Flags::UNMAPPED.is_reverse_complemented());
111 /// ```
112 pub fn is_reverse_complemented(self) -> bool {
113 self.contains(Self::REVERSE_COMPLEMENTED)
114 }
115
116 /// Returns whether the `MATE_REVERSE_COMPLEMENTED` flag is set.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use noodles_sam::alignment::record::Flags;
122 /// assert!(Flags::MATE_REVERSE_COMPLEMENTED.is_mate_reverse_complemented());
123 /// assert!(!Flags::UNMAPPED.is_mate_reverse_complemented());
124 /// ```
125 pub fn is_mate_reverse_complemented(self) -> bool {
126 self.contains(Self::MATE_REVERSE_COMPLEMENTED)
127 }
128
129 /// Returns whether the `FIRST_SEGMENT` flag is set.
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// use noodles_sam::alignment::record::Flags;
135 /// assert!(Flags::FIRST_SEGMENT.is_first_segment());
136 /// assert!(!Flags::UNMAPPED.is_first_segment());
137 /// ```
138 pub fn is_first_segment(self) -> bool {
139 self.contains(Self::FIRST_SEGMENT)
140 }
141
142 /// Returns whether the `LAST_SEGMENT` flag is set.
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// use noodles_sam::alignment::record::Flags;
148 /// assert!(Flags::LAST_SEGMENT.is_last_segment());
149 /// assert!(!Flags::UNMAPPED.is_last_segment());
150 /// ```
151 pub fn is_last_segment(self) -> bool {
152 self.contains(Self::LAST_SEGMENT)
153 }
154
155 /// Returns whether the `SECONDARY` flag is set.
156 ///
157 /// # Examples
158 ///
159 /// ```
160 /// use noodles_sam::alignment::record::Flags;
161 /// assert!(Flags::SECONDARY.is_secondary());
162 /// assert!(!Flags::UNMAPPED.is_secondary());
163 /// ```
164 pub fn is_secondary(self) -> bool {
165 self.contains(Self::SECONDARY)
166 }
167
168 /// Returns whether the `QC_FAIL` flag is set.
169 ///
170 /// # Examples
171 ///
172 /// ```
173 /// use noodles_sam::alignment::record::Flags;
174 /// assert!(Flags::QC_FAIL.is_qc_fail());
175 /// assert!(!Flags::UNMAPPED.is_qc_fail());
176 /// ```
177 pub fn is_qc_fail(self) -> bool {
178 self.contains(Self::QC_FAIL)
179 }
180
181 /// Returns whether the `DUPLICATE` flag is set.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// use noodles_sam::alignment::record::Flags;
187 /// assert!(Flags::DUPLICATE.is_duplicate());
188 /// assert!(!Flags::UNMAPPED.is_duplicate());
189 /// ```
190 pub fn is_duplicate(self) -> bool {
191 self.contains(Self::DUPLICATE)
192 }
193
194 /// Returns whether the `SUPPLEMENTARY` flag is set.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use noodles_sam::alignment::record::Flags;
200 /// assert!(Flags::SUPPLEMENTARY.is_supplementary());
201 /// assert!(!Flags::UNMAPPED.is_supplementary());
202 /// ```
203 pub fn is_supplementary(self) -> bool {
204 self.contains(Self::SUPPLEMENTARY)
205 }
206}
207
208impl From<u16> for Flags {
209 fn from(value: u16) -> Self {
210 Self::from_bits_truncate(value)
211 }
212}
213
214impl From<Flags> for u16 {
215 fn from(flags: Flags) -> Self {
216 flags.bits()
217 }
218}
219
220#[allow(deprecated)]
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn test_default() {
227 let flags = Flags::default();
228
229 assert!(flags.is_empty());
230 assert!(!flags.is_segmented());
231 assert!(!flags.is_properly_aligned());
232 assert!(!flags.is_properly_segmented());
233 assert!(!flags.is_unmapped());
234 assert!(!flags.is_mate_unmapped());
235 assert!(!flags.is_reverse_complemented());
236 assert!(!flags.is_mate_reverse_complemented());
237 assert!(!flags.is_first_segment());
238 assert!(!flags.is_last_segment());
239 assert!(!flags.is_secondary());
240 assert!(!flags.is_qc_fail());
241 assert!(!flags.is_duplicate());
242 assert!(!flags.is_supplementary());
243 }
244
245 #[test]
246 fn test_contains() {
247 assert!(Flags::SEGMENTED.is_segmented());
248 assert!(Flags::PROPERLY_ALIGNED.is_properly_aligned());
249 assert!(Flags::PROPERLY_SEGMENTED.is_properly_segmented());
250 assert!(Flags::UNMAPPED.is_unmapped());
251 assert!(Flags::MATE_UNMAPPED.is_mate_unmapped());
252 assert!(Flags::REVERSE_COMPLEMENTED.is_reverse_complemented());
253 assert!(Flags::MATE_REVERSE_COMPLEMENTED.is_mate_reverse_complemented());
254 assert!(Flags::FIRST_SEGMENT.is_first_segment());
255 assert!(Flags::LAST_SEGMENT.is_last_segment());
256 assert!(Flags::SECONDARY.is_secondary());
257 assert!(Flags::QC_FAIL.is_qc_fail());
258 assert!(Flags::DUPLICATE.is_duplicate());
259 assert!(Flags::SUPPLEMENTARY.is_supplementary());
260 }
261
262 #[test]
263 fn test_from_u16_for_flags() {
264 assert_eq!(Flags::from(0x04), Flags::UNMAPPED);
265 }
266
267 #[test]
268 fn test_from_flags_for_u16() {
269 assert_eq!(u16::from(Flags::UNMAPPED), 0x04);
270 }
271}