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