@@ -314,9 +314,11 @@ mod extension {
314
314
use std:: str;
315
315
316
316
#[ derive( Clone , PartialEq , Eq , Hash ) ]
317
+ // Invariant: the first self.1 bytes of self.0 are valid UTF-8.
317
318
pub struct InlineExtension ( [ u8 ; InlineExtension :: MAX ] , u8 ) ;
318
319
319
320
#[ derive( Clone , PartialEq , Eq , Hash ) ]
321
+ // Invariant: self.0 contains valid UTF-8.
320
322
pub struct AllocatedExtension ( Box < [ u8 ] > ) ;
321
323
322
324
impl InlineExtension {
@@ -328,11 +330,15 @@ mod extension {
328
330
329
331
write_checked ( src, & mut data) ?;
330
332
333
+ // Invariant: write_checked ensures that the first src.len() bytes
334
+ // of data are valid UTF-8.
331
335
Ok ( InlineExtension ( data, src. len ( ) as u8 ) )
332
336
}
333
337
334
338
pub fn as_str ( & self ) -> & str {
335
339
let InlineExtension ( ref data, len) = self ;
340
+ // Safety: the invariant of InlineExtension ensures that the first
341
+ // len bytes of data contain valid UTF-8.
336
342
unsafe { str:: from_utf8_unchecked ( & data[ ..* len as usize ] ) }
337
343
}
338
344
}
@@ -343,10 +349,14 @@ mod extension {
343
349
344
350
write_checked ( src, & mut data) ?;
345
351
352
+ // Invariant: data is exactly src.len() long and write_checked
353
+ // ensures that the first src.len() bytes of data are valid UTF-8.
346
354
Ok ( AllocatedExtension ( data. into_boxed_slice ( ) ) )
347
355
}
348
356
349
357
pub fn as_str ( & self ) -> & str {
358
+ // Safety: the invariant of AllocatedExtension ensures that self.0
359
+ // contains valid UTF-8.
350
360
unsafe { str:: from_utf8_unchecked ( & self . 0 ) }
351
361
}
352
362
}
@@ -363,6 +373,9 @@ mod extension {
363
373
//
364
374
// https://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01#Method
365
375
//
376
+ // Note that this definition means that any &[u8] that consists solely of valid
377
+ // characters is also valid UTF-8 because the valid method characters are a
378
+ // subset of the valid 1 byte UTF-8 encoding.
366
379
const METHOD_CHARS : [ u8 ; 256 ] = [
367
380
// 0 1 2 3 4 5 6 7 8 9
368
381
b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , // x
@@ -393,6 +406,8 @@ mod extension {
393
406
b'\0' , b'\0' , b'\0' , b'\0' , b'\0' , b'\0' // 25x
394
407
] ;
395
408
409
+ // write_checked ensures (among other things) that the first src.len() bytes
410
+ // of dst are valid UTF-8
396
411
fn write_checked ( src : & [ u8 ] , dst : & mut [ u8 ] ) -> Result < ( ) , InvalidMethod > {
397
412
for ( i, & b) in src. iter ( ) . enumerate ( ) {
398
413
let b = METHOD_CHARS [ b as usize ] ;
0 commit comments