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}