1#![cfg_attr(feature = "const_fn", feature(const_fn_trait_bound))]
39#![warn(missing_docs)]
40#![cfg_attr(not(test), no_std)]
41extern crate alloc;
42
43mod traits;
44mod wide;
45
46#[cfg(feature = "impl_serde")]
47mod serde;
48
49pub mod generic;
50#[cfg(target_pointer_width = "64")]
51pub mod lean;
52
53#[cfg(not(target_pointer_width = "64"))]
54pub mod lean {
55 pub use super::wide::Cow;
57}
58
59pub use wide::Cow;
60
61#[rustfmt::skip]
62macro_rules! test { ($tmod:ident => $cow:path) => {
63 #[cfg(test)]
64 mod $tmod {
65 use $cow;
66
67 #[test]
68 fn borrowed_str() {
69 let s = "Hello World";
70 let c = Cow::borrowed(s);
71
72 assert_eq!(s, c);
73 assert_eq!(s, c.as_ref());
74 assert_eq!(s, &*c);
75 }
76
77 #[test]
78 fn owned_string() {
79 let s = String::from("Hello World");
80 let c: Cow<str> = Cow::owned(s.clone());
81
82 assert_eq!(s, c);
83 }
84
85 #[test]
86 fn into_owned() {
87 let hello = "Hello World";
88 let borrowed = Cow::borrowed(hello);
89 let owned: Cow<str> = Cow::owned(String::from(hello));
90
91 assert_eq!(borrowed.into_owned(), hello);
92 assert_eq!(owned.into_owned(), hello);
93 }
94
95 #[test]
96 fn borrowed_slice() {
97 let s: &[_] = &[1, 2, 42];
98 let c = Cow::borrowed(s);
99
100 assert_eq!(s, c);
101 assert_eq!(s, c.as_ref());
102 assert_eq!(s, &*c);
103 }
104
105 #[test]
106 fn owned_slice() {
107 let s = vec![1, 2, 42];
108 let c: Cow<[_]> = Cow::owned(s.clone());
109
110 assert_eq!(s, c);
111 }
112
113 #[test]
114 fn into_owned_vec() {
115 let hello: &[u8] = b"Hello World";
116 let borrowed = Cow::borrowed(hello);
117 let owned: Cow<[u8]> = Cow::owned(hello.to_vec());
118
119 assert_eq!(borrowed.into_owned(), hello);
120 assert_eq!(owned.into_owned(), hello);
121 }
122
123 #[test]
124 fn hash() {
125 use std::collections::hash_map::DefaultHasher;
126 use std::hash::{Hash, Hasher};
127
128 let slice = "Hello World!";
129 let borrowed = Cow::borrowed(slice);
130 let owned: Cow<str> = Cow::owned(slice.to_owned());
131
132 let hash1 = {
133 let mut hasher = DefaultHasher::default();
134
135 slice.hash(&mut hasher);
136
137 hasher.finish()
138 };
139
140 let hash2 = {
141 let mut hasher = DefaultHasher::default();
142
143 borrowed.hash(&mut hasher);
144
145 hasher.finish()
146 };
147
148 let hash3 = {
149 let mut hasher = DefaultHasher::default();
150
151 owned.hash(&mut hasher);
152
153 hasher.finish()
154 };
155
156 assert_eq!(hash1, hash2);
157 assert_eq!(hash1, hash3);
158 assert_eq!(hash2, hash3);
159 }
160
161 #[test]
162 fn ord_and_partial_ord() {
163 use std::cmp::Ordering;
164
165 macro_rules! generate_order_tests {
166 ( $f:tt => $order:expr => $left:expr, $right:expr ) => {
167 assert_eq!(
168 Cow::<str>::borrowed($left).$f(&Cow::<str>::borrowed($right)),
169 $order
170 );
171
172 assert_eq!(
173 Cow::<str>::owned($left.to_owned())
174 .$f(&Cow::<str>::borrowed($right)),
175 $order
176 );
177
178 assert_eq!(
179 Cow::<str>::borrowed($left)
180 .$f(&Cow::<str>::owned($right.to_owned())),
181 $order
182 );
183
184 assert_eq!(
185 Cow::<str>::owned($left.to_owned())
186 .$f(&Cow::<str>::owned($right.to_owned())),
187 $order
188 );
189 }
190 }
191
192 generate_order_tests!(partial_cmp => Some(Ordering::Equal) => "a", "a");
193 generate_order_tests!(partial_cmp => Some(Ordering::Less) => "a", "b");
194 generate_order_tests!(partial_cmp => Some(Ordering::Greater) => "b", "a");
195
196 generate_order_tests!(cmp => Ordering::Equal => "a", "a");
197 generate_order_tests!(cmp => Ordering::Less => "a", "b");
198 generate_order_tests!(cmp => Ordering::Greater => "b", "a");
199 }
200
201 #[test]
202 fn from_std_cow() {
203 let std = std::borrow::Cow::Borrowed("Hello World");
204 let beef = Cow::from(std.clone());
205
206 assert_eq!(&*std, &*beef);
207 }
208
209 #[test]
210 fn unwrap_borrowed() {
211 let borrowed = Cow::borrowed("Hello");
212
213 assert_eq!(borrowed.unwrap_borrowed(), "Hello");
214 }
215
216 #[test]
217 #[should_panic]
218 fn unwrap_owned() {
219 let borrowed: Cow<str> = Cow::owned("Hello".to_string());
220
221 borrowed.unwrap_borrowed();
222 }
223
224 #[test]
225 fn stress_test_owned() {
226 let mut expected = String::from("Hello... ");
227 let mut cow: Cow<str> = Cow::borrowed("Hello... ");
228
229 #[cfg(not(miri))]
230 let iterations = 1024;
231 #[cfg(miri)]
232 let iterations = 10;
233
234 for i in 0..iterations {
235 if i % 3 == 0 {
236 let old = cow;
237 cow = old.clone();
238
239 std::mem::drop(old);
240 }
241
242 let mut owned = cow.into_owned();
243
244 expected.push_str("Hello?.. ");
245 owned.push_str("Hello?.. ");
246
247 cow = owned.into();
248 }
249
250 assert_eq!(expected, cow.into_owned());
251 }
252
253 #[test]
254 fn const_fn_str() {
255 const HELLO: Cow<str> = Cow::const_str("Hello");
256
257 assert_eq!(&*HELLO, "Hello");
258 }
259
260 #[test]
261 #[cfg(feature = "const_fn")]
262 fn const_fn_slice() {
263 const FOO: Cow<[u8]> = Cow::const_slice(b"bar");
264
265 assert_eq!(&*FOO, b"bar");
266 }
267
268 #[test]
269 fn default_str() {
270 let empty: Cow<str> = Default::default();
271
272 assert_eq!(&*empty, "");
273 }
274
275 #[test]
276 fn default_slice() {
277 let empty: Cow<[u8]> = Default::default();
278
279 assert_eq!(&*empty, b"");
280 }
281 }
282} }
283
284test!(test_wide => crate::wide::Cow);
285test!(test_lean => crate::lean::Cow);