Skip to content

Commit 32733fb

Browse files
committed
Remove CowRcStr APIs that might allocate and used to never do so.
1 parent f4cfca9 commit 32733fb

File tree

1 file changed

+23
-52
lines changed

1 file changed

+23
-52
lines changed

src/compact_cow_str.rs

Lines changed: 23 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use std::borrow::{Borrow, Cow};
5+
use std::borrow::Borrow;
66
use std::cmp;
77
use std::fmt;
88
use std::hash;
@@ -21,7 +21,7 @@ use std::usize;
2121
/// FIXME(https://github.com/rust-lang/rfcs/issues/1230): use an actual enum if/when
2222
/// the compiler can do this layout optimization.
2323
pub struct CowRcStr<'a> {
24-
/// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared
24+
/// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared.
2525
/// In the meantime we abuse `&'static _` to get the effect of `NonZero<*const _>`.
2626
/// `ptr` doesn’t really have the 'static lifetime!
2727
ptr: &'static (),
@@ -55,19 +55,24 @@ impl<'a> From<&'a str> for CowRcStr<'a> {
5555
}
5656
}
5757

58-
impl<'a> From<Rc<String>> for CowRcStr<'a> {
58+
impl<'a> From<String> for CowRcStr<'a> {
59+
#[inline]
60+
fn from(s: String) -> Self {
61+
CowRcStr::from_rc(Rc::new(s))
62+
}
63+
}
64+
65+
impl<'a> CowRcStr<'a> {
5966
#[inline]
60-
fn from(s: Rc<String>) -> Self {
67+
fn from_rc(s: Rc<String>) -> Self {
6168
let ptr = unsafe { &*(Rc::into_raw(s) as *const ()) };
6269
CowRcStr {
6370
ptr: ptr,
6471
borrowed_len_or_max: usize::MAX,
6572
phantom: PhantomData,
6673
}
6774
}
68-
}
6975

70-
impl<'a> CowRcStr<'a> {
7176
#[inline]
7277
fn unpack(&self) -> Result<&'a str, *const String> {
7378
if self.borrowed_len_or_max == usize::MAX {
@@ -82,24 +87,21 @@ impl<'a> CowRcStr<'a> {
8287
}
8388
}
8489

85-
#[inline]
86-
fn into_enum(self) -> Result<&'a str, Rc<String>> {
87-
self.unpack().map_err(|ptr| {
88-
mem::forget(self);
89-
unsafe {
90-
Rc::from_raw(ptr)
91-
}
92-
})
93-
}
94-
9590
/// Convert into `String`, re-using an existing memory allocation if possible.
9691
#[inline]
9792
pub fn into_owned(self) -> String {
98-
match self.into_enum() {
93+
let unpacked = self.unpack();
94+
95+
// Inhibit destructor: we’re taking ownership of this strong reference (if any)
96+
mem::forget(self);
97+
98+
match unpacked {
9999
Ok(s) => s.to_owned(),
100-
Err(rc) => match Rc::try_unwrap(rc) {
101-
Ok(s) => s,
102-
Err(rc) => (*rc).clone()
100+
Err(ptr) => {
101+
let rc = unsafe {
102+
Rc::from_raw(ptr)
103+
};
104+
Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone())
103105
}
104106
}
105107
}
@@ -115,7 +117,7 @@ impl<'a> Clone for CowRcStr<'a> {
115117
};
116118
let new_rc = rc.clone();
117119
mem::forget(rc); // Don’t actually take ownership of this strong reference
118-
new_rc.into()
120+
CowRcStr::from_rc(new_rc)
119121
}
120122
Ok(_) => {
121123
CowRcStr { ..*self }
@@ -146,37 +148,6 @@ impl<'a> Deref for CowRcStr<'a> {
146148
}
147149
}
148150

149-
impl<'a> From<CowRcStr<'a>> for Cow<'a, str> {
150-
#[inline]
151-
fn from(cow: CowRcStr<'a>) -> Self {
152-
match cow.into_enum() {
153-
Ok(s) => Cow::Borrowed(s),
154-
Err(rc) => match Rc::try_unwrap(rc) {
155-
Ok(s) => Cow::Owned(s),
156-
Err(rc) => Cow::Owned((*rc).clone())
157-
}
158-
}
159-
}
160-
}
161-
162-
impl<'a> From<String> for CowRcStr<'a> {
163-
#[inline]
164-
fn from(s: String) -> Self {
165-
Self::from(Rc::new(s))
166-
}
167-
}
168-
169-
impl<'a> From<Cow<'a, str>> for CowRcStr<'a> {
170-
#[inline]
171-
fn from(s: Cow<'a, str>) -> Self {
172-
match s {
173-
Cow::Borrowed(s) => Self::from(s),
174-
Cow::Owned(s) => Self::from(s),
175-
}
176-
}
177-
}
178-
179-
180151
// Boilerplate / trivial impls below.
181152

182153
impl<'a> AsRef<str> for CowRcStr<'a> {

0 commit comments

Comments
 (0)