1use 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
14pub type Owned<B, A> = <B as ToOwnedIn<A>>::Owned;
16
17pub trait ToOwnedIn<A: Allocator> {
19 type Owned: Borrow<Self>;
21
22 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 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
50pub enum Cow<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> {
52 Borrowed(&'b T),
54
55 Owned(Owned<T, A>),
57}
58
59impl<'b, T: ToOwnedIn<A> + ?Sized, A: Allocator> Cow<'b, T, A> {
60 #[inline]
62 pub fn is_borrowed(&self) -> bool {
63 matches!(self, Self::Borrowed(_))
64 }
65
66 #[inline]
68 pub fn is_owned(&self) -> bool {
69 matches!(self, Self::Owned(_))
70 }
71
72 #[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 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 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 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 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 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> {}