File tree 1 file changed +14
-3
lines changed
1 file changed +14
-3
lines changed Original file line number Diff line number Diff line change @@ -6,8 +6,6 @@ use crate::fmt;
6
6
use crate :: mem:: transmute;
7
7
use crate :: str:: FromStr ;
8
8
9
- use super :: MAX ;
10
-
11
9
/// Converts a `u32` to a `char`.
12
10
///
13
11
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
@@ -271,7 +269,20 @@ impl FromStr for char {
271
269
272
270
#[ inline]
273
271
const fn char_try_from_u32 ( i : u32 ) -> Result < char , CharTryFromError > {
274
- if ( i > MAX as u32 ) || ( i >= 0xD800 && i <= 0xDFFF ) {
272
+ // This is an optimized version of the check
273
+ // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF),
274
+ // which can also be written as
275
+ // i >= 0x110000 || (i >= 0xD800 && i < 0xE000).
276
+ //
277
+ // The XOR with 0xD800 permutes the ranges such that 0xD800..0xE000 is
278
+ // mapped to 0x0000..0x0800, while keeping all the high bits outside 0xFFFF the same.
279
+ // In particular, numbers >= 0x110000 stay in this range.
280
+ //
281
+ // Subtracting 0x800 causes 0x0000..0x0800 to wrap, meaning that a single
282
+ // unsigned comparison against 0x110000 - 0x800 will detect both the wrapped
283
+ // surrogate range as well as the numbers originally larger than 0x110000.
284
+ //
285
+ if ( i ^ 0xD800 ) . wrapping_sub ( 0x800 ) >= 0x110000 - 0x800 {
275
286
Err ( CharTryFromError ( ( ) ) )
276
287
} else {
277
288
// SAFETY: checked that it's a legal unicode value
You can’t perform that action at this time.
0 commit comments