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}