Skip to content

Commit 8ffe094

Browse files
committed
Make ValueDrain eagerly collect its extra values
1 parent 81ceb61 commit 8ffe094

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

src/header/map.rs

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,8 @@ pub struct ValueIterMut<'a, T: 'a> {
204204
/// An drain iterator of all values associated with a single header name.
205205
#[derive(Debug)]
206206
pub struct ValueDrain<'a, T: 'a> {
207-
raw_links: RawLinks<T>,
208-
extra_values: *mut Vec<ExtraValue<T>>,
209207
first: Option<T>,
210-
next: Option<usize>,
208+
next: Option<::std::vec::IntoIter<T>>,
211209
lt: PhantomData<&'a mut HeaderMap<T>>,
212210
}
213211

@@ -1163,13 +1161,16 @@ impl<T> HeaderMap<T> {
11631161
}
11641162

11651163
let raw_links = self.raw_links();
1166-
let extra_values = &mut self.extra_values as *mut _;
1164+
let extra_values = &mut self.extra_values;
1165+
1166+
let next = links.map(|l| {
1167+
drain_all_extra_values(raw_links, extra_values, l.next)
1168+
.into_iter()
1169+
});
11671170

11681171
ValueDrain {
1169-
raw_links,
1170-
extra_values,
11711172
first: Some(old),
1172-
next: links.map(|l| l.next),
1173+
next: next,
11731174
lt: PhantomData,
11741175
}
11751176
}
@@ -1670,6 +1671,22 @@ fn remove_extra_value<T>(mut raw_links: RawLinks<T>, extra_values: &mut Vec<Extr
16701671
extra
16711672
}
16721673

1674+
1675+
fn drain_all_extra_values<T>(raw_links: RawLinks<T>, extra_values: &mut Vec<ExtraValue<T>>, mut head: usize) -> Vec<T> {
1676+
let mut vec = Vec::new();
1677+
loop {
1678+
let extra = remove_extra_value(raw_links, extra_values, head);
1679+
vec.push(extra.value);
1680+
1681+
if let Link::Extra(idx) = extra.next {
1682+
head = idx;
1683+
} else {
1684+
break;
1685+
}
1686+
}
1687+
vec
1688+
}
1689+
16731690
impl<'a, T> IntoIterator for &'a HeaderMap<T> {
16741691
type Item = (&'a HeaderName, &'a T);
16751692
type IntoIter = Iter<'a, T>;
@@ -2154,17 +2171,17 @@ impl<'a, T> Iterator for Drain<'a, T> {
21542171
// Read the header name
21552172
key = ptr::read(&entry.key as *const _);
21562173
value = ptr::read(&entry.value as *const _);
2157-
next = entry.links.map(|l| l.next);
2158-
21592174

21602175
let raw_links = RawLinks(self.entries);
2161-
let extra_values = self.extra_values;
2176+
let extra_values = &mut *self.extra_values;
2177+
next = entry.links.map(|l| {
2178+
drain_all_extra_values(raw_links, extra_values, l.next)
2179+
.into_iter()
2180+
});
21622181

21632182
ValueDrain {
2164-
raw_links,
2165-
extra_values,
21662183
first: Some(value),
2167-
next: next,
2184+
next,
21682185
lt: PhantomData,
21692186
}
21702187
};
@@ -2898,12 +2915,15 @@ impl<'a, T> OccupiedEntry<'a, T> {
28982915
pub fn remove_entry_mult(self) -> (HeaderName, ValueDrain<'a, T>) {
28992916
let entry = self.map.remove_found(self.probe, self.index);
29002917
let raw_links = self.map.raw_links();
2901-
let extra_values = &mut self.map.extra_values as *mut _;
2918+
let extra_values = &mut self.map.extra_values;
2919+
2920+
let next = entry.links.map(|l| {
2921+
drain_all_extra_values(raw_links, extra_values, l.next)
2922+
.into_iter()
2923+
});
29022924
let drain = ValueDrain {
2903-
raw_links,
2904-
extra_values,
29052925
first: Some(entry.value),
2906-
next: entry.links.map(|l| l.next),
2926+
next,
29072927
lt: PhantomData,
29082928
};
29092929
(entry.key, drain)
@@ -2996,31 +3016,26 @@ impl<'a, T> Iterator for ValueDrain<'a, T> {
29963016
fn next(&mut self) -> Option<T> {
29973017
if self.first.is_some() {
29983018
self.first.take()
2999-
} else if let Some(next) = self.next {
3000-
// Remove the extra value
3001-
let extra = unsafe {
3002-
remove_extra_value(self.raw_links, &mut *self.extra_values, next)
3003-
};
3004-
3005-
match extra.next {
3006-
Link::Extra(idx) => self.next = Some(idx),
3007-
Link::Entry(_) => self.next = None,
3008-
}
3009-
3010-
Some(extra.value)
3019+
} else if let Some(ref mut extras) = self.next {
3020+
extras.next()
30113021
} else {
30123022
None
30133023
}
30143024
}
30153025

30163026
fn size_hint(&self) -> (usize, Option<usize>) {
3017-
match (&self.first, self.next) {
3027+
match (&self.first, &self.next) {
30183028
// Exactly 1
3019-
(&Some(_), None) => (1, Some(1)),
3020-
// At least 1
3021-
(&_, Some(_)) => (1, None),
3029+
(&Some(_), &None) => (1, Some(1)),
3030+
// 1 + extras
3031+
(&Some(_), &Some(ref extras)) => {
3032+
let (l, u) = extras.size_hint();
3033+
(l + 1, u.map(|u| u + 1))
3034+
},
3035+
// Extras only
3036+
(&None, &Some(ref extras)) => extras.size_hint(),
30223037
// No more
3023-
(&None, None) => (0, Some(0)),
3038+
(&None, &None) => (0, Some(0)),
30243039
}
30253040
}
30263041
}

0 commit comments

Comments
 (0)