2
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
5
- use std:: borrow:: { Borrow , Cow } ;
5
+ use std:: borrow:: Borrow ;
6
6
use std:: cmp;
7
7
use std:: fmt;
8
8
use std:: hash;
@@ -21,7 +21,7 @@ use std::usize;
21
21
/// FIXME(https://github.com/rust-lang/rfcs/issues/1230): use an actual enum if/when
22
22
/// the compiler can do this layout optimization.
23
23
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.
25
25
/// In the meantime we abuse `&'static _` to get the effect of `NonZero<*const _>`.
26
26
/// `ptr` doesn’t really have the 'static lifetime!
27
27
ptr : & ' static ( ) ,
@@ -55,19 +55,24 @@ impl<'a> From<&'a str> for CowRcStr<'a> {
55
55
}
56
56
}
57
57
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 > {
59
66
#[ inline]
60
- fn from ( s : Rc < String > ) -> Self {
67
+ fn from_rc ( s : Rc < String > ) -> Self {
61
68
let ptr = unsafe { & * ( Rc :: into_raw ( s) as * const ( ) ) } ;
62
69
CowRcStr {
63
70
ptr : ptr,
64
71
borrowed_len_or_max : usize:: MAX ,
65
72
phantom : PhantomData ,
66
73
}
67
74
}
68
- }
69
75
70
- impl < ' a > CowRcStr < ' a > {
71
76
#[ inline]
72
77
fn unpack ( & self ) -> Result < & ' a str , * const String > {
73
78
if self . borrowed_len_or_max == usize:: MAX {
@@ -82,24 +87,21 @@ impl<'a> CowRcStr<'a> {
82
87
}
83
88
}
84
89
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
-
95
90
/// Convert into `String`, re-using an existing memory allocation if possible.
96
91
#[ inline]
97
92
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 {
99
99
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 ( ) )
103
105
}
104
106
}
105
107
}
@@ -115,7 +117,7 @@ impl<'a> Clone for CowRcStr<'a> {
115
117
} ;
116
118
let new_rc = rc. clone ( ) ;
117
119
mem:: forget ( rc) ; // Don’t actually take ownership of this strong reference
118
- new_rc . into ( )
120
+ CowRcStr :: from_rc ( new_rc )
119
121
}
120
122
Ok ( _) => {
121
123
CowRcStr { ..* self }
@@ -146,37 +148,6 @@ impl<'a> Deref for CowRcStr<'a> {
146
148
}
147
149
}
148
150
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
-
180
151
// Boilerplate / trivial impls below.
181
152
182
153
impl < ' a > AsRef < str > for CowRcStr < ' a > {
0 commit comments