@@ -206,10 +206,8 @@ pub struct ValueIterMut<'a, T> {
206
206
/// An drain iterator of all values associated with a single header name.
207
207
#[ derive( Debug ) ]
208
208
pub struct ValueDrain < ' a , T > {
209
- raw_links : RawLinks < T > ,
210
- extra_values : * mut Vec < ExtraValue < T > > ,
211
209
first : Option < T > ,
212
- next : Option < usize > ,
210
+ next : Option < :: std :: vec :: IntoIter < T > > ,
213
211
lt : PhantomData < & ' a mut HeaderMap < T > > ,
214
212
}
215
213
@@ -1193,13 +1191,16 @@ impl<T> HeaderMap<T> {
1193
1191
}
1194
1192
1195
1193
let raw_links = self . raw_links ( ) ;
1196
- let extra_values = & mut self . extra_values as * mut _ ;
1194
+ let extra_values = & mut self . extra_values ;
1195
+
1196
+ let next = links. map ( |l| {
1197
+ drain_all_extra_values ( raw_links, extra_values, l. next )
1198
+ . into_iter ( )
1199
+ } ) ;
1197
1200
1198
1201
ValueDrain {
1199
- raw_links,
1200
- extra_values,
1201
1202
first : Some ( old) ,
1202
- next : links . map ( |l| l . next ) ,
1203
+ next : next,
1203
1204
lt : PhantomData ,
1204
1205
}
1205
1206
}
@@ -1368,6 +1369,10 @@ impl<T> HeaderMap<T> {
1368
1369
}
1369
1370
1370
1371
/// Remove an entry from the map.
1372
+ ///
1373
+ /// Warning: To avoid inconsistent state, extra values _must_ be removed
1374
+ /// for the `found` index (via `remove_all_extra_values` or similar)
1375
+ /// _before_ this method is called.
1371
1376
#[ inline]
1372
1377
fn remove_found ( & mut self , probe : usize , found : usize ) -> Bucket < T > {
1373
1378
// index `probe` and entry `found` is to be removed
@@ -1587,7 +1592,12 @@ impl<T> HeaderMap<T> {
1587
1592
1588
1593
/// Removes the `ExtraValue` at the given index.
1589
1594
#[ inline]
1590
- fn remove_extra_value < T > ( mut raw_links : RawLinks < T > , extra_values : & mut Vec < ExtraValue < T > > , idx : usize ) -> ExtraValue < T > {
1595
+ fn remove_extra_value < T > (
1596
+ mut raw_links : RawLinks < T > ,
1597
+ extra_values : & mut Vec < ExtraValue < T > > ,
1598
+ idx : usize )
1599
+ -> ExtraValue < T >
1600
+ {
1591
1601
let prev;
1592
1602
let next;
1593
1603
@@ -1703,6 +1713,26 @@ fn remove_extra_value<T>(mut raw_links: RawLinks<T>, extra_values: &mut Vec<Extr
1703
1713
extra
1704
1714
}
1705
1715
1716
+ fn drain_all_extra_values < T > (
1717
+ raw_links : RawLinks < T > ,
1718
+ extra_values : & mut Vec < ExtraValue < T > > ,
1719
+ mut head : usize )
1720
+ -> Vec < T >
1721
+ {
1722
+ let mut vec = Vec :: new ( ) ;
1723
+ loop {
1724
+ let extra = remove_extra_value ( raw_links, extra_values, head) ;
1725
+ vec. push ( extra. value ) ;
1726
+
1727
+ if let Link :: Extra ( idx) = extra. next {
1728
+ head = idx;
1729
+ } else {
1730
+ break ;
1731
+ }
1732
+ }
1733
+ vec
1734
+ }
1735
+
1706
1736
impl < ' a , T > IntoIterator for & ' a HeaderMap < T > {
1707
1737
type Item = ( & ' a HeaderName , & ' a T ) ;
1708
1738
type IntoIter = Iter < ' a , T > ;
@@ -2922,12 +2952,12 @@ impl<'a, T> OccupiedEntry<'a, T> {
2922
2952
/// assert!(!map.contains_key("host"));
2923
2953
/// ```
2924
2954
pub fn remove_entry ( self ) -> ( HeaderName , T ) {
2925
- let entry = self . map . remove_found ( self . probe , self . index ) ;
2926
-
2927
- if let Some ( links) = entry. links {
2955
+ if let Some ( links) = self . map . entries [ self . index ] . links {
2928
2956
self . map . remove_all_extra_values ( links. next ) ;
2929
2957
}
2930
2958
2959
+ let entry = self . map . remove_found ( self . probe , self . index ) ;
2960
+
2931
2961
( entry. key , entry. value )
2932
2962
}
2933
2963
@@ -2936,14 +2966,19 @@ impl<'a, T> OccupiedEntry<'a, T> {
2936
2966
/// The key and all values associated with the entry are removed and
2937
2967
/// returned.
2938
2968
pub fn remove_entry_mult ( self ) -> ( HeaderName , ValueDrain < ' a , T > ) {
2939
- let entry = self . map . remove_found ( self . probe , self . index ) ;
2940
2969
let raw_links = self . map . raw_links ( ) ;
2941
- let extra_values = & mut self . map . extra_values as * mut _ ;
2970
+ let extra_values = & mut self . map . extra_values ;
2971
+
2972
+ let next = self . map . entries [ self . index ] . links . map ( |l| {
2973
+ drain_all_extra_values ( raw_links, extra_values, l. next )
2974
+ . into_iter ( )
2975
+ } ) ;
2976
+
2977
+ let entry = self . map . remove_found ( self . probe , self . index ) ;
2978
+
2942
2979
let drain = ValueDrain {
2943
- raw_links,
2944
- extra_values,
2945
2980
first : Some ( entry. value ) ,
2946
- next : entry . links . map ( |l| l . next ) ,
2981
+ next,
2947
2982
lt : PhantomData ,
2948
2983
} ;
2949
2984
( entry. key , drain)
@@ -3036,31 +3071,26 @@ impl<'a, T> Iterator for ValueDrain<'a, T> {
3036
3071
fn next ( & mut self ) -> Option < T > {
3037
3072
if self . first . is_some ( ) {
3038
3073
self . first . take ( )
3039
- } else if let Some ( next) = self . next {
3040
- // Remove the extra value
3041
- let extra = unsafe {
3042
- remove_extra_value ( self . raw_links , & mut * self . extra_values , next)
3043
- } ;
3044
-
3045
- match extra. next {
3046
- Link :: Extra ( idx) => self . next = Some ( idx) ,
3047
- Link :: Entry ( _) => self . next = None ,
3048
- }
3049
-
3050
- Some ( extra. value )
3074
+ } else if let Some ( ref mut extras) = self . next {
3075
+ extras. next ( )
3051
3076
} else {
3052
3077
None
3053
3078
}
3054
3079
}
3055
3080
3056
3081
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
3057
- match ( & self . first , self . next ) {
3082
+ match ( & self . first , & self . next ) {
3058
3083
// Exactly 1
3059
- ( & Some ( _) , None ) => ( 1 , Some ( 1 ) ) ,
3060
- // At least 1
3061
- ( & _, Some ( _) ) => ( 1 , None ) ,
3084
+ ( & Some ( _) , & None ) => ( 1 , Some ( 1 ) ) ,
3085
+ // 1 + extras
3086
+ ( & Some ( _) , & Some ( ref extras) ) => {
3087
+ let ( l, u) = extras. size_hint ( ) ;
3088
+ ( l + 1 , u. map ( |u| u + 1 ) )
3089
+ } ,
3090
+ // Extras only
3091
+ ( & None , & Some ( ref extras) ) => extras. size_hint ( ) ,
3062
3092
// No more
3063
- ( & None , None ) => ( 0 , Some ( 0 ) ) ,
3093
+ ( & None , & None ) => ( 0 , Some ( 0 ) ) ,
3064
3094
}
3065
3095
}
3066
3096
}
0 commit comments