noodles_vcf/header/
record.rs

1//! VCF header record and components.
2
3pub mod key;
4pub mod value;
5
6pub use self::{key::Key, value::Value};
7
8use std::str::FromStr;
9
10use self::value::{
11    map::{AlternativeAllele, Contig, Filter, Format, Info},
12    Map,
13};
14use super::{parser::record::ParseError, FileFormat};
15
16/// A VCF header record.
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub enum Record {
19    /// An `ALT` record.
20    AlternativeAllele(String, Map<AlternativeAllele>),
21    /// A `contig` record.
22    Contig(String, Map<Contig>),
23    /// A `fileformat` record.
24    FileFormat(FileFormat),
25    /// A `FILTER` record.
26    Filter(String, Map<Filter>),
27    /// A `FORMAT` record.
28    Format(String, Map<Format>),
29    /// An `INFO` record.
30    Info(String, Map<Info>),
31    /// A nonstadard record.
32    Other(key::Other, Value),
33}
34
35impl FromStr for Record {
36    type Err = ParseError;
37
38    fn from_str(s: &str) -> Result<Self, Self::Err> {
39        Self::try_from((FileFormat::default(), s))
40    }
41}
42
43impl TryFrom<(FileFormat, &str)> for Record {
44    type Error = ParseError;
45
46    fn try_from((file_format, s): (FileFormat, &str)) -> Result<Self, Self::Error> {
47        super::parser::parse_record(s.as_bytes(), file_format)
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_from_str() -> Result<(), ParseError> {
57        let line = "##fileformat=VCFv4.3";
58        assert_eq!(line.parse(), Ok(Record::FileFormat(FileFormat::new(4, 3))));
59
60        let line =
61            r#"##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of samples with data">"#;
62        assert!(matches!(line.parse(), Ok(Record::Info(..))));
63
64        assert!("".parse::<Record>().is_err());
65
66        Ok(())
67    }
68}