Skip to content

Commit 8ee7afe

Browse files
committed
Add raw str methods
This patch adds the following methods to `*const str` and `*mut str`: - `len` - `as_ptr` (`as_mut_ptr`) - `get_unchecked` (`get_unchecked_mut`) Similar methods have already existed for raw slices.
1 parent e15212f commit 8ee7afe

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

library/core/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
#![feature(const_slice_from_raw_parts)]
134134
#![feature(const_slice_ptr_len)]
135135
#![feature(const_str_from_utf8_unchecked_mut)]
136+
#![cfg_attr(not(bootstrap), feature(const_str_ptr_len))]
136137
#![feature(const_swap)]
137138
#![feature(const_trait_impl)]
138139
#![feature(const_type_id)]
@@ -193,6 +194,9 @@
193194
#![feature(simd_ffi)]
194195
#![feature(staged_api)]
195196
#![feature(stmt_expr_attributes)]
197+
#![cfg_attr(not(bootstrap), feature(str_ptr_len))]
198+
#![cfg_attr(not(bootstrap), feature(str_ptr_as_ptr))]
199+
#![cfg_attr(not(bootstrap), feature(str_ptr_get))]
196200
#![feature(trait_alias)]
197201
#![feature(transparent_unions)]
198202
#![feature(try_blocks)]

library/core/src/ptr/const_ptr.rs

+80
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,86 @@ impl<T> *const [T] {
10301030
}
10311031
}
10321032

1033+
#[cfg(not(bootstrap))]
1034+
#[lang = "const_str_ptr"]
1035+
impl *const str {
1036+
/// Returns the length of a raw string slice.
1037+
///
1038+
/// The returned value is the number of **bytes**, not the number of characters.
1039+
///
1040+
/// This function is safe, even when the raw string slice cannot be cast to a slice
1041+
/// reference because the pointer is null or unaligned.
1042+
///
1043+
/// # Examples
1044+
///
1045+
/// ```rust
1046+
/// #![feature(str_ptr_len)]
1047+
///
1048+
/// let str: *const str = "abc";
1049+
/// assert_eq!(str.len(), 3);
1050+
/// ```
1051+
#[inline]
1052+
#[unstable(feature = "str_ptr_len", issue = "71146")]
1053+
#[rustc_const_unstable(feature = "const_str_ptr_len", issue = "71146")]
1054+
pub const fn len(self) -> usize {
1055+
metadata(self)
1056+
}
1057+
1058+
/// Returns a raw pointer to the string slice's buffer.
1059+
///
1060+
/// This is equivalent to casting `self` to `*const u8`, but more type-safe.
1061+
///
1062+
/// # Examples
1063+
///
1064+
/// ```rust
1065+
/// #![feature(str_ptr_as_ptr)]
1066+
///
1067+
/// let str: *const str = "a";
1068+
/// let ptr: *const u8 = str.as_ptr();
1069+
/// assert_eq!(unsafe { *ptr }, b'a');
1070+
/// ```
1071+
#[inline]
1072+
#[unstable(feature = "str_ptr_as_ptr", issue = "74265")]
1073+
#[rustc_const_unstable(feature = "str_ptr_as_ptr", issue = "74265")]
1074+
pub const fn as_ptr(self) -> *const u8 {
1075+
self as *const u8
1076+
}
1077+
1078+
/// Returns a raw pointer to an substring, without doing bounds
1079+
/// checking.
1080+
///
1081+
/// # Safety
1082+
///
1083+
/// Calling this method with an out-of-bounds index or when `self` is not dereferenceable
1084+
/// is *[undefined behavior]* even if the resulting pointer is not used.
1085+
///
1086+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1087+
///
1088+
/// Note that calling this function with an index that does not lie on an UTF-8 sequence boundaries
1089+
/// is safe, but dereferencing the pointer returned by such call is unsound.
1090+
///
1091+
/// # Examples
1092+
///
1093+
/// ```
1094+
/// #![feature(str_ptr_get)]
1095+
///
1096+
/// let x = "abc" as *const str;
1097+
///
1098+
/// unsafe {
1099+
/// assert_eq!(&*x.get_unchecked(1..), "bc");
1100+
/// }
1101+
/// ```
1102+
#[unstable(feature = "str_ptr_get", issue = "74265")]
1103+
#[inline]
1104+
pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
1105+
where
1106+
I: SliceIndex<str>,
1107+
{
1108+
// SAFETY: the caller ensures that `self` is dereferenceable and `index` is in-bounds.
1109+
unsafe { index.get_unchecked(self) }
1110+
}
1111+
}
1112+
10331113
// Equality for pointers
10341114
#[stable(feature = "rust1", since = "1.0.0")]
10351115
impl<T: ?Sized> PartialEq for *const T {

library/core/src/ptr/mut_ptr.rs

+87
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,93 @@ impl<T> *mut [T] {
13461346
}
13471347
}
13481348

