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}