noodles_sam/alignment/record/
mapping_quality.rs

1//! Alignment record mapping quality.
2
3use std::{error, fmt};
4
5// ยง 1.4.5 "_MAPQ_" (2023): "A value 255 indicates that the mapping quality is not available."
6const MISSING: u8 = 255;
7
8/// An alignment record mapping quality.
9///
10/// Mapping quality ranges from 0 to 254 (inclusive), where higher is better.
11///
12/// The value 255 is reserved as a marker for a missing mapping quality.
13#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
14pub struct MappingQuality(u8);
15
16impl MappingQuality {
17    /// The minimum mapping quality (0).
18    pub const MIN: Self = Self(0);
19
20    /// The maximum mapping quality (254).
21    pub const MAX: Self = Self(254);
22
23    /// Creates a mapping quality.
24    ///
25    /// # Examples
26    ///
27    /// ```
28    /// use noodles_sam::alignment::record::MappingQuality;
29    /// assert!(MappingQuality::new(8).is_some());
30    /// assert!(MappingQuality::new(255).is_none());
31    /// ```
32    pub const fn new(n: u8) -> Option<Self> {
33        if n == MISSING {
34            None
35        } else {
36            Some(Self(n))
37        }
38    }
39
40    /// Returns the inner value.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use noodles_sam::alignment::record::MappingQuality;
46    /// let mapping_quality = MappingQuality::new(8).unwrap();
47    /// assert_eq!(mapping_quality.get(), 8);
48    /// ```
49    pub const fn get(&self) -> u8 {
50        self.0
51    }
52}
53
54/// An error returned when a raw alignment record mapping quality fails to convert.
55#[derive(Clone, Debug, Eq, PartialEq)]
56pub enum TryFromIntError {
57    /// The value is missing.
58    Missing,
59}
60
61impl error::Error for TryFromIntError {}
62
63impl fmt::Display for TryFromIntError {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        match self {
66            Self::Missing => write!(f, "missing value: {MISSING}"),
67        }
68    }
69}
70
71impl TryFrom<u8> for MappingQuality {
72    type Error = TryFromIntError;
73
74    fn try_from(n: u8) -> Result<Self, Self::Error> {
75        Self::new(n).ok_or(TryFromIntError::Missing)
76    }
77}
78
79impl From<MappingQuality> for u8 {
80    fn from(mapping_quality: MappingQuality) -> Self {
81        mapping_quality.0
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_try_from_u8_for_mapping_quality() {
91        assert_eq!(MappingQuality::try_from(0), Ok(MappingQuality(0)));
92        assert_eq!(MappingQuality::try_from(8), Ok(MappingQuality(8)));
93        assert_eq!(MappingQuality::try_from(13), Ok(MappingQuality(13)));
94        assert_eq!(MappingQuality::try_from(144), Ok(MappingQuality(144)));
95        assert_eq!(MappingQuality::try_from(255), Err(TryFromIntError::Missing));
96    }
97
98    #[test]
99    fn test_from_mapping_quality_for_u8() {
100        assert_eq!(u8::from(MappingQuality(0)), 0);
101        assert_eq!(u8::from(MappingQuality(8)), 8);
102        assert_eq!(u8::from(MappingQuality(13)), 13);
103        assert_eq!(u8::from(MappingQuality(144)), 144);
104    }
105}