fix DoubleEndedIterator impl for Name

This commit is contained in:
Benjamin Fry 2022-02-17 07:06:20 -08:00
parent 13c079391e
commit 7f5490007d
2 changed files with 51 additions and 30 deletions

View File

@ -59,7 +59,8 @@ All notes should be prepended with the location of the change, e.g. `(proto)` or
### Fixed
- (clien) Fix AsyncClient::clone always setting use_edns (ecton) #1598
- (proto) fix DoubleEndedIterator impl for Name #1639
- (client) Fix AsyncClient::clone always setting use_edns (ecton) #1598
- (resolver) Use stream connections if datagram connections are not available (@pinkisemils) #1592
- (server) Release resources when a server future is dropped (@pinkisemils) #1587
- (proto) Panic when name exceeds maximal domain name length during display #1447

View File

@ -109,9 +109,8 @@ impl Name {
pub fn iter(&self) -> LabelIter<'_> {
LabelIter {
name: self,
index: 0,
started: false,
finished: false,
start: 0,
end: self.label_ends.len(),
}
}
@ -929,33 +928,29 @@ impl LabelEnc for LabelEncUtf8 {
/// An iterator over labels in a name
pub struct LabelIter<'a> {
name: &'a Name,
index: usize,
started: bool,
finished: bool,
start: usize,
end: usize,
}
impl<'a> Iterator for LabelIter<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
if self.start >= self.end {
return None;
}
self.started = true;
let end = *self.name.label_ends.get(self.index)?;
let start = match self.index {
let end = *self.name.label_ends.get(self.start)?;
let start = match self.start {
0 => 0,
_ => self.name.label_ends[self.index - 1],
_ => self.name.label_ends[self.start - 1],
};
self.index += 1;
if self.index == self.name.label_ends.len() {
self.finished = true;
}
self.start += 1;
Some(&self.name.label_data[start as usize..end as usize])
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.name.label_ends.len() - self.index;
let len = self.end.saturating_sub(self.start);
(len, Some(len))
}
}
@ -964,23 +959,18 @@ impl<'a> ExactSizeIterator for LabelIter<'a> {}
impl<'a> DoubleEndedIterator for LabelIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.finished {
if self.end <= self.start {
return None;
}
if !self.started {
self.index = self.name.label_ends.len().checked_sub(1)?;
}
self.started = true;
let end = *self.name.label_ends.get(self.index)?;
let start = match self.index {
self.end -= 1;
let end = *self.name.label_ends.get(self.end)?;
let start = match self.end {
0 => 0,
_ => self.name.label_ends[self.index - 1],
_ => self.name.label_ends[self.end - 1],
};
if self.index == 0 {
self.finished = true;
} else {
self.index -= 1;
}
Some(&self.name.label_data[start as usize..end as usize])
}
}
@ -1909,4 +1899,34 @@ mod tests {
_ => panic!("expected too long message"),
}
}
#[test]
fn test_double_ended_iterator() {
let name = Name::from_ascii("www.example.com").unwrap();
let mut iter = name.iter();
assert_eq!(iter.next().unwrap(), b"www");
assert_eq!(iter.next_back().unwrap(), b"com");
assert_eq!(iter.next().unwrap(), b"example");
assert!(iter.next_back().is_none());
assert!(iter.next().is_none());
}
#[test]
fn test_size_hint() {
let name = Name::from_ascii("www.example.com").unwrap();
let mut iter = name.iter();
assert_eq!(iter.size_hint().0, 3);
assert_eq!(iter.next().unwrap(), b"www");
assert_eq!(iter.size_hint().0, 2);
assert_eq!(iter.next_back().unwrap(), b"com");
assert_eq!(iter.size_hint().0, 1);
assert_eq!(iter.next().unwrap(), b"example");
assert_eq!(iter.size_hint().0, 0);
assert!(iter.next_back().is_none());
assert_eq!(iter.size_hint().0, 0);
assert!(iter.next().is_none());
assert_eq!(iter.size_hint().0, 0);
}
}