Skip to content

Commit

Permalink
vcf/variant/record/info/field/value/array/values: Fix iterating over …
Browse files Browse the repository at this point in the history
…an empty lists

This now immediately returns `None`.
  • Loading branch information
zaeleus committed Sep 6, 2024
1 parent 410b94e commit 99b0ec9
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 36 deletions.
5 changes: 5 additions & 0 deletions noodles-vcf/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
* vcf/variant/record/info/field/value/array/values: Fix counting number of
values.

* vcf/variant/record/info/field/value/array/values: Fix iterating over empty
lists.

This now immediately returns `None`.

## 0.63.0 - 2024-09-04

### Added
Expand Down
91 changes: 55 additions & 36 deletions noodles-vcf/src/variant/record/info/field/value/array/values.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, io};
use std::{borrow::Cow, io, iter};

use crate::io::reader::record_buf::value::percent_decode;

Expand All @@ -21,15 +21,19 @@ impl<'a> Values<'a, i32> for &'a str {
}

fn iter(&self) -> Box<dyn Iterator<Item = io::Result<Option<i32>>> + '_> {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => s
.parse()
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
if self.is_empty() {
Box::new(iter::empty())
} else {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => s
.parse()
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
}
}
}

Expand All @@ -39,15 +43,19 @@ impl<'a> Values<'a, f32> for &'a str {
}

fn iter(&self) -> Box<dyn Iterator<Item = io::Result<Option<f32>>> + '_> {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => s
.parse()
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
if self.is_empty() {
Box::new(iter::empty())
} else {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => s
.parse()
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
}
}
}

Expand All @@ -59,15 +67,19 @@ impl<'a> Values<'a, char> for &'a str {
fn iter(&self) -> Box<dyn Iterator<Item = io::Result<Option<char>>> + '_> {
const MISSING: char = '.';

Box::new(
self.split(DELIMITER)
.flat_map(|t| t.chars())
.map(|c| match c {
MISSING => None,
_ => Some(c),
})
.map(Ok),
)
if self.is_empty() {
Box::new(iter::empty())
} else {
Box::new(
self.split(DELIMITER)
.flat_map(|t| t.chars())
.map(|c| match c {
MISSING => None,
_ => Some(c),
})
.map(Ok),
)
}
}
}

Expand All @@ -77,14 +89,18 @@ impl<'a> Values<'a, Cow<'a, str>> for &'a str {
}

fn iter(&self) -> Box<dyn Iterator<Item = io::Result<Option<Cow<'a, str>>>> + '_> {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => percent_decode(s)
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
if self.is_empty() {
Box::new(iter::empty())
} else {
Box::new(self.split(DELIMITER).map(|s| {
match s {
MISSING => Ok(None),
_ => percent_decode(s)
.map(Some)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)),
}
}))
}
}
}

Expand All @@ -109,6 +125,9 @@ mod tests {
let values: Box<dyn Values<'_, Cow<'_, str>>> = Box::new(src);
assert_eq!(values.len(), 0);

let mut iter = values.iter();
assert!(iter.next().transpose()?.is_none());

let src = "a,b%3Bc";
let values: Box<dyn Values<'_, Cow<'_, str>>> = Box::new(src);
assert_eq!(values.len(), 2);
Expand Down

0 comments on commit 99b0ec9

Please sign in to comment.