File tree Expand file tree Collapse file tree 1 file changed +14
-3
lines changed Expand file tree Collapse file tree 1 file changed +14
-3
lines changed Original file line number Diff line number Diff line change @@ -6,8 +6,6 @@ use crate::fmt;
66use crate :: mem:: transmute;
77use crate :: str:: FromStr ;
88
9- use super :: MAX ;
10-
119/// Converts a `u32` to a `char`.
1210///
1311/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
@@ -271,7 +269,20 @@ impl FromStr for char {
271269
272270#[ inline]
273271const 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 {
275286 Err ( CharTryFromError ( ( ) ) )
276287 } else {
277288 // SAFETY: checked that it's a legal unicode value
You can’t perform that action at this time.
0 commit comments