]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! A module for working with borrowed data. | |
12 | ||
13 | #![stable(feature = "rust1", since = "1.0.0")] | |
14 | ||
9e0c209e | 15 | use core::cmp::Ordering; |
85aaf69f | 16 | use core::hash::{Hash, Hasher}; |
85aaf69f | 17 | use core::ops::Deref; |
85aaf69f SL |
18 | |
19 | use fmt; | |
85aaf69f SL |
20 | |
21 | use self::Cow::*; | |
22 | ||
92a42be0 | 23 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e | 24 | pub use core::borrow::{Borrow, BorrowMut}; |
85aaf69f SL |
25 | |
26 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
27 | impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> |
28 | where B: ToOwned, | |
29 | <B as ToOwned>::Owned: 'a | |
30 | { | |
85aaf69f SL |
31 | fn borrow(&self) -> &B { |
32 | &**self | |
33 | } | |
34 | } | |
35 | ||
9346a6ac | 36 | /// A generalization of `Clone` to borrowed data. |
85aaf69f SL |
37 | /// |
38 | /// Some types make it possible to go from borrowed to owned, usually by | |
39 | /// implementing the `Clone` trait. But `Clone` works only for going from `&T` | |
40 | /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data | |
41 | /// from any borrow of a given type. | |
42 | #[stable(feature = "rust1", since = "1.0.0")] | |
43 | pub trait ToOwned { | |
44 | #[stable(feature = "rust1", since = "1.0.0")] | |
45 | type Owned: Borrow<Self>; | |
46 | ||
9346a6ac | 47 | /// Creates owned data from borrowed data, usually by cloning. |
54a0048b SL |
48 | /// |
49 | /// # Examples | |
50 | /// | |
51 | /// Basic usage: | |
52 | /// | |
53 | /// ``` | |
54 | /// let s = "a"; // &str | |
55 | /// let ss = s.to_owned(); // String | |
56 | /// | |
57 | /// let v = &[1, 2]; // slice | |
58 | /// let vv = v.to_owned(); // Vec | |
59 | /// ``` | |
85aaf69f SL |
60 | #[stable(feature = "rust1", since = "1.0.0")] |
61 | fn to_owned(&self) -> Self::Owned; | |
62 | } | |
63 | ||
64 | #[stable(feature = "rust1", since = "1.0.0")] | |
65 | impl<T> ToOwned for T where T: Clone { | |
66 | type Owned = T; | |
92a42be0 SL |
67 | fn to_owned(&self) -> T { |
68 | self.clone() | |
69 | } | |
85aaf69f SL |
70 | } |
71 | ||
72 | /// A clone-on-write smart pointer. | |
73 | /// | |
74 | /// The type `Cow` is a smart pointer providing clone-on-write functionality: it | |
75 | /// can enclose and provide immutable access to borrowed data, and clone the | |
76 | /// data lazily when mutation or ownership is required. The type is designed to | |
77 | /// work with general borrowed data via the `Borrow` trait. | |
78 | /// | |
9346a6ac | 79 | /// `Cow` implements `Deref`, which means that you can call |
85aaf69f | 80 | /// non-mutating methods directly on the data it encloses. If mutation |
9346a6ac | 81 | /// is desired, `to_mut` will obtain a mutable reference to an owned |
85aaf69f SL |
82 | /// value, cloning if necessary. |
83 | /// | |
c34b1796 | 84 | /// # Examples |
85aaf69f | 85 | /// |
c34b1796 | 86 | /// ``` |
85aaf69f SL |
87 | /// use std::borrow::Cow; |
88 | /// | |
92a42be0 | 89 | /// # #[allow(dead_code)] |
c34b1796 | 90 | /// fn abs_all(input: &mut Cow<[i32]>) { |
85aaf69f SL |
91 | /// for i in 0..input.len() { |
92 | /// let v = input[i]; | |
93 | /// if v < 0 { | |
94 | /// // clones into a vector the first time (if not already owned) | |
95 | /// input.to_mut()[i] = -v; | |
96 | /// } | |
97 | /// } | |
98 | /// } | |
99 | /// ``` | |
100 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
101 | pub enum Cow<'a, B: ?Sized + 'a> |
102 | where B: ToOwned | |
103 | { | |
85aaf69f SL |
104 | /// Borrowed data. |
105 | #[stable(feature = "rust1", since = "1.0.0")] | |
7453a54e | 106 | Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B), |
85aaf69f SL |
107 | |
108 | /// Owned data. | |
109 | #[stable(feature = "rust1", since = "1.0.0")] | |
9cc50fc6 | 110 | Owned( |
7453a54e | 111 | #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned |
9cc50fc6 | 112 | ), |
85aaf69f SL |
113 | } |
114 | ||
115 | #[stable(feature = "rust1", since = "1.0.0")] | |
116 | impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { | |
117 | fn clone(&self) -> Cow<'a, B> { | |
118 | match *self { | |
119 | Borrowed(b) => Borrowed(b), | |
120 | Owned(ref o) => { | |
121 | let b: &B = o.borrow(); | |
122 | Owned(b.to_owned()) | |
92a42be0 | 123 | } |
85aaf69f SL |
124 | } |
125 | } | |
126 | } | |
127 | ||
128 | impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { | |
9346a6ac | 129 | /// Acquires a mutable reference to the owned form of the data. |
85aaf69f | 130 | /// |
c1a9b12d | 131 | /// Clones the data if it is not already owned. |
c34b1796 AL |
132 | /// |
133 | /// # Examples | |
134 | /// | |
135 | /// ``` | |
136 | /// use std::borrow::Cow; | |
137 | /// | |
138 | /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); | |
139 | /// | |
140 | /// let hello = cow.to_mut(); | |
141 | /// | |
142 | /// assert_eq!(hello, &[1, 2, 3]); | |
143 | /// ``` | |
85aaf69f SL |
144 | #[stable(feature = "rust1", since = "1.0.0")] |
145 | pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned { | |
146 | match *self { | |
147 | Borrowed(borrowed) => { | |
148 | *self = Owned(borrowed.to_owned()); | |
149 | self.to_mut() | |
150 | } | |
92a42be0 | 151 | Owned(ref mut owned) => owned, |
85aaf69f SL |
152 | } |
153 | } | |
154 | ||
9346a6ac | 155 | /// Extracts the owned data. |
85aaf69f | 156 | /// |
c1a9b12d | 157 | /// Clones the data if it is not already owned. |
c34b1796 AL |
158 | /// |
159 | /// # Examples | |
160 | /// | |
161 | /// ``` | |
162 | /// use std::borrow::Cow; | |
163 | /// | |
164 | /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); | |
165 | /// | |
166 | /// let hello = cow.into_owned(); | |
167 | /// | |
168 | /// assert_eq!(vec![1, 2, 3], hello); | |
169 | /// ``` | |
85aaf69f SL |
170 | #[stable(feature = "rust1", since = "1.0.0")] |
171 | pub fn into_owned(self) -> <B as ToOwned>::Owned { | |
172 | match self { | |
173 | Borrowed(borrowed) => borrowed.to_owned(), | |
92a42be0 | 174 | Owned(owned) => owned, |
85aaf69f SL |
175 | } |
176 | } | |
85aaf69f SL |
177 | } |
178 | ||
179 | #[stable(feature = "rust1", since = "1.0.0")] | |
180 | impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned { | |
181 | type Target = B; | |
182 | ||
183 | fn deref(&self) -> &B { | |
184 | match *self { | |
185 | Borrowed(borrowed) => borrowed, | |
92a42be0 | 186 | Owned(ref owned) => owned.borrow(), |
85aaf69f SL |
187 | } |
188 | } | |
189 | } | |
190 | ||
191 | #[stable(feature = "rust1", since = "1.0.0")] | |
192 | impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {} | |
193 | ||
194 | #[stable(feature = "rust1", since = "1.0.0")] | |
195 | impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned { | |
196 | #[inline] | |
197 | fn cmp(&self, other: &Cow<'a, B>) -> Ordering { | |
198 | Ord::cmp(&**self, &**other) | |
199 | } | |
200 | } | |
201 | ||
202 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
203 | impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> |
204 | where B: PartialEq<C> + ToOwned, | |
205 | C: ToOwned | |
85aaf69f SL |
206 | { |
207 | #[inline] | |
208 | fn eq(&self, other: &Cow<'b, C>) -> bool { | |
209 | PartialEq::eq(&**self, &**other) | |
210 | } | |
211 | } | |
212 | ||
213 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 | 214 | impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned { |
85aaf69f SL |
215 | #[inline] |
216 | fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> { | |
217 | PartialOrd::partial_cmp(&**self, &**other) | |
218 | } | |
219 | } | |
220 | ||
221 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
222 | impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> |
223 | where B: fmt::Debug + ToOwned, | |
224 | <B as ToOwned>::Owned: fmt::Debug | |
85aaf69f SL |
225 | { |
226 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
227 | match *self { | |
228 | Borrowed(ref b) => fmt::Debug::fmt(b, f), | |
229 | Owned(ref o) => fmt::Debug::fmt(o, f), | |
230 | } | |
231 | } | |
232 | } | |
233 | ||
234 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 SL |
235 | impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> |
236 | where B: fmt::Display + ToOwned, | |
237 | <B as ToOwned>::Owned: fmt::Display | |
85aaf69f SL |
238 | { |
239 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
240 | match *self { | |
241 | Borrowed(ref b) => fmt::Display::fmt(b, f), | |
242 | Owned(ref o) => fmt::Display::fmt(o, f), | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
3157f602 XL |
247 | #[stable(feature = "default", since = "1.11.0")] |
248 | impl<'a, B: ?Sized> Default for Cow<'a, B> | |
249 | where B: ToOwned, | |
250 | <B as ToOwned>::Owned: Default | |
251 | { | |
9e0c209e | 252 | /// Creates an owned Cow<'a, B> with the default value for the contained owned value. |
3157f602 XL |
253 | fn default() -> Cow<'a, B> { |
254 | Owned(<B as ToOwned>::Owned::default()) | |
255 | } | |
256 | } | |
257 | ||
85aaf69f | 258 | #[stable(feature = "rust1", since = "1.0.0")] |
92a42be0 | 259 | impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned { |
85aaf69f SL |
260 | #[inline] |
261 | fn hash<H: Hasher>(&self, state: &mut H) { | |
262 | Hash::hash(&**self, state) | |
263 | } | |
264 | } | |
265 | ||
c34b1796 | 266 | #[stable(feature = "rust1", since = "1.0.0")] |
9cc50fc6 | 267 | #[allow(deprecated)] |
9346a6ac | 268 | impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> { |
c34b1796 AL |
269 | fn as_ref(&self) -> &T { |
270 | self | |
271 | } | |
272 | } |