Skip to main content

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 { None } else { Some(Self(n)) }
34    }
35
36    /// Returns the inner value.
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// use noodles_sam::alignment::record::MappingQuality;
42    /// let mapping_quality = MappingQuality::new(8).unwrap();
43    /// assert_eq!(mapping_quality.get(), 8);
44    /// ```
45    pub const fn get(&self) -> u8 {
46        self.0
47    }
48}
49
50/// An error returned when a raw alignment record mapping quality fails to convert.
51#[derive(Clone, Debug, Eq, PartialEq)]
52pub enum TryFromIntError {
53    /// The value is missing.
54    Missing,
55}
56
57impl error::Error for TryFromIntError {}
58
59impl fmt::Display for TryFromIntError {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        match self {
62            Self::Missing => write!(f, "missing value: {MISSING}"),
63        }
64    }
65}
66
67impl TryFrom<u8> for MappingQuality {
68    type Error = TryFromIntError;
69
70    fn try_from(n: u8) -> Result<Self, Self::Error> {
71        Self::new(n).ok_or(TryFromIntError::Missing)
72    }
73}
74
75impl From<MappingQuality> for u8 {
76    fn from(mapping_quality: MappingQuality) -> Self {
77        mapping_quality.0
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_try_from_u8_for_mapping_quality() {
87        assert_eq!(MappingQuality::try_from(0), Ok(MappingQuality(0)));
88        assert_eq!(MappingQuality::try_from(8), Ok(MappingQuality(8)));
89        assert_eq!(MappingQuality::try_from(13), Ok(MappingQuality(13)));
90        assert_eq!(MappingQuality::try_from(144), Ok(MappingQuality(144)));
91        assert_eq!(MappingQuality::try_from(255), Err(TryFromIntError::Missing));
92    }
93
94    #[test]
95    fn test_from_mapping_quality_for_u8() {
96        assert_eq!(u8::from(MappingQuality(0)), 0);
97        assert_eq!(u8::from(MappingQuality(8)), 8);
98        assert_eq!(u8::from(MappingQuality(13)), 13);
99        assert_eq!(u8::from(MappingQuality(144)), 144);
100    }
101}