noodles_vcf/header/parser/record/value/map/field/
value.rs1pub(crate) mod string;
2
3use std::{borrow::Cow, error, fmt};
4
5use self::string::{parse_escaped_string, parse_raw_string};
6
7#[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}