about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGabriel Bjørnager Jensen <gabriel@achernar.io>2024-09-17 18:20:42 +0200
committerDavid Tolnay <dtolnay@gmail.com>2024-09-18 14:56:01 -0700
commitfb475e47594d089f1b670009ffcd38cea1544fb3 (patch)
treee9e0db4df350e4831f9e90b599f1b67a14555643
parente9e13a68d7271baac458addc056ffff6ddbbe57c (diff)
downloadrust-fb475e47594d089f1b670009ffcd38cea1544fb3.tar.gz
rust-fb475e47594d089f1b670009ffcd38cea1544fb3.zip
Mark and implement 'char::encode_utf8' as const.
-rw-r--r--library/core/src/char/methods.rs32
-rw-r--r--library/core/src/lib.rs1
2 files changed, 15 insertions, 18 deletions
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index bc5c7c32490..fcaa91184d3 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -672,8 +672,9 @@ impl char {
     /// 'ß'.encode_utf8(&mut b);
     /// ```
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
+    #[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
     #[inline]
-    pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
+    pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
         // SAFETY: `char` is not a surrogate, so this is valid UTF-8.
         unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) }
     }
@@ -1735,14 +1736,11 @@ impl EscapeDebugExtArgs {
 
 #[inline]
 const fn len_utf8(code: u32) -> usize {
-    if code < MAX_ONE_B {
-        1
-    } else if code < MAX_TWO_B {
-        2
-    } else if code < MAX_THREE_B {
-        3
-    } else {
-        4
+    match code {
+        ..MAX_ONE_B => 1,
+        ..MAX_TWO_B => 2,
+        ..MAX_THREE_B => 3,
+        _ => 4,
     }
 }
 
@@ -1760,11 +1758,12 @@ const fn len_utf8(code: u32) -> usize {
 /// Panics if the buffer is not large enough.
 /// A buffer of length four is large enough to encode any `char`.
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
+#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
 #[doc(hidden)]
 #[inline]
-pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
+pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
     let len = len_utf8(code);
-    match (len, &mut dst[..]) {
+    match (len, &mut *dst) {
         (1, [a, ..]) => {
             *a = code as u8;
         }
@@ -1783,14 +1782,11 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
             *c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
             *d = (code & 0x3F) as u8 | TAG_CONT;
         }
-        _ => panic!(
-            "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
-            len,
-            code,
-            dst.len(),
-        ),
+        // Note that we cannot format in constant expressions.
+        _ => panic!("encode_utf8: buffer does not have enough bytes to encode code point"),
     };
-    &mut dst[..len]
+    // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
+    unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
 }
 
 /// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 058dcf34532..f25f6922bca 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -119,6 +119,7 @@
 #![feature(const_bigint_helper_methods)]
 #![feature(const_black_box)]
 #![feature(const_cell_into_inner)]
+#![feature(const_char_encode_utf8)]
 #![feature(const_eval_select)]
 #![feature(const_exact_div)]
 #![feature(const_float_classify)]