noodles_vcf/header/parser/
record.rs

1mod key;
2mod value;
3
4use std::{error, fmt};
5
6use self::{key::parse_key, value::parse_value};
7use crate::header::{FileFormat, Record};
8
9/// An error returned when a VCF header record fails to parse.
10#[derive(Clone, Debug, Eq, PartialEq)]
11pub enum ParseError {
12    /// The header prefix is missing.
13    MissingPrefix,
14    /// The key is invalid.
15    InvalidKey(key::ParseError),
16    /// The value is invalid.
17    InvalidValue(value::ParseError),
18}
19
20impl error::Error for ParseError {
21    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
22        match self {
23            Self::MissingPrefix => None,
24            Self::InvalidKey(e) => Some(e),
25            Self::InvalidValue(e) => Some(e),
26        }
27    }
28}
29
30impl fmt::Display for ParseError {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        match self {
33            Self::MissingPrefix => write!(f, "missing prefix"),
34            Self::InvalidKey(_) => write!(f, "invalid key"),
35            Self::InvalidValue(_) => write!(f, "invalid value"),
36        }
37    }
38}
39
40#[allow(missing_docs)]
41pub fn parse_record(mut src: &[u8], file_format: FileFormat) -> Result<Record, ParseError> {
42    consume_prefix(&mut src)?;
43    let key = parse_key(&mut src).map_err(ParseError::InvalidKey)?;
44    parse_value(&mut src, file_format, key).map_err(ParseError::InvalidValue)
45}
46
47fn consume_prefix(src: &mut &[u8]) -> Result<(), ParseError> {
48    const PREFIX: &[u8] = b"##";
49
50    if let Some(rest) = src.strip_prefix(PREFIX) {
51        *src = rest;
52        Ok(())
53    } else {
54        Err(ParseError::MissingPrefix)
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_consume_prefix() {
64        let mut src = &b"##fileformat"[..];
65        assert!(consume_prefix(&mut src).is_ok());
66        assert_eq!(src, b"fileformat");
67
68        let mut src = &b""[..];
69        assert_eq!(consume_prefix(&mut src), Err(ParseError::MissingPrefix));
70
71        let mut src = &b"#"[..];
72        assert_eq!(consume_prefix(&mut src), Err(ParseError::MissingPrefix));
73
74        let mut src = &b"@"[..];
75        assert_eq!(consume_prefix(&mut src), Err(ParseError::MissingPrefix));
76    }
77}