]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | //! A module for working with borrowed data. |
2 | ||
3 | #![stable(feature = "rust1", since = "1.0.0")] | |
4 | ||
9e0c209e | 5 | use core::cmp::Ordering; |
85aaf69f | 6 | use core::hash::{Hash, Hasher}; |
c30ab7b3 | 7 | use core::ops::{Add, AddAssign, Deref}; |
85aaf69f | 8 | |
92a42be0 | 9 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e | 10 | pub use core::borrow::{Borrow, BorrowMut}; |
85aaf69f | 11 | |
9fa01778 XL |
12 | use crate::fmt; |
13 | use crate::string::String; | |
14 | ||
15 | use Cow::*; | |
16 | ||
85aaf69f | 17 | #[stable(feature = "rust1", since = "1.0.0")] |
92a42be0 SL |
18 | impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> |
19 | where B: ToOwned, | |
20 | <B as ToOwned>::Owned: 'a | |
21 | { | |
85aaf69f SL |
22 | fn borrow(&self) -> &B { |
23 | &**self | |
24 | } | |
25 | } | |
26 | ||
9346a6ac | 27 | /// A generalization of `Clone` to borrowed data. |
85aaf69f SL |
28 | /// |
29 | /// Some types make it possible to go from borrowed to owned, usually by | |
30 | /// implementing the `Clone` trait. But `Clone` works only for going from `&T` | |
31 | /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data | |
32 | /// from any borrow of a given type. | |
33 | #[stable(feature = "rust1", since = "1.0.0")] | |
34 | pub trait ToOwned { | |
48663c56 | 35 | /// The resulting type after obtaining ownership. |
85aaf69f SL |
36 | #[stable(feature = "rust1", since = "1.0.0")] |
37 | type Owned: Borrow<Self>; | |
38 | ||
9346a6ac | 39 | /// Creates owned data from borrowed data, usually by cloning. |
54a0048b SL |
40 | /// |
41 | /// # Examples | |
42 | /// | |
43 | /// Basic usage: | |
44 | /// | |
45 | /// ``` | |
8bb4bdeb XL |
46 | /// let s: &str = "a"; |
47 | /// let ss: String = s.to_owned(); | |
54a0048b | 48 | /// |
8bb4bdeb XL |
49 | /// let v: &[i32] = &[1, 2]; |
50 | /// let vv: Vec<i32> = v.to_owned(); | |
54a0048b | 51 | /// ``` |
85aaf69f | 52 | #[stable(feature = "rust1", since = "1.0.0")] |
83c7162d | 53 | #[must_use = "cloning is often expensive and is not expected to have side effects"] |
85aaf69f | 54 | fn to_owned(&self) -> Self::Owned; |
cc61c64b XL |
55 | |
56 | /// Uses borrowed data to replace owned data, usually by cloning. | |
57 | /// | |
58 | /// This is borrow-generalized version of `Clone::clone_from`. | |
59 | /// | |
60 | /// # Examples | |
61 | /// | |
62 | /// Basic usage: | |
63 | /// | |
64 | /// ``` | |
65 | /// # #![feature(toowned_clone_into)] | |
66 | /// let mut s: String = String::new(); | |
67 | /// "hello".clone_into(&mut s); | |
68 | /// | |
69 | /// let mut v: Vec<i32> = Vec::new(); | |
70 | /// [1, 2][..].clone_into(&mut v); | |
71 | /// ``` | |
72 | #[unstable(feature = "toowned_clone_into", | |
73 | reason = "recently added", | |
74 | issue = "41263")] | |
75 | fn clone_into(&self, target: &mut Self::Owned) { | |
76 | *target = self.to_owned(); | |
77 | } | |
85aaf69f SL |
78 | } |
79 | ||
80 | #[stable(feature = "rust1", since = "1.0.0")] | |
32a655c1 SL |
81 | impl<T> ToOwned for T |
82 | where T: Clone | |
83 | { | |
85aaf69f | 84 | type Owned = T; |
92a42be0 SL |
85 | fn to_owned(&self) -> T { |
86 | self.clone() | |
87 | } | |
cc61c64b XL |
88 | |
89 | fn clone_into(&self, target: &mut T) { | |
90 | target.clone_from(self); | |
91 | } | |
85aaf69f SL |
92 | } |
93 | ||
94 | /// A clone-on-write smart pointer. | |
95 | /// | |
96 | /// The type `Cow` is a smart pointer providing clone-on-write functionality: it | |
97 | /// can enclose and provide immutable access to borrowed data, and clone the | |
98 | /// data lazily when mutation or ownership is required. The type is designed to | |
99 | /// work with general borrowed data via the `Borrow` trait. | |
100 | /// | |
9346a6ac | 101 | /// `Cow` implements `Deref`, which means that you can call |
85aaf69f | 102 | /// non-mutating methods directly on the data it encloses. If mutation |
9346a6ac | 103 | /// is desired, `to_mut` will obtain a mutable reference to an owned |
85aaf69f SL |
104 | /// value, cloning if necessary. |
105 | /// | |
c34b1796 | 106 | /// # Examples |
85aaf69f | 107 | /// |
c34b1796 | 108 | /// ``` |
85aaf69f SL |
109 | /// use std::borrow::Cow; |
110 | /// | |
c34b1796 | 111 | /// fn abs_all(input: &mut Cow<[i32]>) { |
85aaf69f SL |
112 | /// for i in 0..input.len() { |
113 | /// let v = input[i]; | |
114 | /// if v < 0 { | |
c30ab7b3 | 115 | /// // Clones into a vector if not already owned. |
85aaf69f SL |
116 | /// input.to_mut()[i] = -v; |
117 | /// } | |
118 | /// } | |
119 | /// } | |
c30ab7b3 SL |
120 | /// |
121 | /// // No clone occurs because `input` doesn't need to be mutated. | |
122 | /// let slice = [0, 1, 2]; | |
123 | /// let mut input = Cow::from(&slice[..]); | |
124 | /// abs_all(&mut input); | |
125 | /// | |
126 | /// // Clone occurs because `input` needs to be mutated. | |
127 | /// let slice = [-1, 0, 1]; | |
128 | /// let mut input = Cow::from(&slice[..]); | |
129 | /// abs_all(&mut input); | |
130 | /// | |
131 | /// // No clone occurs because `input` is already owned. | |
132 | /// let mut input = Cow::from(vec![-1, 0, 1]); | |
133 | /// abs_all(&mut input); | |
85aaf69f | 134 | /// ``` |
b7449926 XL |
135 | /// |
136 | /// Another example showing how to keep `Cow` in a struct: | |
137 | /// | |
138 | /// ``` | |
532ac7d7 | 139 | /// use std::borrow::Cow; |
b7449926 | 140 | /// |
9fa01778 | 141 | /// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> { |
b7449926 XL |
142 | /// values: Cow<'a, [X]>, |
143 | /// } | |
144 | /// | |
9fa01778 | 145 | /// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned<Owned = Vec<X>> { |
b7449926 XL |
146 | /// fn new(v: Cow<'a, [X]>) -> Self { |
147 | /// Items { values: v } | |
148 | /// } | |
149 | /// } | |
150 | /// | |
151 | /// // Creates a container from borrowed values of a slice | |
152 | /// let readonly = [1, 2]; | |
153 | /// let borrowed = Items::new((&readonly[..]).into()); | |
154 | /// match borrowed { | |
155 | /// Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b), | |
156 | /// _ => panic!("expect borrowed value"), | |
157 | /// } | |
158 | /// | |
159 | /// let mut clone_on_write = borrowed; | |
160 | /// // Mutates the data from slice into owned vec and pushes a new value on top | |
161 | /// clone_on_write.values.to_mut().push(3); | |
162 | /// println!("clone_on_write = {:?}", clone_on_write.values); | |
163 | /// | |
164 | /// // The data was mutated. Let check it out. | |
165 | /// match clone_on_write { | |
166 | /// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"), | |
167 | /// _ => panic!("expect owned data"), | |
168 | /// } | |
169 | /// ``` | |
85aaf69f | 170 | #[stable(feature = "rust1", since = "1.0.0")] |
92a42be0 SL |
171 | pub enum Cow<'a, B: ?Sized + 'a> |
172 | where B: ToOwned | |
173 | { | |
85aaf69f SL |
174 | /// Borrowed data. |
175 | #[stable(feature = "rust1", since = "1.0.0")] | |
32a655c1 SL |
176 | Borrowed(#[stable(feature = "rust1", since = "1.0.0")] |
177 | &'a B), | |
85aaf69f SL |
178 | |
179 | /// Owned data. | |
180 | #[stable(feature = "rust1", since = "1.0.0")] | |
32a655c1 SL |
181 | Owned(#[stable(feature = "rust1", since = "1.0.0")] |
182 | <B as ToOwned>::Owned), | |
85aaf69f SL |
183 | } |
184 | ||
185 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 XL |
186 | impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> { |
187 | fn clone(&self) -> Self { | |
85aaf69f SL |
188 | match *self { |
189 | Borrowed(b) => Borrowed(b), | |
190 | Owned(ref o) => { | |
191 | let b: &B = o.borrow(); | |
192 | Owned(b.to_owned()) | |
92a42be0 | 193 | } |
85aaf69f SL |
194 | } |
195 | } | |
cc61c64b | 196 | |
9fa01778 | 197 | fn clone_from(&mut self, source: &Self) { |
cc61c64b XL |
198 | if let Owned(ref mut dest) = *self { |
199 | if let Owned(ref o) = *source { | |
200 | o.borrow().clone_into(dest); | |
201 | return; | |
202 | } | |
203 | } | |
204 | ||
205 | *self = source.clone(); | |
206 | } | |
85aaf69f SL |
207 | } |
208 | ||
9fa01778 | 209 | impl<B: ?Sized + ToOwned> Cow<'_, B> { |
9346a6ac | 210 | /// Acquires a mutable reference to the owned form of the data. |
85aaf69f | 211 | /// |
c1a9b12d | 212 | /// Clones the data if it is not already owned. |
c34b1796 AL |
213 | /// |
214 | /// # Examples | |
215 | /// | |
216 | /// ``` | |
217 | /// use std::borrow::Cow; | |
218 | /// | |
7cac9316 XL |
219 | /// let mut cow = Cow::Borrowed("foo"); |
220 | /// cow.to_mut().make_ascii_uppercase(); | |
c34b1796 | 221 | /// |
7cac9316 XL |
222 | /// assert_eq!( |
223 | /// cow, | |
224 | /// Cow::Owned(String::from("FOO")) as Cow<str> | |
225 | /// ); | |
c34b1796 | 226 | /// ``` |
85aaf69f SL |
227 | #[stable(feature = "rust1", since = "1.0.0")] |
228 | pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned { | |
229 | match *self { | |
230 | Borrowed(borrowed) => { | |
231 | *self = Owned(borrowed.to_owned()); | |
c30ab7b3 SL |
232 | match *self { |
233 | Borrowed(..) => unreachable!(), | |
234 | Owned(ref mut owned) => owned, | |
235 | } | |
85aaf69f | 236 | } |
92a42be0 | 237 | Owned(ref mut owned) => owned, |
85aaf69f SL |
238 | } |
239 | } | |
240 | ||
9346a6ac | 241 | /// Extracts the owned data. |
85aaf69f | 242 | /// |
c1a9b12d | 243 | /// Clones the data if it is not already owned. |
c34b1796 AL |
244 | /// |
245 | /// # Examples | |
246 | /// | |
7cac9316 XL |
247 | /// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data |
248 | /// and becomes a `Cow::Owned`: | |
249 | /// | |
c34b1796 AL |
250 | /// ``` |
251 | /// use std::borrow::Cow; | |
252 | /// | |
7cac9316 XL |
253 | /// let s = "Hello world!"; |
254 | /// let cow = Cow::Borrowed(s); | |
255 | /// | |
256 | /// assert_eq!( | |
257 | /// cow.into_owned(), | |
abe05a73 | 258 | /// String::from(s) |
7cac9316 XL |
259 | /// ); |
260 | /// ``` | |
261 | /// | |
262 | /// Calling `into_owned` on a `Cow::Owned` is a no-op: | |
263 | /// | |
264 | /// ``` | |
265 | /// use std::borrow::Cow; | |
c34b1796 | 266 | /// |
7cac9316 XL |
267 | /// let s = "Hello world!"; |
268 | /// let cow: Cow<str> = Cow::Owned(String::from(s)); | |
c34b1796 | 269 | /// |
7cac9316 XL |
270 | /// assert_eq!( |
271 | /// cow.into_owned(), | |
abe05a73 | 272 | /// String::from(s) |
7cac9316 | 273 | /// ); |
c34b1796 | 274 | /// ``` |
85aaf69f SL |
275 | #[stable(feature = "rust1", since = "1.0.0")] |
276 | pub fn into_owned(self) -> <B as ToOwned>::Owned { | |
277 | match self { | |
278 | Borrowed(borrowed) => borrowed.to_owned(), | |
92a42be0 | 279 | Owned(owned) => owned, |
85aaf69f SL |
280 | } |
281 | } | |
85aaf69f SL |
282 | } |
283 | ||
284 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 285 | impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> { |
85aaf69f SL |
286 | type Target = B; |
287 | ||
288 | fn deref(&self) -> &B { | |
289 | match *self { | |
290 | Borrowed(borrowed) => borrowed, | |
92a42be0 | 291 | Owned(ref owned) => owned.borrow(), |
85aaf69f SL |
292 | } |
293 | } | |
294 | } | |
295 | ||
296 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 297 | impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + ToOwned {} |
85aaf69f SL |
298 | |
299 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 300 | impl<B: ?Sized> Ord for Cow<'_, B> |
32a655c1 SL |
301 | where B: Ord + ToOwned |
302 | { | |
85aaf69f | 303 | #[inline] |
9fa01778 | 304 | fn cmp(&self, other: &Self) -> Ordering { |
85aaf69f SL |
305 | Ord::cmp(&**self, &**other) |
306 | } | |
307 | } | |
308 | ||
309 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
310 | impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> |
311 | where B: PartialEq<C> + ToOwned, | |
312 | C: ToOwned | |
85aaf69f SL |
313 | { |
314 | #[inline] | |
315 | fn eq(&self, other: &Cow<'b, C>) -> bool { | |
316 | PartialEq::eq(&**self, &**other) | |
317 | } | |
318 | } | |
319 | ||
320 | #[stable(feature = "rust1", since = "1.0.0")] | |
32a655c1 SL |
321 | impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> |
322 | where B: PartialOrd + ToOwned | |
323 | { | |
85aaf69f SL |
324 | #[inline] |
325 | fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> { | |
326 | PartialOrd::partial_cmp(&**self, &**other) | |
327 | } | |
328 | } | |
329 | ||
330 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 331 | impl<B: ?Sized> fmt::Debug for Cow<'_, B> |
416331ca XL |
332 | where |
333 | B: fmt::Debug + ToOwned<Owned: fmt::Debug>, | |
85aaf69f | 334 | { |
9fa01778 | 335 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
336 | match *self { |
337 | Borrowed(ref b) => fmt::Debug::fmt(b, f), | |
338 | Owned(ref o) => fmt::Debug::fmt(o, f), | |
339 | } | |
340 | } | |
341 | } | |
342 | ||
343 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 344 | impl<B: ?Sized> fmt::Display for Cow<'_, B> |
416331ca XL |
345 | where |
346 | B: fmt::Display + ToOwned<Owned: fmt::Display>, | |
85aaf69f | 347 | { |
9fa01778 | 348 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
349 | match *self { |
350 | Borrowed(ref b) => fmt::Display::fmt(b, f), | |
351 | Owned(ref o) => fmt::Display::fmt(o, f), | |
352 | } | |
353 | } | |
354 | } | |
355 | ||
3157f602 | 356 | #[stable(feature = "default", since = "1.11.0")] |
9fa01778 | 357 | impl<B: ?Sized> Default for Cow<'_, B> |
416331ca XL |
358 | where |
359 | B: ToOwned<Owned: Default>, | |
3157f602 | 360 | { |
9e0c209e | 361 | /// Creates an owned Cow<'a, B> with the default value for the contained owned value. |
9fa01778 | 362 | fn default() -> Self { |
3157f602 XL |
363 | Owned(<B as ToOwned>::Owned::default()) |
364 | } | |
365 | } | |
366 | ||
85aaf69f | 367 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 368 | impl<B: ?Sized> Hash for Cow<'_, B> |
32a655c1 SL |
369 | where B: Hash + ToOwned |
370 | { | |
85aaf69f SL |
371 | #[inline] |
372 | fn hash<H: Hasher>(&self, state: &mut H) { | |
373 | Hash::hash(&**self, state) | |
374 | } | |
375 | } | |
376 | ||
c34b1796 | 377 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 378 | impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T> { |
c34b1796 AL |
379 | fn as_ref(&self) -> &T { |
380 | self | |
381 | } | |
382 | } | |
c30ab7b3 SL |
383 | |
384 | #[stable(feature = "cow_add", since = "1.14.0")] | |
385 | impl<'a> Add<&'a str> for Cow<'a, str> { | |
386 | type Output = Cow<'a, str>; | |
387 | ||
388 | #[inline] | |
389 | fn add(mut self, rhs: &'a str) -> Self::Output { | |
390 | self += rhs; | |
391 | self | |
392 | } | |
393 | } | |
394 | ||
395 | #[stable(feature = "cow_add", since = "1.14.0")] | |
396 | impl<'a> Add<Cow<'a, str>> for Cow<'a, str> { | |
397 | type Output = Cow<'a, str>; | |
398 | ||
399 | #[inline] | |
400 | fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { | |
401 | self += rhs; | |
402 | self | |
403 | } | |
404 | } | |
405 | ||
406 | #[stable(feature = "cow_add", since = "1.14.0")] | |
407 | impl<'a> AddAssign<&'a str> for Cow<'a, str> { | |
408 | fn add_assign(&mut self, rhs: &'a str) { | |
409 | if self.is_empty() { | |
410 | *self = Cow::Borrowed(rhs) | |
411 | } else if rhs.is_empty() { | |
412 | return; | |
413 | } else { | |
414 | if let Cow::Borrowed(lhs) = *self { | |
415 | let mut s = String::with_capacity(lhs.len() + rhs.len()); | |
416 | s.push_str(lhs); | |
417 | *self = Cow::Owned(s); | |
418 | } | |
419 | self.to_mut().push_str(rhs); | |
420 | } | |
421 | } | |
422 | } | |
423 | ||
424 | #[stable(feature = "cow_add", since = "1.14.0")] | |
425 | impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> { | |
426 | fn add_assign(&mut self, rhs: Cow<'a, str>) { | |
427 | if self.is_empty() { | |
428 | *self = rhs | |
429 | } else if rhs.is_empty() { | |
430 | return; | |
431 | } else { | |
432 | if let Cow::Borrowed(lhs) = *self { | |
433 | let mut s = String::with_capacity(lhs.len() + rhs.len()); | |
434 | s.push_str(lhs); | |
435 | *self = Cow::Owned(s); | |
436 | } | |
437 | self.to_mut().push_str(&rhs); | |
438 | } | |
439 | } | |
440 | } |