1616//! [W3C Baggage]: https://w3c.github.io/baggage
1717use crate :: { Context , Key , KeyValue , Value } ;
1818use once_cell:: sync:: Lazy ;
19+ use std:: collections:: hash_map:: Entry ;
1920use std:: collections:: { hash_map, HashMap } ;
2021use std:: fmt;
2122
@@ -124,6 +125,8 @@ impl Baggage {
124125 /// Same with `insert`, if the name was not present, [`None`] will be returned.
125126 /// If the name is present, the old value and metadata will be returned.
126127 ///
128+ /// Also checks for [limits](https://w3c.github.io/baggage/#limits).
129+ ///
127130 /// # Examples
128131 ///
129132 /// ```
@@ -146,10 +149,41 @@ impl Baggage {
146149 S : Into < BaggageMetadata > ,
147150 {
148151 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+ }
153187 }
154188 }
155189
@@ -169,59 +203,10 @@ impl Baggage {
169203 self . inner . is_empty ( )
170204 }
171205
172- /// Gets an iterator over the baggage items, sorted by name .
206+ /// Gets an iterator over the baggage items, in any order .
173207 pub fn iter ( & self ) -> Iter < ' _ > {
174208 self . into_iter ( )
175209 }
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- }
225210}
226211
227212/// Get the number of bytes for one key-value pair
@@ -376,13 +361,11 @@ impl BaggageExt for Context {
376361 & self ,
377362 baggage : T ,
378363 ) -> 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+ } ;
386369 for kvm in baggage. into_iter ( ) . map ( |kv| kv. into ( ) ) {
387370 merged. insert_with_metadata ( kvm. key , kvm. value , kvm. metadata ) ;
388371 }
0 commit comments