@@ -411,14 +411,17 @@ pub struct EscapeUnicode {
411411 hex_digit_idx : usize ,
412412}
413413
414+ // The enum values are ordered so that their representation is the
415+ // same as the remaining length (besides the hexadecimal digits). This
416+ // likely makes `len()` a single load from memory) and inline-worth.
414417#[ derive( Clone , Debug ) ]
415418enum EscapeUnicodeState {
416- Backslash ,
417- Type ,
418- LeftBrace ,
419- Value ,
420- RightBrace ,
421419 Done ,
420+ RightBrace ,
421+ Value ,
422+ LeftBrace ,
423+ Type ,
424+ Backslash ,
422425}
423426
424427#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -457,19 +460,17 @@ impl Iterator for EscapeUnicode {
457460 }
458461 }
459462
463+ #[ inline]
460464 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
461- let n = match self . state {
462- EscapeUnicodeState :: Backslash => 5 ,
463- EscapeUnicodeState :: Type => 4 ,
464- EscapeUnicodeState :: LeftBrace => 3 ,
465- EscapeUnicodeState :: Value => 2 ,
466- EscapeUnicodeState :: RightBrace => 1 ,
467- EscapeUnicodeState :: Done => 0 ,
468- } ;
469- let n = n + self . hex_digit_idx ;
465+ let n = self . len ( ) ;
470466 ( n, Some ( n) )
471467 }
472468
469+ #[ inline]
470+ fn count ( self ) -> usize {
471+ self . len ( )
472+ }
473+
473474 fn last ( self ) -> Option < char > {
474475 match self . state {
475476 EscapeUnicodeState :: Done => None ,
@@ -483,6 +484,22 @@ impl Iterator for EscapeUnicode {
483484 }
484485}
485486
487+ #[ stable( feature = "exact_size_escape" , since = "1.11.0" ) ]
488+ impl ExactSizeIterator for EscapeUnicode {
489+ #[ inline]
490+ fn len ( & self ) -> usize {
491+ // The match is a single memory access with no branching
492+ self . hex_digit_idx + match self . state {
493+ EscapeUnicodeState :: Done => 0 ,
494+ EscapeUnicodeState :: RightBrace => 1 ,
495+ EscapeUnicodeState :: Value => 2 ,
496+ EscapeUnicodeState :: LeftBrace => 3 ,
497+ EscapeUnicodeState :: Type => 4 ,
498+ EscapeUnicodeState :: Backslash => 5 ,
499+ }
500+ }
501+ }
502+
486503/// An iterator that yields the literal escape code of a `char`.
487504///
488505/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
@@ -498,9 +515,9 @@ pub struct EscapeDefault {
498515
499516#[ derive( Clone , Debug ) ]
500517enum EscapeDefaultState {
501- Backslash ( char ) ,
502- Char ( char ) ,
503518 Done ,
519+ Char ( char ) ,
520+ Backslash ( char ) ,
504521 Unicode ( EscapeUnicode ) ,
505522}
506523
@@ -523,22 +540,15 @@ impl Iterator for EscapeDefault {
523540 }
524541 }
525542
543+ #[ inline]
526544 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
527- match self . state {
528- EscapeDefaultState :: Char ( _) => ( 1 , Some ( 1 ) ) ,
529- EscapeDefaultState :: Backslash ( _) => ( 2 , Some ( 2 ) ) ,
530- EscapeDefaultState :: Unicode ( ref iter) => iter. size_hint ( ) ,
531- EscapeDefaultState :: Done => ( 0 , Some ( 0 ) ) ,
532- }
545+ let n = self . len ( ) ;
546+ ( n, Some ( n) )
533547 }
534548
549+ #[ inline]
535550 fn count ( self ) -> usize {
536- match self . state {
537- EscapeDefaultState :: Char ( _) => 1 ,
538- EscapeDefaultState :: Unicode ( iter) => iter. count ( ) ,
539- EscapeDefaultState :: Done => 0 ,
540- EscapeDefaultState :: Backslash ( _) => 2 ,
541- }
551+ self . len ( )
542552 }
543553
544554 fn nth ( & mut self , n : usize ) -> Option < char > {
@@ -578,6 +588,18 @@ impl Iterator for EscapeDefault {
578588 }
579589}
580590
591+ #[ stable( feature = "exact_size_escape" , since = "1.11.0" ) ]
592+ impl ExactSizeIterator for EscapeDefault {
593+ fn len ( & self ) -> usize {
594+ match self . state {
595+ EscapeDefaultState :: Done => 0 ,
596+ EscapeDefaultState :: Char ( _) => 1 ,
597+ EscapeDefaultState :: Backslash ( _) => 2 ,
598+ EscapeDefaultState :: Unicode ( ref iter) => iter. len ( ) ,
599+ }
600+ }
601+ }
602+
581603/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
582604/// value.
583605///
0 commit comments