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}