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
57impl TryToOwned for crate::path::Path {
58    type Owned = crate::path::PathBuf;
59
60    fn try_to_owned(&self) -> Result<Self::Owned, Error> {
61        Ok(self.to_path_buf())
62    }
63}
64
65/// A clone-on-write smart pointer.
66///
67/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
68/// can enclose and provide immutable access to borrowed data, and clone the
69/// data lazily when mutation or ownership is required. The type is designed to
70/// work with general borrowed data via the `Borrow` trait.
71///
72/// `Cow` implements `Deref`, which means that you can call non-mutating methods
73/// directly on the data it encloses. If mutation is desired, `to_mut` will
74/// obtain a mutable reference to an owned value, cloning if necessary.
75///
76/// If you need reference-counting pointers, note that
77/// [`Rc::make_mut`][rust_alloc::rc::Rc::make_mut] and
78/// [`Arc::make_mut`][rust_alloc::sync::Arc::make_mut] can provide
79/// clone-on-write functionality as well.
80///
81/// # Examples
82///
83/// ```
84/// use rune::alloc::borrow::Cow;
85/// use rune::alloc::try_vec;
86/// use rune::alloc::prelude::*;
87///
88/// fn abs_all(input: &mut Cow<'_, [i32]>) -> rune::alloc::Result<()> {
89///     for i in 0..input.len() {
90///         let v = input[i];
91///         if v < 0 {
92///             // Clones into a vector if not already owned.
93///             input.try_to_mut()?[i] = -v;
94///         }
95///     }
96///
97///     Ok(())
98/// }
99///
100/// // No clone occurs because `input` doesn't need to be mutated.
101/// let slice = [0, 1, 2];
102/// let mut input = Cow::from(&slice[..]);
103/// abs_all(&mut input)?;
104///
105/// // Clone occurs because `input` needs to be mutated.
106/// let slice = [-1, 0, 1];
107/// let mut input = Cow::from(&slice[..]);
108/// abs_all(&mut input)?;
109///
110/// // No clone occurs because `input` is already owned.
111/// let mut input = Cow::from(try_vec![-1, 0, 1]);
112/// abs_all(&mut input)?;
113/// # Ok::<_, rune::alloc::Error>(())
114/// ```
115///
116/// Another example showing how to keep `Cow` in a struct:
117///
118/// ```
119/// use rune::alloc::Vec;
120/// use rune::alloc::borrow::Cow;
121/// use rune::alloc::prelude::*;
122///
123/// struct Items<'a, X> where [X]: TryToOwned<Owned = Vec<X>> {
124///     values: Cow<'a, [X]>,
125/// }
126///
127/// impl<'a, X: TryClone + 'a> Items<'a, X> where [X]: TryToOwned<Owned = Vec<X>> {
128///     fn new(v: Cow<'a, [X]>) -> Self {
129///         Items { values: v }
130///     }
131/// }
132///
133/// // Creates a container from borrowed values of a slice
134/// let readonly = [1, 2];
135/// let borrowed = Items::new((&readonly[..]).into());
136/// match borrowed {
137///     Items { values: Cow::Borrowed(b) } => println!("borrowed {b:?}"),
138///     _ => panic!("expect borrowed value"),
139/// }
140///
141/// let mut clone_on_write = borrowed;
142/// // Mutates the data from slice into owned vec and pushes a new value on top
143/// clone_on_write.values.try_to_mut()?.try_push(3)?;
144/// println!("clone_on_write = {:?}", clone_on_write.values);
145///
146/// // The data was mutated. Let's check it out.
147/// match clone_on_write {
148///     Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"),
149///     _ => panic!("expect owned data"),
150/// }
151/// # Ok::<_, rune::alloc::Error>(())
152/// ```
153pub enum Cow<'b, T: ?Sized + 'b>
154where
155    T: TryToOwned,
156{
157    /// Borrowed data.
158    Borrowed(&'b T),
159    /// Owned data.
160    Owned(<T as TryToOwned>::Owned),
161}
162
163impl<B: ?Sized + TryToOwned> Cow<'_, B> {
164    /// Returns true if the data is borrowed, i.e. if `to_mut` would require
165    /// additional work.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use rune::alloc::borrow::Cow;
171    /// use rune::alloc::prelude::*;
172    ///
173    /// let cow = Cow::Borrowed("moo");
174    /// assert!(cow.is_borrowed());
175    ///
176    /// let bull: Cow<'_, str> = Cow::Owned("...moo?".try_to_string()?);
177    /// assert!(!bull.is_borrowed());
178    /// # Ok::<_, rune::alloc::Error>(())
179    /// ```
180    pub const fn is_borrowed(&self) -> bool {
181        matches!(self, Cow::Borrowed(..))
182    }
183
184    /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op.
185    ///
186    /// # Examples
187    ///
188    /// ```
189    /// use rune::alloc::borrow::Cow;
190    /// use rune::alloc::prelude::*;
191    ///
192    /// let cow: Cow<'_, str> = Cow::Owned("moo".try_to_string()?);
193    /// assert!(cow.is_owned());
194    ///
195    /// let bull = Cow::Borrowed("...moo?");
196    /// assert!(!bull.is_owned());
197    /// # Ok::<_, rune::alloc::Error>(())
198    /// ```
199    pub const fn is_owned(&self) -> bool {
200        !self.is_borrowed()
201    }
202
203    /// Acquires a mutable reference to the owned form of the data.
204    ///
205    /// Clones the data if it is not already owned.
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use rune::alloc::borrow::Cow;
211    /// use rune::alloc::String;
212    ///
213    /// let mut cow = Cow::Borrowed("foo");
214    /// cow.try_to_mut()?.make_ascii_uppercase();
215    ///
216    /// assert_eq!(cow, Cow::Owned(String::try_from("FOO")?));
217    /// # Ok::<_, rune::alloc::Error>(())
218    /// ```
219    pub fn try_to_mut(&mut self) -> Result<&mut <B as TryToOwned>::Owned, Error> {
220        Ok(match *self {
221            Cow::Borrowed(borrowed) => {
222                *self = Cow::Owned(borrowed.try_to_owned()?);
223
224                match *self {
225                    Cow::Borrowed(..) => unreachable!(),
226                    Cow::Owned(ref mut owned) => owned,
227                }
228            }
229            Cow::Owned(ref mut owned) => owned,
230        })
231    }
232
233    /// Extracts the owned data.
234    ///
235    /// Clones the data if it is not already owned.
236    ///
237    /// # Examples
238    ///
239    /// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data:
240    ///
241    /// ```
242    /// use rune::alloc::borrow::Cow;
243    /// use rune::alloc::String;
244    ///
245    /// let s = "Hello world!";
246    /// let cow = Cow::Borrowed(s);
247    ///
248    /// assert_eq!(cow.try_into_owned()?, String::try_from(s)?);
249    /// # Ok::<_, rune::alloc::Error>(())
250    /// ```
251    ///
252    /// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the
253    /// `Cow` without being cloned.
254    ///
255    /// ```
256    /// use rune::alloc::borrow::Cow;
257    /// use rune::alloc::String;
258    ///
259    /// let s = "Hello world!";
260    /// let cow: Cow<'_, str> = Cow::Owned(String::try_from(s)?);
261    ///
262    /// assert_eq!(cow.try_into_owned()?, String::try_from(s)?);
263    /// # Ok::<_, rune::alloc::Error>(())
264    /// ```
265    pub fn try_into_owned(self) -> Result<<B as TryToOwned>::Owned, Error> {
266        match self {
267            Cow::Borrowed(borrowed) => borrowed.try_to_owned(),
268            Cow::Owned(owned) => Ok(owned),
269        }
270    }
271}
272
273impl<'a, T: ?Sized + 'a> From<&'a T> for Cow<'a, T>
274where
275    T: TryToOwned,
276{
277    /// Construct a `Cow` from a reference.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// use rune::alloc::borrow::Cow;
283    ///
284    /// let s = Cow::from("Hello World");
285    /// assert_eq!("Hello World", s);
286    /// # Ok::<_, rune::alloc::Error>(())
287    /// ```
288    #[inline]
289    fn from(b: &'a T) -> Self {
290        Cow::Borrowed(b)
291    }
292}
293
294#[cfg(feature = "alloc")]
295impl<'a, T: ?Sized + 'a> TryFrom<rust_alloc::borrow::Cow<'a, T>> for Cow<'a, T>
296where
297    T: ToOwned + TryToOwned,
298    <T as 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: ?Sized + TryToOwned> Deref for Cow<'_, B>
311where
312    B::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: ?Sized> Hash for Cow<'_, B>
401where
402    B: Hash + TryToOwned,
403{
404    #[inline]
405    fn hash<H: Hasher>(&self, state: &mut H) {
406        Hash::hash(&**self, state)
407    }
408}