16
16
//! [W3C Baggage]: https://w3c.github.io/baggage
17
17
use crate :: { Context , Key , KeyValue , Value } ;
18
18
use once_cell:: sync:: Lazy ;
19
+ use std:: collections:: hash_map:: Entry ;
19
20
use std:: collections:: { hash_map, HashMap } ;
20
21
use std:: fmt;
21
22
@@ -124,6 +125,8 @@ impl Baggage {
124
125
/// Same with `insert`, if the name was not present, [`None`] will be returned.
125
126
/// If the name is present, the old value and metadata will be returned.
126
127
///
128
+ /// Also checks for [limits](https://w3c.github.io/baggage/#limits).
129
+ ///
127
130
/// # Examples
128
131
///
129
132
/// ```
@@ -146,10 +149,41 @@ impl Baggage {
146
149
S : Into < BaggageMetadata > ,
147
150
{
148
151
let ( key, value, metadata) = ( key. into ( ) , value. into ( ) , metadata. into ( ) ) ;
149
- if self . insertable ( & key, & value, & metadata) {
150
- self . inner . insert ( key, ( value, metadata) )
151
- } else {
152
- None
152
+ if !key. as_str ( ) . is_ascii ( ) {
153
+ return None ;
154
+ }
155
+ let entry_content_len =
156
+ key_value_metadata_bytes_size ( key. as_str ( ) , value. as_str ( ) . as_ref ( ) , metadata. as_str ( ) ) ;
157
+ if entry_content_len >= MAX_BYTES_FOR_ONE_PAIR {
158
+ return None ;
159
+ }
160
+ let entries_count = self . inner . len ( ) ;
161
+ match self . inner . entry ( key) {
162
+ Entry :: Occupied ( mut occupied_entry) => {
163
+ let prev_content_len = key_value_metadata_bytes_size (
164
+ occupied_entry. key ( ) . as_str ( ) ,
165
+ & occupied_entry. get ( ) . 0 . as_str ( ) . as_ref ( ) ,
166
+ occupied_entry. get ( ) . 1 . as_str ( ) ,
167
+ ) ;
168
+ let new_content_len = self . kv_content_len + entry_content_len - prev_content_len;
169
+ if new_content_len > MAX_LEN_OF_ALL_PAIRS {
170
+ return None ;
171
+ }
172
+ self . kv_content_len = new_content_len;
173
+ Some ( occupied_entry. insert ( ( value, metadata) ) )
174
+ }
175
+ Entry :: Vacant ( vacant_entry) => {
176
+ if entries_count == MAX_KEY_VALUE_PAIRS {
177
+ return None ;
178
+ }
179
+ let new_content_len = self . kv_content_len + entry_content_len;
180
+ if new_content_len > MAX_LEN_OF_ALL_PAIRS {
181
+ return None ;
182
+ }
183
+ self . kv_content_len = new_content_len;
184
+ vacant_entry. insert ( ( value, metadata) ) ;
185
+ None
186
+ }
153
187
}
154
188
}
155
189
@@ -169,59 +203,10 @@ impl Baggage {
169
203
self . inner . is_empty ( )
170
204
}
171
205
172
- /// Gets an iterator over the baggage items, sorted by name .
206
+ /// Gets an iterator over the baggage items, in any order .
173
207
pub fn iter ( & self ) -> Iter < ' _ > {
174
208
self . into_iter ( )
175
209
}
176
-
177
- /// Determine whether the key value pair exceed one of the [limits](https://w3c.github.io/baggage/#limits).
178
- /// If not, update the total length of key values
179
- fn insertable ( & mut self , key : & Key , value : & Value , metadata : & BaggageMetadata ) -> bool {
180
- if !key. as_str ( ) . is_ascii ( ) {
181
- return false ;
182
- }
183
- let value = value. as_str ( ) ;
184
- if key_value_metadata_bytes_size ( key. as_str ( ) , value. as_ref ( ) , metadata. as_str ( ) )
185
- < MAX_BYTES_FOR_ONE_PAIR
186
- {
187
- match self . inner . get ( key) {
188
- None => {
189
- // check total length
190
- if self . kv_content_len
191
- + metadata. as_str ( ) . len ( )
192
- + value. len ( )
193
- + key. as_str ( ) . len ( )
194
- > MAX_LEN_OF_ALL_PAIRS
195
- {
196
- return false ;
197
- }
198
- // check number of pairs
199
- if self . inner . len ( ) + 1 > MAX_KEY_VALUE_PAIRS {
200
- return false ;
201
- }
202
- self . kv_content_len +=
203
- metadata. as_str ( ) . len ( ) + value. len ( ) + key. as_str ( ) . len ( )
204
- }
205
- Some ( ( old_value, old_metadata) ) => {
206
- let old_value = old_value. as_str ( ) ;
207
- if self . kv_content_len - old_metadata. as_str ( ) . len ( ) - old_value. len ( )
208
- + metadata. as_str ( ) . len ( )
209
- + value. len ( )
210
- > MAX_LEN_OF_ALL_PAIRS
211
- {
212
- return false ;
213
- }
214
- self . kv_content_len =
215
- self . kv_content_len - old_metadata. as_str ( ) . len ( ) - old_value. len ( )
216
- + metadata. as_str ( ) . len ( )
217
- + value. len ( )
218
- }
219
- }
220
- true
221
- } else {
222
- false
223
- }
224
- }
225
210
}
226
211
227
212
/// Get the number of bytes for one key-value pair
@@ -376,13 +361,11 @@ impl BaggageExt for Context {
376
361
& self ,
377
362
baggage : T ,
378
363
) -> Self {
379
- let mut merged: Baggage = self
380
- . baggage ( )
381
- . iter ( )
382
- . map ( |( key, ( value, metadata) ) | {
383
- KeyValueMetadata :: new ( key. clone ( ) , value. clone ( ) , metadata. clone ( ) )
384
- } )
385
- . collect ( ) ;
364
+ let old = self . baggage ( ) ;
365
+ let mut merged = Baggage {
366
+ inner : old. inner . clone ( ) ,
367
+ kv_content_len : old. kv_content_len ,
368
+ } ;
386
369
for kvm in baggage. into_iter ( ) . map ( |kv| kv. into ( ) ) {
387
370
merged. insert_with_metadata ( kvm. key , kvm. value , kvm. metadata ) ;
388
371
}
0 commit comments