rune_alloc/borrow/
mod.rs

1//! A module for working with borrowed data.
2
3use core::borrow::Borrow;
4use core::cmp::Ordering;
5use core::fmt;
6use core::hash::{Hash, Hasher};
7use core::ops::Deref;
8
9#[cfg(feature = "alloc")]
10use rust_alloc::borrow::ToOwned;
11
12use crate::clone::TryClone;
13use crate::error::Error;
14use crate::vec::Vec;
15
16/// A generalization of `TryClone` to borrowed data.
17///
18/// Some types make it possible to go from borrowed to owned, usually by
19/// implementing the `TryClone` trait. But `TryClone` works only for going from
20/// `&T` to `T`. The `ToOwned` trait generalizes `TryClone` to construct owned
21/// data from any borrow of a given type.
22pub trait TryToOwned {
23    /// The resulting type after obtaining ownership.
24    type Owned: Borrow<Self>;
25
26    /// Creates owned data from borrowed data, usually by cloning.
27    ///
28    /// # Examples
29    ///
30    /// Basic usage:
31    ///
32    /// ```
33    /// use rune::alloc::{Vec, String};
34    /// use rune::alloc::prelude::*;
35    ///
36    /// let s: &str = "a";
37    /// let ss: String = s.try_to_owned()?;
38    /// # let v: &[i32] = &[1, 2];
39    /// # let vv: Vec<i32> = v.try_to_owned()?;
40    /// # Ok::<_, rune::alloc::Error>(())
41    /// ```
42    fn try_to_owned(&self) -> Result<Self::Owned, Error>;
43}
44
45impl<T> TryToOwned for T
46where
47    T: TryClone,
48{
49    type Owned = T;
50
51    #[inline]
52    fn try_to_owned(&self) -> Result<T, Error> {
53        self.try_clone()
54    }
55}
56
57#[cfg(feature = "std")]
58impl TryToOwned for std::path::Path {
59    type Owned = std::path::PathBuf;
60
61    fn try_to_owned(&self) -> Result<Self::Owned, Error> {
62        Ok(self.to_path_buf())
63    }
64}
65
66/// A clone-on-write smart pointer.
67///
68/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
69/// can enclose and provide immutable access to borrowed data, and clone the
70/// data lazily when mutation or ownership is required. The type is designed to
71/// work with general borrowed data via the `Borrow` trait.
72///
73/// `Cow` implements `Deref`, which means that you can call non-mutating methods
74/// directly on the data it encloses. If mutation is desired, `to_mut` will
75/// obtain a mutable reference to an owned value, cloning if necessary.
76///
77/// If you need reference-counting pointers, note that
78/// [`Rc::make_mut`][rust_alloc::rc::Rc::make_mut] and
79/// [`Arc::make_mut`][rust_alloc::sync::Arc::make_mut] can provide
80/// clone-on-write functionality as well.
81///
82/// # Examples
83///
84/// ```
85/// use rune::alloc::borrow::Cow;
86/// use rune::alloc::try_vec;
87/// use rune::alloc::prelude::*;
88///
89/// fn abs_all(input: &mut Cow<'_, [i32]>) -> rune::alloc::Result<()> {
90///     for i in 0..input.len() {
91///         let v = input[i];
92///         if v < 0 {
93///             // Clones into a vector if not already owned.
94///             input.try_to_mut()?[i] = -v;
95///         }
96///     }
97///
98///     Ok(())
99/// }
100///
101/// // No clone occurs because `input` doesn't need to be mutated.
102/// let slice = [0, 1, 2];
103/// let mut input = Cow::from(&slice[..]);
104/// abs_all(&mut input)?;
105///
106/// // Clone occurs because `input` needs to be mutated.
107/// let slice = [-1, 0, 1];
108/// let mut input = Cow::from(&slice[..]);
109/// abs_all(&mut input)?;
110///
111/// // No clone occurs because `input` is already owned.
112/// let mut input = Cow::from(try_vec![-1, 0, 1]);
113/// abs_all(&mut input)?;
114/// # Ok::<_, rune::alloc::Error>(())
115/// ```
116///
117/// Another example showing how to keep `Cow` in a struct:
118///
119/// ```
120/// use rune::alloc::Vec;
121/// use rune::alloc::borrow::Cow;
122/// use rune::alloc::prelude::*;
123///
124/// struct Items<'a, X> where [X]: TryToOwned<Owned = Vec<X>> {
125///     values: Cow<'a, [X]>,
126/// }
127///
128/// impl<'a, X: TryClone + 'a> Items<'a, X> where [X]: TryToOwned<Owned = Vec<X>> {
129///     fn new(v: Cow<'a, [X]>) -> Self {
130///         Items { values: v }
131///     }
132/// }
133///
134/// // Creates a container from borrowed values of a slice
135/// let readonly = [1, 2];
136/// let borrowed = Items::new((&readonly[..]).into());
137/// match borrowed {
138///     Items { values: Cow::Borrowed(b) } => println!("borrowed {b:?}"),
139///     _ => panic!("expect borrowed value"),
140/// }
141///
142/// let mut clone_on_write = borrowed;
143/// // Mutates the data from slice into owned vec and pushes a new value on top
144/// clone_on_write.values.try_to_mut()?.try_push(3)?;
145/// println!("clone_on_write = {:?}", clone_on_write.values);
146///
147/// // The data was mutated. Let's check it out.
148/// match clone_on_write {
149///     Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"),
150///     _ => panic!("expect owned data"),
151/// }
152/// # Ok::<_, rune::alloc::Error>(())
153/// ```
154pub enum Cow<'b, T: ?Sized + 'b>
155where
156    T: TryToOwned,
157{
158    /// Borrowed data.
159    Borrowed(&'b T),
160    /// Owned data.
161    Owned(<T as TryToOwned>::Owned),
162}
163
164impl<B: ?Sized + TryToOwned> Cow<'_, B> {
165    /// Returns true if the data is borrowed, i.e. if `to_mut` would require
166    /// additional work.
167    ///
168    /// # Examples
169    ///
170    /// ```
171    /// use rune::alloc::borrow::Cow;
172    /// use rune::alloc::prelude::*;
173    ///
174    /// let cow = Cow::Borrowed("moo");
175    /// assert!(cow.is_borrowed());
176    ///
177    /// let bull: Cow<'_, str> = Cow::Owned("...moo?".try_to_string()?);
178    /// assert!(!bull.is_borrowed());
179    /// # Ok::<_, rune::alloc::Error>(())
180    /// ```
181    pub const fn is_borrowed(&self) -> bool {
182        matches!(self, Cow::Borrowed(..))
183    }
184
185    /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op.
186    ///
187    /// # Examples
188    ///
189    /// ```
190    /// use rune::alloc::borrow::Cow;
191    /// use rune::alloc::prelude::*;
192    ///
193    /// let cow: Cow<'_, str> = Cow::Owned("moo".try_to_string()?);
194    /// assert!(cow.is_owned());
195    ///
196    /// let bull = Cow::Borrowed("...moo?");
197    /// assert!(!bull.is_owned());
198    /// # Ok::<_, rune::alloc::Error>(())
199    /// ```
200    pub const fn is_owned(&self) -> bool {
201        !self.is_borrowed()
202    }
203
204    /// Acquires a mutable reference to the owned form of the data.
205    ///
206    /// Clones the data if it is not already owned.
207    ///
208    /// # Examples
209    ///
210    /// ```
211    /// use rune::alloc::borrow::Cow;
212    /// use rune::alloc::String;
213    ///
214    /// let mut cow = Cow::Borrowed("foo");
215    /// cow.try_to_mut()?.make_ascii_uppercase();
216    ///
217    /// assert_eq!(cow, Cow::Owned(String::try_from("FOO")?));
218    /// # Ok::<_, rune::alloc::Error>(())
219    /// ```
220    pub fn try_to_mut(&mut self) -> Result<&mut <B as TryToOwned>::Owned, Error> {
221        Ok(match *self {
222            Cow::Borrowed(borrowed) => {
223                *self = Cow::Owned(borrowed.try_to_owned()?);
224
225                match *self {
226                    Cow::Borrowed(..) => unreachable!(),
227                    Cow::Owned(ref mut owned) => owned,
228                }
229            }
230            Cow::Owned(ref mut owned) => owned,
231        })
232    }
233
234    /// Extracts the owned data.
235    ///
236    /// Clones the data if it is not already owned.
237    ///
238    /// # Examples
239    ///
240    /// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data:
241    ///
242    /// ```
243    /// use rune::alloc::borrow::Cow;
244    /// use rune::alloc::String;
245    ///
246    /// let s = "Hello world!";
247    /// let cow = Cow::Borrowed(s);
248    ///
249    /// assert_eq!(cow.try_into_owned()?, String::try_from(s)?);
250    /// # Ok::<_, rune::alloc::Error>(())
251    /// ```
252    ///
253    /// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the
254    /// `Cow` without being cloned.
255    ///
256    /// ```
257    /// use rune::alloc::borrow::Cow;
258    /// use rune::alloc::String;
259    ///
260    /// let s = "Hello world!";
261    /// let cow: Cow<'_, str> = Cow::Owned(String::try_from(s)?);
262    ///
263    /// assert_eq!(cow.try_into_owned()?, String::try_from(s)?);
264    /// # Ok::<_, rune::alloc::Error>(())
265    /// ```
266    pub fn try_into_owned(self) -> Result<<B as TryToOwned>::Owned, Error> {
267        match self {
268            Cow::Borrowed(borrowed) => borrowed.try_to_owned(),
269            Cow::Owned(owned) => Ok(owned),
270        }
271    }
272}
273
274impl<'a, T: ?Sized + 'a> From<&'a T> for Cow<'a, T>
275where
276    T: TryToOwned,
277{
278    /// Construct a `Cow` from a reference.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use rune::alloc::borrow::Cow;
284    ///
285    /// let s = Cow::from("Hello World");
286    /// assert_eq!("Hello World", s);
287    /// # Ok::<_, rune::alloc::Error>(())
288    /// ```
289    #[inline]
290    fn from(b: &'a T) -> Self {
291        Cow::Borrowed(b)
292    }
293}
294
295#[cfg(feature = "alloc")]
296impl<'a, T: ?Sized + 'a> TryFrom<rust_alloc::borrow::Cow<'a, T>> for Cow<'a, T>
297where
298    T: ToOwned + TryToOwned<Owned: TryFrom<<T as ToOwned>::Owned>>,
299{
300    type Error = <<T as TryToOwned>::Owned as TryFrom<<T as ToOwned>::Owned>>::Error;
301
302    fn try_from(value: rust_alloc::borrow::Cow<'a, T>) -> Result<Self, Self::Error> {
303        Ok(match value {
304            rust_alloc::borrow::Cow::Borrowed(b) => Cow::Borrowed(b),
305            rust_alloc::borrow::Cow::Owned(o) => Cow::Owned(<T as TryToOwned>::Owned::try_from(o)?),
306        })
307    }
308}
309
310impl<B> Deref for Cow<'_, B>
311where
312    B: ?Sized + TryToOwned<Owned: Borrow<B>>,
313{
314    type Target = B;
315
316    fn deref(&self) -> &B {
317        match *self {
318            Cow::Borrowed(borrowed) => borrowed,
319            Cow::Owned(ref owned) => owned.borrow(),
320        }
321    }
322}
323
324impl<T: ?Sized + TryToOwned> AsRef<T> for Cow<'_, T> {
325    #[inline]
326    fn as_ref(&self) -> &T {
327        self
328    }
329}
330
331impl<T: ?Sized> fmt::Display for Cow<'_, T>
332where
333    T: fmt::Display + TryToOwned,
334{
335    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336        (**self).fmt(f)
337    }
338}
339
340impl<T: ?Sized> fmt::Debug for Cow<'_, T>
341where
342    T: fmt::Debug + TryToOwned,
343{
344    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345        (**self).fmt(f)
346    }
347}
348
349impl TryClone for Cow<'_, str> {
350    #[inline]
351    fn try_clone(&self) -> Result<Self, Error> {
352        Ok(match self {
353            Cow::Borrowed(b) => Cow::Borrowed(b),
354            Cow::Owned(o) => Cow::Owned(o.try_clone()?),
355        })
356    }
357}
358
359impl<T> From<Vec<T>> for Cow<'_, [T]>
360where
361    T: TryClone,
362{
363    fn from(vec: Vec<T>) -> Self {
364        Cow::Owned(vec)
365    }
366}
367
368impl<B: ?Sized> PartialEq for Cow<'_, B>
369where
370    B: PartialEq + TryToOwned,
371{
372    #[inline]
373    fn eq(&self, other: &Self) -> bool {
374        (**self).eq(&**other)
375    }
376}
377
378impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + TryToOwned {}
379
380impl<B: ?Sized> PartialOrd for Cow<'_, B>
381where
382    B: PartialOrd + TryToOwned,
383{
384    #[inline]
385    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
386        (**self).partial_cmp(&**other)
387    }
388}
389
390impl<B: ?Sized> Ord for Cow<'_, B>
391where
392    B: Ord + TryToOwned,
393{
394    #[inline]
395    fn cmp(&self, other: &Self) -> Ordering {
396        (**self).cmp(&**other)
397    }
398}
399
400impl<B> Hash for Cow<'_, B>
401where
402    B: ?Sized + Hash + TryToOwned,
403{
404    #[inline]
405    fn hash<H>(&self, state: &mut H)
406    where
407        H: Hasher,
408    {
409        Hash::hash(&**self, state)
410    }
411}