noodles_vcf/header/parser/record/value/map/field/
value.rs

1pub(crate) mod string;
2
3use std::{borrow::Cow, error, fmt};
4
5use self::string::{parse_escaped_string, parse_raw_string};
6
7/// An error returned when a VCF header record map field value fails to parse.
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum ParseError {
10    InvalidString(string::ParseError),
11}
12
13impl error::Error for ParseError {
14    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
15        match self {
16            Self::InvalidString(e) => Some(e),
17        }
18    }
19}
20
21impl fmt::Display for ParseError {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            Self::InvalidString(_) => write!(f, "invalid string"),
25        }
26    }
27}
28
29pub fn parse_value<'a>(src: &mut &'a [u8]) -> Result<Cow<'a, str>, ParseError> {
30    const QUOTATION_MARK: u8 = b'"';
31
32    if let Some(buf) = src.strip_prefix(&[QUOTATION_MARK]) {
33        *src = buf;
34
35        parse_escaped_string(src).map_err(ParseError::InvalidString)
36    } else {
37        parse_raw_string(src)
38            .map(Cow::from)
39            .map_err(ParseError::InvalidString)
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_parse_value() {
49        let mut src = &b"noodles-vcf,"[..];
50        assert_eq!(parse_value(&mut src), Ok(Cow::from("noodles-vcf")));
51
52        let mut src = &br#""noodles-vcf","#[..];
53        assert_eq!(parse_value(&mut src), Ok(Cow::from("noodles-vcf")));
54
55        let mut src = &b"noodles-vcf"[..];
56        assert!(matches!(
57            parse_value(&mut src),
58            Err(ParseError::InvalidString(_))
59        ));
60    }
61}