1349+
#[cfg(not(bootstrap))]
1350+
#[lang = "mut_str_ptr"]
1351+
impl *mut str {
1352+
/// Returns the length of a raw string slice.
1353+
///
1354+
/// The returned value is the number of **bytes**, not the number of characters.
1355+
///
1356+
/// This function is safe, even when the raw string slice cannot be cast to a slice
1357+
/// reference because the pointer is null or unaligned.
1358+
///
1359+
/// # Examples
1360+
///
1361+
/// ```rust
1362+
/// #![feature(str_ptr_len)]
1363+
///
1364+
/// let mut arr = [b'a', b'b', b'c'];
1365+
/// let s: &mut str = std::str::from_utf8_mut(&mut arr).unwrap();
1366+
/// let s: *mut str = s as *mut str;
1367+
///
1368+
/// assert_eq!(s.len(), 3);
1369+
/// ```
1370+
#[inline]
1371+
#[unstable(feature = "str_ptr_len", issue = "71146")]
1372+
#[rustc_const_unstable(feature = "const_str_ptr_len", issue = "71146")]
1373+
pub const fn len(self) -> usize {
1374+
metadata(self)
1375+
}
1376+
1377+
/// Returns a raw pointer to the string slice's buffer.
1378+
///
1379+
/// This is equivalent to casting `self` to `*mut u8`, but more type-safe.
1380+
///
1381+
/// # Examples
1382+
///
1383+
/// ```rust
1384+
/// #![feature(str_ptr_as_ptr)]
1385+
///
1386+
/// let mut arr = [b'a', b'b', b'c'];
1387+
/// let s: &mut str = std::str::from_utf8_mut(&mut arr).unwrap();
1388+
/// let s: *mut str = s as *mut str;
1389+
///
1390+
/// assert_eq!(s.as_mut_ptr(), arr.as_mut_ptr());
1391+
/// ```
1392+
#[inline]
1393+
#[unstable(feature = "str_ptr_as_ptr", issue = "74265")]
1394+
#[rustc_const_unstable(feature = "str_ptr_as_ptr", issue = "74265")]
1395+
pub const fn as_mut_ptr(self) -> *mut u8 {
1396+
self as *mut u8
1397+
}
1398+
1399+
/// Returns a raw pointer to an substring, without doing bounds
1400+
/// checking.
1401+
///
1402+
/// # Safety
1403+
///
1404+
/// Calling this method with an out-of-bounds index or when `self` is not dereferenceable
1405+
/// is *[undefined behavior]* even if the resulting pointer is not used.
1406+
///
1407+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1408+
///
1409+
/// Note that calling this function with an index that does not lie on an UTF-8 sequence boundaries
1410+
/// is safe, but dereferencing the pointer returned by such call is unsound.
1411+
///
1412+
/// # Examples
1413+
///
1414+
/// ```
1415+
/// #![feature(str_ptr_get)]
1416+
///
1417+
/// let mut x = [b'a', b'b', b'c'];
1418+
/// let x: &mut str = std::str::from_utf8_mut(&mut x).unwrap();
1419+
/// let x: *mut str = x as *mut str;
1420+
///
1421+
/// unsafe {
1422+
/// assert_eq!(&*x.get_unchecked_mut(1..), "bc");
1423+
/// }
1424+
/// ```
1425+
#[unstable(feature = "str_ptr_get", issue = "74265")]
1426+
#[inline]
1427+
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
1428+
where
1429+
I: SliceIndex<str>,
1430+
{
1431+
// SAFETY: the caller ensures that `self` is dereferenceable and `index` is in-bounds.
1432+
unsafe { index.get_unchecked_mut(self) }
1433+
}
1434+
}
1435+
13491436
// Equality for pointers
13501437
#[stable(feature = "rust1", since = "1.0.0")]
13511438
impl<T: ?Sized> PartialEq for *mut T {

0 commit comments

Comments
 (0)