]> git.lizzy.rs Git - rust.git/blobdiff - library/core/src/char/methods.rs
Make char methods const
[rust.git] / library / core / src / char / methods.rs
index 2baea7842a796ed12293d701b8e872f66d0d49d7..e292fe2cb9daa74a220b6b7516e369a6456d2134 100644 (file)
@@ -1,5 +1,6 @@
 //! impl char {}
 
+use crate::intrinsics::likely;
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
 use crate::unicode::printable::is_printable;
@@ -331,14 +332,11 @@ pub fn is_digit(self, radix: u32) -> bool {
     #[inline]
     pub fn to_digit(self, radix: u32) -> Option<u32> {
         assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
-
         // the code is split up here to improve execution speed for cases where
         // the `radix` is constant and 10 or smaller
-        let val = if radix <= 10 {
-            match self {
-                '0'..='9' => self as u32 - '0' as u32,
-                _ => return None,
-            }
+        let val = if likely(radix <= 10) {
+            // If not a digit, a number greater than radix will be created.
+            (self as u32).wrapping_sub('0' as u32)
         } else {
             match self {
                 '0'..='9' => self as u32 - '0' as u32,
@@ -386,8 +384,9 @@ pub fn to_digit(self, radix: u32) -> Option<u32> {
     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_char_escape_unicode", since = "1.50.0")]
     #[inline]
-    pub fn escape_unicode(self) -> EscapeUnicode {
+    pub const fn escape_unicode(self) -> EscapeUnicode {
         let c = self as u32;
 
         // or-ing 1 ensures that for c==0 the code computes that one
@@ -512,8 +511,9 @@ pub fn escape_debug(self) -> EscapeDebug {
     /// assert_eq!('"'.escape_default().to_string(), "\\\"");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_char_escape_default", since = "1.50.0")]
     #[inline]
-    pub fn escape_default(self) -> EscapeDefault {
+    pub const fn escape_default(self) -> EscapeDefault {
         let init_state = match self {
             '\t' => EscapeDefaultState::Backslash('t'),
             '\r' => EscapeDefaultState::Backslash('r'),
@@ -571,8 +571,9 @@ pub fn escape_default(self) -> EscapeDefault {
     /// assert_eq!(len, tokyo.len());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_char_len_utf", since = "1.50.0")]
     #[inline]
-    pub fn len_utf8(self) -> usize {
+    pub const fn len_utf8(self) -> usize {
         len_utf8(self as u32)
     }
 
@@ -596,8 +597,9 @@ pub fn len_utf8(self) -> usize {
     /// assert_eq!(len, 2);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_char_len_utf", since = "1.50.0")]
     #[inline]
-    pub fn len_utf16(self) -> usize {
+    pub const fn len_utf16(self) -> usize {
         let ch = self as u32;
         if (ch & 0xFFFF) == ch { 1 } else { 2 }
     }
@@ -1088,9 +1090,14 @@ pub const fn is_ascii(&self) -> bool {
     /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase
     /// [`to_uppercase()`]: #method.to_uppercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.50.0")]
     #[inline]
-    pub fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self }
+    pub const fn to_ascii_uppercase(&self) -> char {
+        if self.is_ascii_lowercase() {
+            (*self as u8).ascii_change_case_unchecked() as char
+        } else {
+            *self
+        }
     }
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -1116,9 +1123,14 @@ pub fn to_ascii_uppercase(&self) -> char {
     /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase
     /// [`to_lowercase()`]: #method.to_lowercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.50.0")]
     #[inline]
-    pub fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self }
+    pub const fn to_ascii_lowercase(&self) -> char {
+        if self.is_ascii_uppercase() {
+            (*self as u8).ascii_change_case_unchecked() as char
+        } else {
+            *self
+        }
     }
 
     /// Checks that two values are an ASCII case-insensitive match.
@@ -1137,8 +1149,9 @@ pub fn to_ascii_lowercase(&self) -> char {
     /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.50.0")]
     #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &char) -> bool {
+    pub const fn eq_ignore_ascii_case(&self, other: &char) -> bool {
         self.to_ascii_lowercase() == other.to_ascii_lowercase()
     }
 
@@ -1555,7 +1568,7 @@ pub const fn is_ascii_control(&self) -> bool {
 }
 
 #[inline]
-fn len_utf8(code: u32) -> usize {
+const fn len_utf8(code: u32) -> usize {
     if code < MAX_ONE_B {
         1
     } else if code < MAX_TWO_B {