Skip to content

Commit c89cfc9

Browse files
committed
Change HeaderMap::drain API to match into_iter instead
1 parent 6c2b789 commit c89cfc9

File tree

2 files changed

+54
-50
lines changed

2 files changed

+54
-50
lines changed

src/header/map.rs

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ pub struct Drain<'a, T> {
137137
idx: usize,
138138
len: usize,
139139
entries: *mut [Bucket<T>],
140+
// If None, pull from `entries`
141+
next: Option<usize>,
140142
extra_values: *mut Vec<ExtraValue<T>>,
141143
lt: PhantomData<&'a mut HeaderMap<T>>,
142144
}
@@ -922,6 +924,10 @@ impl<T> HeaderMap<T> {
922924
///
923925
/// The internal memory is kept for reuse.
924926
///
927+
/// For each yielded item that has `None` provided for the `HeaderName`,
928+
/// then the associated header name is the same as that of the previously
929+
/// yielded item. The first yielded item will have `HeaderName` set.
930+
///
925931
/// # Examples
926932
///
927933
/// ```
@@ -935,18 +941,13 @@ impl<T> HeaderMap<T> {
935941
///
936942
/// let mut drain = map.drain();
937943
///
938-
/// let (key, mut vals) = drain.next().unwrap();
939944
///
940-
/// assert_eq!("host", key);
941-
/// assert_eq!("hello", vals.next().unwrap());
942-
/// assert_eq!("goodbye", vals.next().unwrap());
943-
/// assert!(vals.next().is_none());
945+
/// assert_eq!(drain.next(), Some((Some(HOST), "hello".parse().unwrap())));
946+
/// assert_eq!(drain.next(), Some((None, "goodbye".parse().unwrap())));
944947
///
945-
/// let (key, mut vals) = drain.next().unwrap();
948+
/// assert_eq!(drain.next(), Some((Some(CONTENT_LENGTH), "123".parse().unwrap())));
946949
///
947-
/// assert_eq!("content-length", key);
948-
/// assert_eq!("123", vals.next().unwrap());
949-
/// assert!(vals.next().is_none());
950+
/// assert_eq!(drain.next(), None);
950951
/// ```
951952
pub fn drain(&mut self) -> Drain<'_, T> {
952953
for i in self.indices.iter_mut() {
@@ -970,6 +971,7 @@ impl<T> HeaderMap<T> {
970971
len,
971972
entries,
972973
extra_values,
974+
next: None,
973975
lt: PhantomData,
974976
}
975977
}
@@ -2165,9 +2167,25 @@ impl<'a, T> FusedIterator for ValuesMut<'a, T> {}
21652167
// ===== impl Drain =====
21662168

21672169
impl<'a, T> Iterator for Drain<'a, T> {
2168-
type Item = (HeaderName, ValueDrain<'a, T>);
2170+
type Item = (Option<HeaderName>, T);
21692171

21702172
fn next(&mut self) -> Option<Self::Item> {
2173+
if let Some(next) = self.next {
2174+
// Remove the extra value
2175+
2176+
let raw_links = RawLinks(self.entries);
2177+
let extra = unsafe {
2178+
remove_extra_value(raw_links, &mut *self.extra_values, next)
2179+
};
2180+
2181+
match extra.next {
2182+
Link::Extra(idx) => self.next = Some(idx),
2183+
Link::Entry(_) => self.next = None,
2184+
}
2185+
2186+
return Some((None, extra.value));
2187+
}
2188+
21712189
let idx = self.idx;
21722190

21732191
if idx == self.len {
@@ -2176,37 +2194,27 @@ impl<'a, T> Iterator for Drain<'a, T> {
21762194

21772195
self.idx += 1;
21782196

2179-
let key;
2180-
let value;
2181-
let next;
2182-
2183-
let values = unsafe {
2197+
unsafe {
21842198
let entry = &(*self.entries)[idx];
21852199

21862200
// Read the header name
2187-
key = ptr::read(&entry.key as *const _);
2188-
value = ptr::read(&entry.value as *const _);
2189-
next = entry.links.map(|l| l.next);
2190-
2201+
let key = ptr::read(&entry.key as *const _);
2202+
let value = ptr::read(&entry.value as *const _);
2203+
self.next = entry.links.map(|l| l.next);
21912204

2192-
let raw_links = RawLinks(self.entries);
2193-
let extra_values = self.extra_values;
2194-
2195-
ValueDrain {
2196-
raw_links,
2197-
extra_values,
2198-
first: Some(value),
2199-
next: next,
2200-
lt: PhantomData,
2201-
}
2202-
};
2203-
2204-
Some((key, values))
2205+
Some((Some(key), value))
2206+
}
22052207
}
22062208

22072209
fn size_hint(&self) -> (usize, Option<usize>) {
2210+
// At least this many names... It's unknown if the user wants
2211+
// to count the extra_values on top.
2212+
//
2213+
// For instance, extending a new `HeaderMap` wouldn't need to
2214+
// reserve the upper-bound in `entries`, only the lower-bound.
22082215
let lower = self.len - self.idx;
2209-
(lower, Some(lower))
2216+
let upper = unsafe { (*self.extra_values).len() } + lower;
2217+
(lower, Some(upper))
22102218
}
22112219
}
22122220

tests/header_map.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,10 @@ fn drain() {
6161

6262
{
6363
let mut iter = headers.drain();
64-
let (name, values) = iter.next().unwrap();
65-
assert_eq!(name.as_str(), "hello");
64+
let (name, value) = iter.next().unwrap();
65+
assert_eq!(name.unwrap().as_str(), "hello");
6666

67-
let values: Vec<_> = values.collect();
68-
assert_eq!(values.len(), 1);
69-
assert_eq!(values[0], "world");
67+
assert_eq!(value, "world");
7068

7169
assert!(iter.next().is_none());
7270
}
@@ -90,20 +88,18 @@ fn drain() {
9088
// Drain...
9189
{
9290
let mut iter = headers.drain();
93-
let (name, values) = iter.next().unwrap();
94-
assert_eq!(name.as_str(), "hello");
9591

96-
let values: Vec<_> = values.collect();
97-
assert_eq!(values.len(), 2);
98-
assert_eq!(values[0], "world");
99-
assert_eq!(values[1], "world2");
92+
let (name, value) = iter.next().unwrap();
93+
assert_eq!(name.unwrap().as_str(), "hello");
94+
assert_eq!(value, "world");
10095

101-
let (name, values) = iter.next().unwrap();
102-
assert_eq!(name.as_str(), "zomg");
96+
let (name, value) = iter.next().unwrap();
97+
assert_eq!(name, None);
98+
assert_eq!(value, "world2");
10399

104-
let values: Vec<_> = values.collect();
105-
assert_eq!(values.len(), 1);
106-
assert_eq!(values[0], "bar");
100+
let (name, value) = iter.next().unwrap();
101+
assert_eq!(name.unwrap().as_str(), "zomg");
102+
assert_eq!(value, "bar");
107103

108104
assert!(iter.next().is_none());
109105
}
@@ -119,7 +115,7 @@ fn drain_drop_immediately() {
119115
headers.append("hello", "world2".parse().unwrap());
120116

121117
let iter = headers.drain();
122-
assert_eq!(iter.size_hint(), (2, Some(2)));
118+
assert_eq!(iter.size_hint(), (2, Some(3)));
123119
// not consuming `iter`
124120
}
125121

0 commit comments

Comments
 (0)