diff --git a/src/header/map.rs b/src/header/map.rs index 08a1b8bc..e16d6317 100644 --- a/src/header/map.rs +++ b/src/header/map.rs @@ -2368,7 +2368,11 @@ impl<'a, T> Iterator for Iter<'a, T> { let map = self.map; debug_assert!(map.entries.len() >= self.entry); - let lower = map.entries.len() - self.entry; + let mut lower = map.entries.len() - self.entry; + if self.cursor.is_none() { + // The current entry is exhausted. Saturate for an empty map. + lower = lower.saturating_sub(1); + } // We could pessimistically guess at the upper bound, saying // that its lower + map.extra_values.len(). That could be // way over though, such as if we're near the end, and have @@ -2453,7 +2457,11 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn size_hint(&self) -> (usize, Option) { debug_assert!(self.entries_len >= self.entry); - let lower = self.entries_len - self.entry; + let mut lower = self.entries_len - self.entry; + if self.cursor.is_none() { + // The current entry is exhausted. Saturate for an empty map. + lower = lower.saturating_sub(1); + } // We could pessimistically guess at the upper bound, saying // that its lower + map.extra_values.len(). That could be // way over though, such as if we're near the end, and have diff --git a/tests/header_map.rs b/tests/header_map.rs index f6210135..67505c2e 100644 --- a/tests/header_map.rs +++ b/tests/header_map.rs @@ -690,6 +690,37 @@ fn ensure_miri_sharedreadonly_not_violated() { let _foo = &headers.iter().next(); } +#[test] +fn iter_size_hint() { + fn check(mut iter: impl Iterator, len: usize) { + for remaining in (0..=len).rev() { + let (lower, upper) = iter.size_hint(); + assert!(lower <= remaining, "lower {lower} > remaining {remaining}"); + if let Some(upper) = upper { + assert!(upper >= remaining); + } + assert_eq!(iter.next().is_some(), remaining > 0); + } + assert_eq!(iter.size_hint().0, 0); + assert!(iter.next().is_none()); + } + + for counts in [vec![], vec![1], vec![3], vec![1, 1], vec![3, 1, 2]] { + let mut headers = HeaderMap::new(); + for (i, count) in counts.into_iter().enumerate() { + let name = HeaderName::from_bytes(format!("header-{i}").as_bytes()).unwrap(); + for _ in 0..count { + headers.append(name.clone(), HeaderValue::from_static("x")); + } + } + let len = headers.len(); + check(headers.iter(), len); + check(headers.iter_mut(), len); + check(headers.values(), len); + check(headers.values_mut(), len); + } +} + #[test] fn ensure_miri_itermut_not_violated() { let mut headers = HeaderMap::::default();