]>
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) { |
60c5eb7d XL |
198 | match (self, source) { |
199 | (&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest), | |
200 | (t, s) => *t = s.clone(), | |
cc61c64b | 201 | } |
cc61c64b | 202 | } |
85aaf69f SL |
203 | } |
204 | ||
9fa01778 | 205 | impl<B: ?Sized + ToOwned> Cow<'_, B> { |
e74abb32 XL |
206 | /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. |
207 | /// | |
208 | /// # Examples | |
209 | /// | |
210 | /// ``` | |
211 | /// #![feature(cow_is_borrowed)] | |
212 | /// use std::borrow::Cow; | |
213 | /// | |
214 | /// let cow = Cow::Borrowed("moo"); | |
215 | /// assert!(cow.is_borrowed()); | |
216 | /// | |
217 | /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); | |
218 | /// assert!(!bull.is_borrowed()); | |
219 | /// ``` | |
220 | #[unstable(feature = "cow_is_borrowed", issue = "65143")] | |
221 | pub fn is_borrowed(&self) -> bool { | |
222 | match *self { | |
223 | Borrowed(_) => true, | |
224 | Owned(_) => false, | |
225 | } | |
226 | } | |
227 | ||
228 | /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. | |
229 | /// | |
230 | /// # Examples | |
231 | /// | |
232 | /// ``` | |
233 | /// #![feature(cow_is_borrowed)] | |
234 | /// use std::borrow::Cow; | |
235 | /// | |
236 | /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); | |
237 | /// assert!(cow.is_owned()); | |
238 | /// | |
239 | /// let bull = Cow::Borrowed("...moo?"); | |
240 | /// assert!(!bull.is_owned()); | |
241 | /// ``` | |
242 | #[unstable(feature = "cow_is_borrowed", issue = "65143")] | |
243 | pub fn is_owned(&self) -> bool { | |
244 | !self.is_borrowed() | |
245 | } | |
246 | ||
9346a6ac | 247 | /// Acquires a mutable reference to the owned form of the data. |
85aaf69f | 248 | /// |
c1a9b12d | 249 | /// Clones the data if it is not already owned. |
c34b1796 AL |
250 | /// |
251 | /// # Examples | |
252 | /// | |
253 | /// ``` | |
254 | /// use std::borrow::Cow; | |
255 | /// | |
7cac9316 XL |
256 | /// let mut cow = Cow::Borrowed("foo"); |
257 | /// cow.to_mut().make_ascii_uppercase(); | |
c34b1796 | 258 | /// |
7cac9316 XL |
259 | /// assert_eq!( |
260 | /// cow, | |
261 | /// Cow::Owned(String::from("FOO")) as Cow<str> | |
262 | /// ); | |
c34b1796 | 263 | /// ``` |
85aaf69f SL |
264 | #[stable(feature = "rust1", since = "1.0.0")] |
265 | pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned { | |
266 | match *self { | |
267 | Borrowed(borrowed) => { | |
268 | *self = Owned(borrowed.to_owned()); | |
c30ab7b3 SL |
269 | match *self { |
270 | Borrowed(..) => unreachable!(), | |
271 | Owned(ref mut owned) => owned, | |
272 | } | |
85aaf69f | 273 | } |
92a42be0 | 274 | Owned(ref mut owned) => owned, |
85aaf69f SL |
275 | } |
276 | } | |
277 | ||
9346a6ac | 278 | /// Extracts the owned data. |
85aaf69f | 279 | /// |
c1a9b12d | 280 | /// Clones the data if it is not already owned. |
c34b1796 AL |
281 | /// |
282 | /// # Examples | |
283 | /// | |
7cac9316 XL |
284 | /// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data |
285 | /// and becomes a `Cow::Owned`: | |
286 | /// | |
c34b1796 AL |
287 | /// ``` |
288 | /// use std::borrow::Cow; | |
289 | /// | |
7cac9316 XL |
290 | /// let s = "Hello world!"; |
291 | /// let cow = Cow::Borrowed(s); | |
292 | /// | |
293 | /// assert_eq!( | |
294 | /// cow.into_owned(), | |
abe05a73 | 295 | /// String::from(s) |
7cac9316 XL |
296 | /// ); |
297 | /// ``` | |
298 | /// | |
299 | /// Calling `into_owned` on a `Cow::Owned` is a no-op: | |
300 | /// | |
301 | /// ``` | |
302 | /// use std::borrow::Cow; | |
c34b1796 | 303 | /// |
7cac9316 XL |
304 | /// let s = "Hello world!"; |
305 | /// let cow: Cow<str> = Cow::Owned(String::from(s)); | |
c34b1796 | 306 | /// |
7cac9316 XL |
307 | /// assert_eq!( |
308 | /// cow.into_owned(), | |
abe05a73 | 309 | /// String::from(s) |
7cac9316 | 310 | /// ); |
c34b1796 | 311 | /// ``` |
85aaf69f SL |
312 | #[stable(feature = "rust1", since = "1.0.0")] |
313 | pub fn into_owned(self) -> <B as ToOwned>::Owned { | |
314 | match self { | |
315 | Borrowed(borrowed) => borrowed.to_owned(), | |
92a42be0 | 316 | Owned(owned) => owned, |
85aaf69f SL |
317 | } |
318 | } | |
85aaf69f SL |
319 | } |
320 | ||
321 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 322 | impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> { |
85aaf69f SL |
323 | type Target = B; |
324 | ||
325 | fn deref(&self) -> &B { | |
326 | match *self { | |
327 | Borrowed(borrowed) => borrowed, | |
92a42be0 | 328 | Owned(ref owned) => owned.borrow(), |
85aaf69f SL |
329 | } |
330 | } | |
331 | } | |
332 | ||
333 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 334 | impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + ToOwned {} |
85aaf69f SL |
335 | |
336 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 337 | impl<B: ?Sized> Ord for Cow<'_, B> |
32a655c1 SL |
338 | where B: Ord + ToOwned |
339 | { | |
85aaf69f | 340 | #[inline] |
9fa01778 | 341 | fn cmp(&self, other: &Self) -> Ordering { |
85aaf69f SL |
342 | Ord::cmp(&**self, &**other) |
343 | } | |
344 | } | |
345 | ||
346 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
347 | impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> |
348 | where B: PartialEq<C> + ToOwned, | |
349 | C: ToOwned | |
85aaf69f SL |
350 | { |
351 | #[inline] | |
352 | fn eq(&self, other: &Cow<'b, C>) -> bool { | |
353 | PartialEq::eq(&**self, &**other) | |
354 | } | |
355 | } | |
356 | ||
357 | #[stable(feature = "rust1", since = "1.0.0")] | |
32a655c1 SL |
358 | impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> |
359 | where B: PartialOrd + ToOwned | |
360 | { | |
85aaf69f SL |
361 | #[inline] |
362 | fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> { | |
363 | PartialOrd::partial_cmp(&**self, &**other) | |
364 | } | |
365 | } | |
366 | ||
367 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 368 | impl<B: ?Sized> fmt::Debug for Cow<'_, B> |
416331ca XL |
369 | where |
370 | B: fmt::Debug + ToOwned<Owned: fmt::Debug>, | |
85aaf69f | 371 | { |
9fa01778 | 372 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
373 | match *self { |
374 | Borrowed(ref b) => fmt::Debug::fmt(b, f), | |
375 | Owned(ref o) => fmt::Debug::fmt(o, f), | |
376 | } | |
377 | } | |
378 | } | |
379 | ||
380 | #[stable(feature = "rust1", since = "1.0.0")] | |
9fa01778 | 381 | impl<B: ?Sized> fmt::Display for Cow<'_, B> |
416331ca XL |
382 | where |
383 | B: fmt::Display + ToOwned<Owned: fmt::Display>, | |
85aaf69f | 384 | { |
9fa01778 | 385 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
386 | match *self { |
387 | Borrowed(ref b) => fmt::Display::fmt(b, f), | |
388 | Owned(ref o) => fmt::Display::fmt(o, f), | |
389 | } | |
390 | } | |
391 | } | |
392 | ||
3157f602 | 393 | #[stable(feature = "default", since = "1.11.0")] |
9fa01778 | 394 | impl<B: ?Sized> Default for Cow<'_, B> |
416331ca XL |
395 | where |
396 | B: ToOwned<Owned: Default>, | |
3157f602 | 397 | { |
9e0c209e | 398 | /// Creates an owned Cow<'a, B> with the default value for the contained owned value. |
9fa01778 | 399 | fn default() -> Self { |
3157f602 XL |
400 | Owned(<B as ToOwned>::Owned::default()) |
401 | } | |
402 | } | |
403 | ||
85aaf69f | 404 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 405 | impl<B: ?Sized> Hash for Cow<'_, B> |
32a655c1 SL |
406 | where B: Hash + ToOwned |
407 | { | |
85aaf69f SL |
408 | #[inline] |
409 | fn hash<H: Hasher>(&self, state: &mut H) { | |
410 | Hash::hash(&**self, state) | |
411 | } | |
412 | } | |
413 | ||
c34b1796 | 414 | #[stable(feature = "rust1", since = "1.0.0")] |
9fa01778 | 415 | impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T> { |
c34b1796 AL |
416 | fn as_ref(&self) -> &T { |
417 | self | |
418 | } | |
419 | } | |
c30ab7b3 SL |
420 | |
421 | #[stable(feature = "cow_add", since = "1.14.0")] | |
422 | impl<'a> Add<&'a str> for Cow<'a, str> { | |
423 | type Output = Cow<'a, str>; | |
424 | ||
425 | #[inline] | |
426 | fn add(mut self, rhs: &'a str) -> Self::Output { | |
427 | self += rhs; | |
428 | self | |
429 | } | |
430 | } | |
431 | ||
432 | #[stable(feature = "cow_add", since = "1.14.0")] | |
433 | impl<'a> Add<Cow<'a, str>> for Cow<'a, str> { | |
434 | type Output = Cow<'a, str>; | |
435 | ||
436 | #[inline] | |
437 | fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { | |
438 | self += rhs; | |
439 | self | |
440 | } | |
441 | } | |
442 | ||
443 | #[stable(feature = "cow_add", since = "1.14.0")] | |
444 | impl<'a> AddAssign<&'a str> for Cow<'a, str> { | |
445 | fn add_assign(&mut self, rhs: &'a str) { | |
446 | if self.is_empty() { | |
447 | *self = Cow::Borrowed(rhs) | |
60c5eb7d | 448 | } else if !rhs.is_empty() { |
c30ab7b3 SL |
449 | if let Cow::Borrowed(lhs) = *self { |
450 | let mut s = String::with_capacity(lhs.len() + rhs.len()); | |
451 | s.push_str(lhs); | |
452 | *self = Cow::Owned(s); | |
453 | } | |
454 | self.to_mut().push_str(rhs); | |
455 | } | |
456 | } | |
457 | } | |
458 | ||
459 | #[stable(feature = "cow_add", since = "1.14.0")] | |
460 | impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> { | |
461 | fn add_assign(&mut self, rhs: Cow<'a, str>) { | |
462 | if self.is_empty() { | |
463 | *self = rhs | |
60c5eb7d | 464 | } else if !rhs.is_empty() { |
c30ab7b3 SL |
465 | if let Cow::Borrowed(lhs) = *self { |
466 | let mut s = String::with_capacity(lhs.len() + rhs.len()); | |
467 | s.push_str(lhs); | |
468 | *self = Cow::Owned(s); | |
469 | } | |
470 | self.to_mut().push_str(&rhs); | |
471 | } | |
472 | } | |
473 | } |