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