flex_alloc/
borrow.rs

1//! Support for flexibility over owned or borrowed collections.
2
3use core::{
4    borrow::Borrow,
5    fmt::{self, Debug, Display},
6    ops::Deref,
7};
8
9use const_default::ConstDefault;
10
11use crate::alloc::{AllocateIn, Allocator};
12use crate::error::StorageError;
13
14/// The owned type for a collection which may be owned or borrowed.
15pub type Owned<B, A> = <B as ToOwnedIn<A>>::Owned;
16
17/// Support conversion from borrowed types to owned ones associated with an allocator.
18pub trait ToOwnedIn<A: Allocator> {
19    /// The owned representation of this type.
20    type Owned: Borrow<Self>;
21
22    /// Create an owned copy of this instance in a given allocation target.
23    fn to_owned_in<I>(&self, alloc_in: I) -> Self::Owned
24    where
25        I: AllocateIn<Alloc = A>,
26    {
27        match self.try_to_owned_in(alloc_in) {
28            Ok(inst) => inst,
29            Err(err) => err.panic(),
30        }
31    }
32
33    /// To to create an owned copy of this instance in a given allocation target.
34    fn try_to_owned_in<I>(&self, alloc_in: I) -> Result<Self::Owned, StorageError>
35    where
36        I: AllocateIn<Alloc = A>;
37}
38
39impl<T: Clone + 'static, A: Allocator> ToOwnedIn<A> for T {
40    type Owned = T;
41
42    fn try_to_owned_in<I>(&self, _alloc_in: I) -> Result<Self::Owned, StorageError>
43    where
44        I: AllocateIn<Alloc = A>,
45    {
46        Ok(self.clone())
47    }
48}
49
50/// Representation of either an owned or borrowed instance of a type.
51pub enum Cow<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> {
52    /// The borrowed variant, limited by a lifetime.
53    Borrowed(&'b T),
54
55    /// The owned variant.
56    Owned(Owned<T, A>),
57}
58
59impl<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> Cow<'b, T, A> {
60    /// Determine if this instance is borrowed.
61    #[inline]
62    pub fn is_borrowed(&self) -> bool {
63        matches!(self, Self::Borrowed(_))
64    }
65
66    /// Determine if this instance is owned.
67    #[inline]
68    pub fn is_owned(&self) -> bool {
69        matches!(self, Self::Owned(_))
70    }
71
72    /// If necessary, convert `self` into an owned instance. Return a mutable reference
73    /// to the owned instance.
74    #[inline]
75    pub fn to_mut(&mut self) -> &mut Owned<T, A>
76    where
77        A: Default + Allocator,
78    {
79        self.to_mut_in(A::default())
80    }
81
82    /// If necessary, convert `self` into an owned instance given an allocation target.
83    /// Return a mutable reference to the owned instance.
84    pub fn to_mut_in<I>(&mut self, alloc_in: I) -> &mut Owned<T, A>
85    where
86        I: AllocateIn<Alloc = A>,
87    {
88        match *self {
89            Self::Borrowed(borrowed) => {
90                *self = Self::Owned(borrowed.to_owned_in(alloc_in));
91                let Self::Owned(owned) = self else {
92                    unreachable!()
93                };
94                owned
95            }
96            Self::Owned(ref mut owned) => owned,
97        }
98    }
99
100    /// If necessary, convert `self` into an owned instance. Unwrap and return the
101    /// owned instance.
102    pub fn into_owned(self) -> Owned<T, A>
103    where
104        A: Default + Allocator,
105    {
106        match self {
107            Self::Borrowed(borrowed) => borrowed.to_owned_in(A::default()),
108            Self::Owned(owned) => owned,
109        }
110    }
111
112    /// If necessary, convert `self` into an owned instance given an allocation target.
113    /// Unwrap and return the owned instance.
114    pub fn into_owned_in<I>(self, alloc_in: I) -> Owned<T, A>
115    where
116        I: AllocateIn<Alloc = A>,
117    {
118        match self {
119            Self::Borrowed(borrowed) => borrowed.to_owned_in(alloc_in),
120            Self::Owned(owned) => owned,
121        }
122    }
123
124    /// If necessary, try to convert `self` into an owned instance.
125    /// Unwrap and return the owned instance or a storage error.
126    pub fn try_into_owned(self) -> Result<Owned<T, A>, StorageError>
127    where
128        A: Default + Allocator,
129    {
130        match self {
131            Self::Borrowed(borrowed) => borrowed.try_to_owned_in(A::default()),
132            Self::Owned(owned) => Ok(owned),
133        }
134    }
135
136    /// If necessary, try to convert `self` into an owned instance given an allocation
137    /// target. Unwrap and return the owned instance or a storage error.
138    pub fn try_into_owned_in<I>(self, storage: I) -> Result<Owned<T, A>, StorageError>
139    where
140        I: AllocateIn<Alloc = A>,
141    {
142        match self {
143            Self::Borrowed(borrowed) => borrowed.try_to_owned_in(storage),
144            Self::Owned(owned) => Ok(owned),
145        }
146    }
147}
148
149impl<T: ToOwnedIn<A> + ?Sized, A: Allocator> AsRef<T> for Cow<'_, T, A> {
150    fn as_ref(&self) -> &T {
151        self
152    }
153}
154
155impl<T: ToOwnedIn<A> + ?Sized, A: Allocator> Borrow<T> for Cow<'_, T, A> {
156    fn borrow(&self) -> &T {
157        self
158    }
159}
160
161impl<T: ToOwnedIn<A> + ?Sized, A: Allocator> Clone for Cow<'_, T, A>
162where
163    Owned<T, A>: Clone,
164{
165    fn clone(&self) -> Self {
166        match self {
167            Self::Borrowed(b) => Self::Borrowed(*b),
168            Self::Owned(o) => Self::Owned(o.clone()),
169        }
170    }
171
172    fn clone_from(&mut self, source: &Self) {
173        match (self, source) {
174            (&mut Self::Owned(ref mut dest), Self::Owned(ref o)) => dest.clone_from(o),
175            (t, s) => *t = s.clone(),
176        }
177    }
178}
179
180impl<T, A: Allocator> ConstDefault for Cow<'_, T, A>
181where
182    T: ToOwnedIn<A> + ?Sized,
183    T::Owned: ConstDefault,
184{
185    const DEFAULT: Self = Self::Owned(T::Owned::DEFAULT);
186}
187
188impl<T, A: Allocator> Debug for Cow<'_, T, A>
189where
190    T: ToOwnedIn<A> + Debug + ?Sized,
191    Owned<T, A>: Debug,
192{
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        match *self {
195            Self::Borrowed(b) => Debug::fmt(b, f),
196            Self::Owned(ref o) => Debug::fmt(o, f),
197        }
198    }
199}
200
201impl<T, A: Allocator> Display for Cow<'_, T, A>
202where
203    T: ToOwnedIn<A> + Display + ?Sized,
204    Owned<T, A>: Display,
205{
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        match *self {
208            Self::Borrowed(ref b) => Display::fmt(b, f),
209            Self::Owned(ref o) => Display::fmt(o, f),
210        }
211    }
212}
213
214impl<T: ToOwnedIn<A> + ?Sized, A: Allocator> Deref for Cow<'_, T, A> {
215    type Target = T;
216
217    fn deref(&self) -> &T {
218        match *self {
219            Self::Borrowed(borrowed) => borrowed,
220            Self::Owned(ref owned) => owned.borrow(),
221        }
222    }
223}
224
225impl<T: ToOwnedIn<A> + ?Sized, A: Allocator> Default for Cow<'_, T, A>
226where
227    Owned<T, A>: Default,
228{
229    #[inline]
230    fn default() -> Self {
231        Self::Owned(Default::default())
232    }
233}
234
235impl<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> From<&'b T> for Cow<'b, T, A> {
236    #[inline]
237    fn from(borrow: &'b T) -> Self {
238        Self::Borrowed(borrow)
239    }
240}
241
242impl<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> From<&'b mut T> for Cow<'b, T, A> {
243    #[inline]
244    fn from(borrow: &'b mut T) -> Self {
245        Self::Borrowed(borrow)
246    }
247}
248
249impl<'a, 'b, T: ToOwnedIn<A> + ?Sized, A: Allocator, U: ToOwnedIn<B> + ?Sized, B: Allocator>
250    PartialEq<Cow<'b, U, B>> for Cow<'a, T, A>
251where
252    T: PartialEq<U>,
253{
254    #[inline]
255    fn eq(&self, other: &Cow<'b, U, B>) -> bool {
256        self.deref().eq(other.deref())
257    }
258}
259
260impl<'a, T: ToOwnedIn<A> + Eq + ?Sized, A: Allocator> Eq for Cow<'a, T, A> {}