diff --git a/noodles-vcf/CHANGELOG.md b/noodles-vcf/CHANGELOG.md index 61cf64da1..552e9bdea 100644 --- a/noodles-vcf/CHANGELOG.md +++ b/noodles-vcf/CHANGELOG.md @@ -14,8 +14,8 @@ When the input is VCF 4.2, this allows the `Child` or `Derived` field to act as the record ID in the value collection. - * vcf/header/parser/record/value/map/other: Only parse `Values` field in META - record. + * vcf/header/parser/record/value/map/other: Only parse `Values` field in VCF + 4.3+ META records. [#201]: https://github.com/zaeleus/noodles/issues/201 [#203]: https://github.com/zaeleus/noodles/issues/203 diff --git a/noodles-vcf/src/header/parser/record/value.rs b/noodles-vcf/src/header/parser/record/value.rs index 9bb51960b..2e72561fc 100644 --- a/noodles-vcf/src/header/parser/record/value.rs +++ b/noodles-vcf/src/header/parser/record/value.rs @@ -181,7 +181,7 @@ pub(super) fn parse_value( .map_err(ParseError::InvalidContig), Key::Other(k) => { let v = if k.as_ref() == META { - map::other::parse_meta(src) + map::other::parse_meta(src, file_format) .map(Value::from) .map_err(|e| ParseError::InvalidOtherMap(k.clone(), e))? } else if k.as_ref() == PEDIGREE { diff --git a/noodles-vcf/src/header/parser/record/value/map/other.rs b/noodles-vcf/src/header/parser/record/value/map/other.rs index 450699f87..7015afff1 100644 --- a/noodles-vcf/src/header/parser/record/value/map/other.rs +++ b/noodles-vcf/src/header/parser/record/value/map/other.rs @@ -103,8 +103,12 @@ pub fn parse_other(src: &mut &[u8]) -> Result<(String, Map), ParseError> )) } -pub fn parse_meta(src: &mut &[u8]) -> Result<(String, Map), ParseError> { +pub fn parse_meta( + src: &mut &[u8], + file_format: FileFormat, +) -> Result<(String, Map), ParseError> { const VALUES: &str = "Values"; + const VCF_4_3: FileFormat = FileFormat::new(4, 3); super::consume_prefix(src).map_err(|e| ParseError::new(None, ParseErrorKind::InvalidMap(e)))?; @@ -119,7 +123,7 @@ pub fn parse_meta(src: &mut &[u8]) -> Result<(String, Map), ParseError> { match tag { tag::ID => parse_id(src, &id).and_then(|v| try_replace(&mut id, &None, tag::ID, v))?, Tag::Other(t) => { - if t == VALUES { + if file_format >= VCF_4_3 && t == VALUES { parse_values(src, &id, &t) .and_then(|value| try_insert(&mut other_fields, &id, t, value))?; } else { @@ -302,6 +306,34 @@ mod tests { assert_eq!(parse_other(&mut src), Ok(expected)); } + #[test] + fn test_parse_meta() -> Result<(), Box> { + const VCF_4_2: FileFormat = FileFormat::new(4, 2); + const VCF_4_3: FileFormat = FileFormat::new(4, 3); + + let mut src = &b""[..]; + assert_eq!( + parse_meta(&mut src, VCF_4_3), + Ok(( + String::from("Assay"), + Map::::builder() + .insert("Values".parse()?, "[WholeGenome, Exome]") + .build()? + )) + ); + + let mut src = &b""[..]; + assert!(matches!( + parse_meta(&mut src, VCF_4_2), + Err(ParseError { + id, + kind: ParseErrorKind::InvalidKey(_) + }) if id == Some(String::from("Assay")) + )); + + Ok(()) + } + #[test] fn test_parse_pedigree() -> Result<(), Box> { const VCF_4_2: FileFormat = FileFormat::new(4, 2);