@@ -299,7 +299,20 @@ impl CharExt for char {
299
299
300
300
#[ inline]
301
301
fn escape_unicode ( self ) -> EscapeUnicode {
302
- EscapeUnicode { c : self , state : EscapeUnicodeState :: Backslash }
302
+ let c = self as u32 ;
303
+
304
+ // or-ing 1 ensures that for c==0 the code computes that one
305
+ // digit should be printed and (which is the same) avoids the
306
+ // (31 - 32) underflow
307
+ let msb = 31 - ( c | 1 ) . leading_zeros ( ) ;
308
+
309
+ // the index of the most significant hex digit
310
+ let ms_hex_digit = msb / 4 ;
311
+ EscapeUnicode {
312
+ c : self ,
313
+ state : EscapeUnicodeState :: Backslash ,
314
+ hex_digit_idx : ms_hex_digit as usize ,
315
+ }
303
316
}
304
317
305
318
#[ inline]
@@ -392,15 +405,20 @@ impl CharExt for char {
392
405
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
393
406
pub struct EscapeUnicode {
394
407
c : char ,
395
- state : EscapeUnicodeState
408
+ state : EscapeUnicodeState ,
409
+
410
+ // The index of the next hex digit to be printed (0 if none),
411
+ // i.e. the number of remaining hex digits to be printed;
412
+ // increasing from the least significant digit: 0x543210
413
+ hex_digit_idx : usize ,
396
414
}
397
415
398
416
#[ derive( Clone , Debug ) ]
399
417
enum EscapeUnicodeState {
400
418
Backslash ,
401
419
Type ,
402
420
LeftBrace ,
403
- Value ( usize ) ,
421
+ Value ,
404
422
RightBrace ,
405
423
Done ,
406
424
}
@@ -420,19 +438,16 @@ impl Iterator for EscapeUnicode {
420
438
Some ( 'u' )
421
439
}
422
440
EscapeUnicodeState :: LeftBrace => {
423
- let mut n = 0 ;
424
- while ( self . c as u32 ) >> ( 4 * ( n + 1 ) ) != 0 {
425
- n += 1 ;
426
- }
427
- self . state = EscapeUnicodeState :: Value ( n) ;
441
+ self . state = EscapeUnicodeState :: Value ;
428
442
Some ( '{' )
429
443
}
430
- EscapeUnicodeState :: Value ( offset) => {
431
- let c = from_digit ( ( ( self . c as u32 ) >> ( offset * 4 ) ) & 0xf , 16 ) . unwrap ( ) ;
432
- if offset == 0 {
444
+ EscapeUnicodeState :: Value => {
445
+ let hex_digit = ( ( self . c as u32 ) >> ( self . hex_digit_idx * 4 ) ) & 0xf ;
446
+ let c = from_digit ( hex_digit, 16 ) . unwrap ( ) ;
447
+ if self . hex_digit_idx == 0 {
433
448
self . state = EscapeUnicodeState :: RightBrace ;
434
449
} else {
435
- self . state = EscapeUnicodeState :: Value ( offset - 1 ) ;
450
+ self . hex_digit_idx -= 1 ;
436
451
}
437
452
Some ( c)
438
453
}
@@ -445,18 +460,15 @@ impl Iterator for EscapeUnicode {
445
460
}
446
461
447
462
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
448
- let mut n = 0 ;
449
- while ( self . c as usize ) >> ( 4 * ( n + 1 ) ) != 0 {
450
- n += 1 ;
451
- }
452
463
let n = match self . state {
453
- EscapeUnicodeState :: Backslash => n + 5 ,
454
- EscapeUnicodeState :: Type => n + 4 ,
455
- EscapeUnicodeState :: LeftBrace => n + 3 ,
456
- EscapeUnicodeState :: Value ( offset ) => offset + 2 ,
464
+ EscapeUnicodeState :: Backslash => 5 ,
465
+ EscapeUnicodeState :: Type => 4 ,
466
+ EscapeUnicodeState :: LeftBrace => 3 ,
467
+ EscapeUnicodeState :: Value => 2 ,
457
468
EscapeUnicodeState :: RightBrace => 1 ,
458
469
EscapeUnicodeState :: Done => 0 ,
459
470
} ;
471
+ let n = n + self . hex_digit_idx ;
460
472
( n, Some ( n) )
461
473
}
462
474
}
0 commit comments