noodles_gff/directive_buf/value/
genome_build.rs

1//! GFF directive genome build.
2
3use std::{error, fmt, str::FromStr};
4
5use bstr::{BStr, BString};
6
7/// A GFF directive genome build.
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct GenomeBuild {
10    source: BString,
11    name: BString,
12}
13
14impl GenomeBuild {
15    /// Creates a genome build directive.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use noodles_gff::directive_buf::value::GenomeBuild;
21    /// let genome_build = GenomeBuild::new("NDLS", "r1");
22    /// ```
23    pub fn new<S, N>(source: S, name: N) -> Self
24    where
25        S: Into<BString>,
26        N: Into<BString>,
27    {
28        Self {
29            source: source.into(),
30            name: name.into(),
31        }
32    }
33
34    /// Returns the genome build source.
35    ///
36    /// # Examples
37    ///
38    /// ```
39    /// use noodles_gff::directive_buf::value::GenomeBuild;
40    /// let genome_build = GenomeBuild::new("NDLS", "r1");
41    /// assert_eq!(genome_build.source(), "NDLS");
42    /// ```
43    pub fn source(&self) -> &BStr {
44        self.source.as_ref()
45    }
46
47    /// Returns the genome build name.
48    ///
49    /// # Examples
50    ///
51    /// ```
52    /// use noodles_gff::directive_buf::value::GenomeBuild;
53    /// let genome_build = GenomeBuild::new("NDLS", "r1");
54    /// assert_eq!(genome_build.name(), "r1");
55    /// ```
56    pub fn name(&self) -> &BStr {
57        self.name.as_ref()
58    }
59}
60
61impl fmt::Display for GenomeBuild {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "{} {}", self.source, self.name)
64    }
65}
66
67/// An error returned when a raw GFF genome build directive fails to parse.
68#[derive(Clone, Debug, Eq, PartialEq)]
69pub enum ParseError {
70    /// The input is empty.
71    Empty,
72    /// The genome build source is missing.
73    MissingSource,
74    /// The genome build name is missing.
75    MissingName,
76}
77
78impl error::Error for ParseError {}
79
80impl fmt::Display for ParseError {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        f.write_str("invalid genome build directive: ")?;
83
84        match self {
85            Self::Empty => f.write_str("empty input"),
86            Self::MissingSource => f.write_str("missing source"),
87            Self::MissingName => f.write_str("missing name"),
88        }
89    }
90}
91
92impl FromStr for GenomeBuild {
93    type Err = ParseError;
94
95    fn from_str(s: &str) -> Result<Self, Self::Err> {
96        if s.is_empty() {
97            return Err(ParseError::Empty);
98        }
99
100        let mut args = s.split_ascii_whitespace();
101        let source = args.next().ok_or(ParseError::MissingSource)?;
102        let name = args.next().ok_or(ParseError::MissingName)?;
103
104        Ok(Self::new(source, name))
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn test_fmt() {
114        let genome_build = GenomeBuild::new("NDLS", "r1");
115        assert_eq!(genome_build.to_string(), "NDLS r1");
116    }
117
118    #[test]
119    fn test_from_str() -> Result<(), ParseError> {
120        assert_eq!("NDLS r1".parse(), Ok(GenomeBuild::new("NDLS", "r1")));
121
122        assert_eq!("".parse::<GenomeBuild>(), Err(ParseError::Empty));
123        assert_eq!("NDLS".parse::<GenomeBuild>(), Err(ParseError::MissingName));
124
125        Ok(())
126    }
127}