dairy/lib.rs
1//! A more compact, user friendly clone-on-write smart pointer.
2//!
3//! ```
4//! use dairy::Cow;
5//! let borrowed: Cow<str> = Cow::borrowed("Hello World!");
6//! let owned: Cow<str> = Cow::owned(String::from("Hello World!"));
7//! ```
8//!
9//! [`dairy::Cow`][Cow] is an improved version of the standard library
10//! [`std::borrow::Cow`]. Depending on the platform and type this crate provides
11//! a better underlying implementation which will be more compact. This crate
12//! currently supports the following types: [`str`], [`[T]`][slice], [`CStr`],
13//! [`OsStr`], and [`Path`].
14//!
15//! [`dairy::Cow`][Cow] is also able to provide many more [`From`]
16//! implementations; some which are not possible for the standard library to
17//! provide due to the `alloc`, `std` split. For example `Cow<Path>` now has
18//! the useful `From<&str>` implementation.
19//!
20//! ### Underlying implementation
21//!
22//! - On 64-bit platforms the *compact* implementation of [`Cow`] is two words
23//! wide, storing the length, capacity, and the ownership tag in the same
24//! word.
25//! - On 32-bit platforms the *compact* implementation of [`Cow`] is three words
26//! wide, storing the capacity and the ownership tag in the same word.
27//! - The **default** implementation simply uses the the standard library
28//! implementation which is four words wide. This is typically required in
29//! cases where the standard library does not provide an `.into_raw_parts()`
30//! or equivalent method for the owned version of types.
31//!
32//! The following table documents how `Cow<T>` is implemented for each type on
33//! depending on the platform.
34//!
35//! | `Cow<T>` | Unix/WASI | Other |
36//! | ------------ | --------- | -------------- |
37//! | `Cow<str>` | *compact* | *compact* |
38//! | `Cow<[T]>` | *compact* | *compact* |
39//! | `Cow<CStr>` | *compact* | *compact* |
40//! | `Cow<OsStr>` | *compact* | **default** |
41//! | `Cow<Path>` | *compact* | **default** |
42
43#![no_std]
44#![warn(unsafe_op_in_unsafe_fn)]
45
46extern crate alloc;
47
48#[cfg(feature = "std")]
49extern crate std;
50
51mod as_ref;
52mod cmp;
53mod extend;
54mod from;
55mod from_iter;
56mod from_str;
57mod imp;
58mod serde;
59mod to_boxed;
60
61use core::borrow::Borrow;
62use core::fmt;
63use core::hash::{Hash, Hasher};
64use core::marker::Unpin;
65use core::ops::Deref;
66
67use alloc::boxed::Box;
68
69#[cfg(feature = "std")]
70use std::{
71 ffi::{CStr, OsStr},
72 path::Path,
73};
74
75use crate::imp::Cow as _;
76pub use crate::imp::Dairy;
77pub use crate::to_boxed::ToBoxed;
78
79/// Convenient type alias for a clone-on-write [`str`].
80pub type String<'a> = Cow<'a, str>;
81
82/// Convenient type alias for a clone-on-write [`[T]`][slice].
83pub type Vec<'a, T> = Cow<'a, [T]>;
84
85/// Convenient type alias for a clone-on-write [`CStr`].
86#[cfg(feature = "std")]
87pub type CString<'a> = Cow<'a, CStr>;
88
89/// Convenient type alias for a clone-on-write [`OsStr`].
90#[cfg(feature = "std")]
91pub type OsString<'a> = Cow<'a, OsStr>;
92
93/// Convenient type alias for a clone-on-write [`Path`].
94#[cfg(feature = "std")]
95pub type PathBuf<'a> = Cow<'a, Path>;
96
97/// A clone-on-write smart pointer.
98///
99/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
100/// can enclose and provide immutable access to borrowed data, and clone the
101/// data lazily when mutation or ownership is required.
102///
103/// `Cow` implements [`Deref`], which means that you can call non-mutating
104/// methods directly on the data it encloses.
105pub struct Cow<'a, T>
106where
107 T: ?Sized + Dairy<'a>,
108{
109 inner: T::Cow,
110}
111
112impl<'a, T> Cow<'a, T>
113where
114 T: ?Sized + Dairy<'a>,
115{
116 /// Construct from borrowed data.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use dairy::Cow;
122 /// let cow: Cow<str> = Cow::borrowed("moo");
123 /// ```
124 #[inline]
125 pub fn borrowed(b: &'a T) -> Self {
126 Self {
127 inner: T::Cow::borrowed(b),
128 }
129 }
130
131 /// Construct from owned data.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use dairy::Cow;
137 /// let cow: Cow<str> = Cow::owned(String::from("moo"));
138 /// ```
139 #[inline]
140 pub fn owned(o: T::Owned) -> Self {
141 Self {
142 inner: T::Cow::owned(o),
143 }
144 }
145
146 /// Returns true if the data is borrowed.
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use dairy::Cow;
152 ///
153 /// let cow: Cow<str> = Cow::borrowed("moo");
154 /// assert!(cow.is_borrowed());
155 ///
156 /// let cow: Cow<str> = Cow::owned(String::from("...moo?"));
157 /// assert!(!cow.is_borrowed());
158 /// ```
159 #[inline]
160 pub fn is_borrowed(&self) -> bool {
161 self.inner.is_borrowed()
162 }
163
164 /// Returns true if the data is owned.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use dairy::Cow;
170 ///
171 /// let cow: Cow<str> = Cow::owned(String::from("moo"));
172 /// assert!(cow.is_owned());
173 ///
174 /// let cow: Cow<str> = Cow::borrowed("...moo?");
175 /// assert!(!cow.is_owned());
176 /// ```
177 #[inline]
178 pub fn is_owned(&self) -> bool {
179 self.inner.is_owned()
180 }
181
182 #[inline]
183 fn make_ref(&self) -> &T {
184 self.inner.make_ref()
185 }
186
187 /// Converts into owned data.
188 ///
189 /// Clones the data if it is not already owned.
190 ///
191 /// # Examples
192 ///
193 /// Calling `.into_owned()` on a borrowed `Cow` clones the underlying data.
194 ///
195 /// ```
196 /// use dairy::Cow;
197 ///
198 /// let cow = Cow::borrowed("Moo!");
199 /// assert_eq!(cow.into_owned(), String::from("Moo!"));
200 /// ```
201 ///
202 /// Calling `.into_owned()` on an owned `Cow` is a noop.
203 ///
204 /// ```
205 /// use dairy::Cow;
206 ///
207 /// let cow: Cow<str> = Cow::owned(String::from("Moo!"));
208 /// assert_eq!(cow.into_owned(), String::from("Moo!"));
209 /// ```
210 #[inline]
211 pub fn into_owned(self) -> T::Owned {
212 self.inner.into_owned()
213 }
214
215 /// Converts into boxed data.
216 ///
217 /// Clones the data if it is not already owned.
218 ///
219 /// # Examples
220 ///
221 /// Calling `.into_boxed()` on a borrowed `Cow` clones the underlying data.
222 ///
223 /// ```
224 /// use dairy::Cow;
225 ///
226 /// let cow = Cow::borrowed("Moo!");
227 /// assert_eq!(cow.into_boxed(), String::from("Moo!").into_boxed_str());
228 /// ```
229 ///
230 /// Calling `.into_boxed()` on an owned `Cow` is a noop.
231 ///
232 /// ```
233 /// use dairy::Cow;
234 ///
235 /// let cow: Cow<str> = Cow::owned(String::from("Moo!"));
236 /// assert_eq!(cow.into_boxed(), String::from("Moo!").into_boxed_str());
237 /// ```
238 #[inline]
239 pub fn into_boxed(self) -> Box<T>
240 where
241 T: ToBoxed,
242 {
243 T::to_boxed(self.into_owned())
244 }
245
246 /// Applies the given function to the owned data.
247 ///
248 /// Clones the data if it is not already owned. This is useful because the
249 /// compact implementation is not able to provide a `.to_mut()` method like
250 /// the standard library. This function allows you to modify the `Cow`
251 /// without [moving] it.
252 ///
253 /// # Examples
254 ///
255 /// ```
256 /// use dairy::Cow;
257 ///
258 /// let mut cow = Cow::borrowed("Moo!");
259 /// cow.apply(|s| s.make_ascii_uppercase());
260 /// assert_eq!(cow, "MOO!");
261 /// ```
262 ///
263 /// [moving]: https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html?#ways-variables-and-data-interact-move
264 #[inline]
265 pub fn apply<F>(&mut self, f: F)
266 where
267 F: FnOnce(&mut T::Owned),
268 {
269 self.inner.apply(f)
270 }
271}
272
273impl<'a, T> Deref for Cow<'a, T>
274where
275 T: ?Sized + Dairy<'a>,
276{
277 type Target = T;
278
279 #[inline]
280 fn deref(&self) -> &T {
281 self.make_ref()
282 }
283}
284
285impl<'a, T> Borrow<T> for Cow<'a, T>
286where
287 T: ?Sized + Dairy<'a>,
288{
289 #[inline]
290 fn borrow(&self) -> &T {
291 self.make_ref()
292 }
293}
294
295impl<'a, T> Clone for Cow<'a, T>
296where
297 T: ?Sized + Dairy<'a>,
298{
299 #[inline]
300 fn clone(&self) -> Self {
301 Self {
302 inner: self.inner.clone(),
303 }
304 }
305}
306
307impl<'a, T> fmt::Debug for Cow<'a, T>
308where
309 T: ?Sized + Dairy<'a> + fmt::Debug,
310 T::Owned: fmt::Debug,
311{
312 #[inline]
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 fmt::Debug::fmt(&**self, f)
315 }
316}
317
318impl<'a, T> fmt::Display for Cow<'a, T>
319where
320 T: ?Sized + Dairy<'a> + fmt::Display,
321 T::Owned: fmt::Display,
322{
323 #[inline]
324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325 fmt::Display::fmt(&**self, f)
326 }
327}
328
329impl<'a, T> Default for Cow<'a, T>
330where
331 T: ?Sized + Dairy<'a>,
332 T::Owned: Default,
333{
334 #[inline]
335 fn default() -> Self {
336 Self::owned(T::Owned::default())
337 }
338}
339
340impl<'a, T> Hash for Cow<'a, T>
341where
342 T: ?Sized + Dairy<'a> + Hash,
343{
344 #[inline]
345 fn hash<H: Hasher>(&self, state: &mut H) {
346 Hash::hash(&**self, state)
347 }
348}
349
350unsafe impl<'a, T> Send for Cow<'a, T>
351where
352 T: ?Sized + Dairy<'a> + Sync,
353 T::Owned: Send,
354{
355}
356
357unsafe impl<'a, T> Sync for Cow<'a, T>
358where
359 T: ?Sized + Dairy<'a> + Sync,
360 T::Owned: Sync,
361{
362}
363
364impl<'a, T> Unpin for Cow<'a, T>
365where
366 T: ?Sized + Dairy<'a>,
367 T::Owned: Unpin,
368{
369}