@@ -282,22 +282,45 @@ impl FromIterator<KeyValueMetadata> for Baggage {
282
282
}
283
283
284
284
fn encode ( s : & str ) -> String {
285
- let special_characters = [ '.' , '-' , '_' , '~' ] ;
286
- let mut encoded_string = String :: with_capacity ( s. len ( ) ) ;
287
-
288
- for char in s. chars ( ) {
289
- if char. is_ascii_alphanumeric ( ) || special_characters. contains ( & char) {
290
- encoded_string. push ( char) ;
291
- } else if char == ' ' {
292
- encoded_string. push_str ( "%20" ) ;
293
- } else {
294
- let mut buffer = [ 0 ; 4 ] ;
295
- let encoded_char = char. encode_utf8 ( & mut buffer) ;
296
- for byte in encoded_char. as_bytes ( ) {
297
- encoded_string. push_str ( & format ! ( "%{:02X}" , byte) ) ;
285
+ let special_characters = [ b'.' , b'-' , b'_' , b'~' ] ;
286
+ let mut encoded_string = String :: with_capacity ( s. len ( ) * 3 ) ;
287
+
288
+ let bytes = s. as_bytes ( ) ;
289
+ let mut i = 0 ;
290
+
291
+ while i < bytes. len ( ) {
292
+ let byte = bytes[ i] ;
293
+
294
+ match byte {
295
+ b' ' => encoded_string. push_str ( "%20" ) ,
296
+ byte if byte. is_ascii_alphanumeric ( ) || special_characters. contains ( & byte) => {
297
+ encoded_string. push ( byte as char )
298
+ }
299
+ _ => {
300
+ if byte. is_ascii ( ) {
301
+ encoded_string. push_str ( & format ! ( "%{:02X}" , byte) ) ;
302
+ } else {
303
+ let start = i;
304
+ let mut end = start + 1 ;
305
+
306
+ while end < bytes. len ( ) && !bytes[ end] . is_ascii ( ) {
307
+ end += 1 ;
308
+ }
309
+
310
+ // Encoding each byte of the multi-byte character
311
+ for & multi_byte in & bytes[ start..end] {
312
+ encoded_string. push_str ( & format ! ( "%{:02X}" , multi_byte) ) ;
313
+ }
314
+
315
+ // Adjust `i` to skip over the bytes we've just encoded
316
+ i = end - 1 ;
317
+ }
298
318
}
299
319
}
320
+
321
+ i += 1 ;
300
322
}
323
+
301
324
encoded_string
302
325
}
303
326
@@ -500,6 +523,8 @@ mod tests {
500
523
let string4 = "Unicode: 😊" ;
501
524
let string5 = "Non-ASCII: áéíóú" ;
502
525
let string6 = "Unsafe: ~!@#$%^&*()_+{}[];:'\\ \" <>?,./" ;
526
+ let string7: & str = "🚀Unicode:" ;
527
+ let string8 = "ΑΒΓ" ;
503
528
504
529
assert_eq ! ( encode( string1) , "test_%20123" ) ;
505
530
assert_eq ! ( encode( string2) , "Hello123" ) ;
@@ -510,6 +535,8 @@ mod tests {
510
535
"Non-ASCII%3A%20%C3%A1%C3%A9%C3%AD%C3%B3%C3%BA"
511
536
) ;
512
537
assert_eq ! ( encode( string6) , "Unsafe%3A%20~%21%40%23%24%25%5E%26%2A%28%29_%2B%7B%7D%5B%5D%3B%3A%27%5C%22%3C%3E%3F%2C.%2F" ) ;
538
+ assert_eq ! ( encode( string7) , "%F0%9F%9A%80Unicode%3A" ) ;
539
+ assert_eq ! ( encode( string8) , "%CE%91%CE%92%CE%93" ) ;
513
540
}
514
541
515
542
#[ test]
0 commit comments