Skip to content

Commit 1e82fdf

Browse files
committed
Initial work to make String usable with feature(allocator_api).
More `allocator_api`-aware `String` implementations (Most allocator-irrelevant associated functions, Drain, and FromUtf8Error). More `allocator_api`-aware `String` implementations, including added `new_in` etc inherent impls. tidy, new_in etc, raw_parts_in etc, allocator(&self), FromUtf8Error impls, Extend, Pattern, PartialEq &str etc with String<A>, Display, Debug, Hash, Add(Assign), ToString, AsRef/AsMut, conversions Box<str, A> -> String<A>, &String -> Cow<str>, String<A> -> Vec<u8, A>; fmt::Write. Fix gdb/lldb integration for String<A>. Add some simple trait impls I missed. Borrow(Mut)<str> for String, From<String<A>> for Rc<str>/Arc<str>, Clone for Box<str, A>. Remove FIXMEs for String<A> APIs that don't already exist for Vec<T,A>. Rewrite `Clone for Box<str, A>` to avoid extra capacity/length checks converting from Vec. Also implement `clone_from` to re-use the allocation when the lengths are the same. Remove `From<String<A>> for Rc<str>`/`Arc` impls to allow for future alloc-ification of `Rc`/`Arc` Note: find out how to make "the full type name has been written to" errors be deterministic (./x.py test alone didn't do it). AsRef<OsStr> and AsRef<Path> for String<A: Allocator>
1 parent a6434ef commit 1e82fdf

File tree

6 files changed

+360
-91
lines changed

6 files changed

+360
-91
lines changed

library/alloc/src/boxed.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,11 +1848,23 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
18481848

18491849
#[cfg(not(no_global_oom_handling))]
18501850
#[stable(feature = "box_slice_clone", since = "1.3.0")]
1851-
impl Clone for Box<str> {
1851+
impl<A: Allocator + Clone> Clone for Box<str, A> {
18521852
fn clone(&self) -> Self {
1853-
// this makes a copy of the data
1854-
let buf: Box<[u8]> = self.as_bytes().into();
1855-
unsafe { from_boxed_utf8_unchecked(buf) }
1853+
let alloc = Box::allocator(self).clone();
1854+
let len = self.len();
1855+
let buf = RawVec::with_capacity_in(len, alloc);
1856+
unsafe {
1857+
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
1858+
from_boxed_utf8_unchecked(buf.into_box(len).assume_init())
1859+
}
1860+
}
1861+
1862+
fn clone_from(&mut self, other: &Self) {
1863+
if self.len() == other.len() {
1864+
unsafe { self.as_bytes_mut().copy_from_slice(other.as_bytes()) }
1865+
} else {
1866+
*self = other.clone();
1867+
}
18561868
}
18571869
}
18581870

library/alloc/src/str.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub use core::str::{from_raw_parts, from_raw_parts_mut};
4949
use core::unicode::conversions;
5050
use core::{mem, ptr};
5151

52+
use crate::alloc::{Allocator, Global};
5253
use crate::borrow::ToOwned;
5354
use crate::boxed::Box;
5455
use crate::slice::{Concat, Join, SliceIndex};
@@ -186,15 +187,15 @@ where
186187
}
187188

188189
#[stable(feature = "rust1", since = "1.0.0")]
189-
impl Borrow<str> for String {
190+
impl<A: Allocator> Borrow<str> for String<A> {
190191
#[inline]
191192
fn borrow(&self) -> &str {
192193
&self[..]
193194
}
194195
}
195196

196197
#[stable(feature = "string_borrow_mut", since = "1.36.0")]
197-
impl BorrowMut<str> for String {
198+
impl<A: Allocator> BorrowMut<str> for String<A> {
198199
#[inline]
199200
fn borrow_mut(&mut self) -> &mut str {
200201
&mut self[..]
@@ -235,7 +236,7 @@ impl str {
235236
#[stable(feature = "str_box_extras", since = "1.20.0")]
236237
#[must_use = "`self` will be dropped if the result is not used"]
237238
#[inline]
238-
pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
239+
pub fn into_boxed_bytes<A: Allocator>(self: Box<str, A>) -> Box<[u8], A> {
239240
self.into()
240241
}
241242

@@ -502,8 +503,8 @@ impl str {
502503
#[rustc_allow_incoherent_impl]
503504
#[must_use = "`self` will be dropped if the result is not used"]
504505
#[inline]
505-
pub fn into_string(self: Box<str>) -> String {
506-
let slice = Box::<[u8]>::from(self);
506+
pub fn into_string<A: Allocator>(self: Box<str, A>) -> String<A> {
507+
let slice = Box::<[u8], A>::from(self);
507508
unsafe { String::from_utf8_unchecked(slice.into_vec()) }
508509
}
509510

@@ -615,8 +616,9 @@ impl str {
615616
#[stable(feature = "str_box_extras", since = "1.20.0")]
616617
#[must_use]
617618
#[inline]
618-
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
619-
unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
619+
pub unsafe fn from_boxed_utf8_unchecked<A: Allocator>(v: Box<[u8], A>) -> Box<str, A> {
620+
let (raw, alloc) = Box::into_raw_with_allocator(v);
621+
unsafe { Box::from_raw_in(raw as *mut str, alloc) }
620622
}
621623

622624
/// Converts leading ascii bytes in `s` by calling the `convert` function.

0 commit comments

Comments
 (0)