as_is/
is_cow.rs

1use crate::{AsIs, BorrowAsIs, Is, IsMut, Owned, ToOwned, ToOwnedMut};
2use core::borrow::{Borrow, BorrowMut};
3use core::cmp::Ordering;
4use core::hash::{Hash, Hasher};
5use core::ops::{Add, BitAnd, BitOr, BitXor, Deref, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub};
6use ref_ops::{
7    RefAdd, RefBitAnd, RefBitOr, RefBitXor, RefDiv, RefMul, RefMutAdd, RefMutBitAnd, RefMutBitOr,
8    RefMutBitXor, RefMutDiv, RefMutMul, RefMutNeg, RefMutNot, RefMutRem, RefMutShl, RefMutShr,
9    RefMutSub, RefNeg, RefNot, RefRem, RefShl, RefShr, RefSub,
10};
11
12/// Represents an owned or an immutably borrowed data.
13#[derive(Debug)]
14pub enum IsCow<'a, T>
15where
16    T: ?Sized + ToOwned,
17{
18    /// Owned data.
19    Owned(T::Owned),
20    /// Immutably borrowed data.
21    Borrowed(&'a T),
22}
23
24impl<T> Default for IsCow<'_, T>
25where
26    T: ?Sized + ToOwned,
27    T::Owned: Default,
28{
29    /// Creates an owned [`IsCow<'_, T>`] with the default value for `T::Owned`.
30    ///
31    /// [`IsCow<'_, T>`]: enum.IsCow.html
32    fn default() -> Self {
33        IsCow::Owned(T::Owned::default())
34    }
35}
36
37impl<T> Deref for IsCow<'_, T>
38where
39    T: ?Sized + ToOwned,
40{
41    type Target = T;
42
43    fn deref(&self) -> &T {
44        match self {
45            IsCow::Owned(x) => x.borrow(),
46            IsCow::Borrowed(x) => x,
47        }
48    }
49}
50
51impl<T> Borrow<T> for IsCow<'_, T>
52where
53    T: ?Sized + ToOwned,
54{
55    fn borrow(&self) -> &T {
56        self
57    }
58}
59
60impl<T> Borrow<T> for &IsCow<'_, T>
61where
62    T: ?Sized + ToOwned,
63{
64    fn borrow(&self) -> &T {
65        self
66    }
67}
68
69impl<T> Borrow<T> for &mut IsCow<'_, T>
70where
71    T: ?Sized + ToOwned,
72{
73    fn borrow(&self) -> &T {
74        self
75    }
76}
77
78impl<T, U> PartialEq<Is<'_, U>> for IsCow<'_, T>
79where
80    T: ?Sized + ToOwned + PartialEq<U>,
81    U: ?Sized + ToOwned,
82{
83    fn eq(&self, other: &Is<'_, U>) -> bool {
84        **self == **other
85    }
86}
87
88impl<T, U> PartialEq<IsCow<'_, U>> for IsCow<'_, T>
89where
90    T: ?Sized + ToOwned + PartialEq<U>,
91    U: ?Sized + ToOwned,
92{
93    fn eq(&self, other: &IsCow<'_, U>) -> bool {
94        **self == **other
95    }
96}
97
98impl<T, U> PartialEq<IsMut<'_, U>> for IsCow<'_, T>
99where
100    T: ?Sized + ToOwned + PartialEq<U>,
101    U: ?Sized + ToOwned,
102{
103    fn eq(&self, other: &IsMut<'_, U>) -> bool {
104        **self == **other
105    }
106}
107
108impl<T> Eq for IsCow<'_, T> where T: ?Sized + ToOwned + Eq {}
109
110impl<T, U> PartialOrd<Is<'_, U>> for IsCow<'_, T>
111where
112    T: ?Sized + ToOwned + PartialOrd<U>,
113    U: ?Sized + ToOwned,
114{
115    fn partial_cmp(&self, other: &Is<'_, U>) -> Option<Ordering> {
116        (**self).partial_cmp(&**other)
117    }
118}
119
120impl<T, U> PartialOrd<IsCow<'_, U>> for IsCow<'_, T>
121where
122    T: ?Sized + ToOwned + PartialOrd<U>,
123    U: ?Sized + ToOwned,
124{
125    fn partial_cmp(&self, other: &IsCow<'_, U>) -> Option<Ordering> {
126        (**self).partial_cmp(&**other)
127    }
128}
129
130impl<T, U> PartialOrd<IsMut<'_, U>> for IsCow<'_, T>
131where
132    T: ?Sized + ToOwned + PartialOrd<U>,
133    U: ?Sized + ToOwned,
134{
135    fn partial_cmp(&self, other: &IsMut<'_, U>) -> Option<Ordering> {
136        (**self).partial_cmp(&**other)
137    }
138}
139
140impl<T> Ord for IsCow<'_, T>
141where
142    T: ?Sized + ToOwned + Ord,
143{
144    fn cmp(&self, other: &Self) -> Ordering {
145        (**self).cmp(&**other)
146    }
147}
148
149impl<T> Hash for IsCow<'_, T>
150where
151    T: ?Sized + ToOwned + Hash,
152{
153    fn hash<H: Hasher>(&self, state: &mut H) {
154        (**self).hash(state);
155    }
156}
157
158impl<T> BorrowAsIs for IsCow<'_, T>
159where
160    T: ?Sized + BorrowAsIs<Is = T> + ToOwned,
161{
162    type Is = T;
163
164    fn borrow_or_clone<B>(&self) -> IsCow<'_, B>
165    where
166        T: Borrow<B>,
167        B: ?Sized + ToOwned<Owned = T::Owned>,
168    {
169        (**self).borrow_or_clone()
170    }
171}
172
173impl<T> AsIs for IsCow<'_, T>
174where
175    T: ?Sized + BorrowAsIs<Is = T> + ToOwned,
176{
177    fn as_is<'a>(self) -> Is<'a, T>
178    where
179        Self: 'a,
180    {
181        match self {
182            IsCow::Owned(x) => Is::Owned(x),
183            IsCow::Borrowed(x) => match x.borrow_or_clone() {
184                IsCow::Owned(x) => Is::Owned(x),
185                IsCow::Borrowed(_) => Is::Borrowed(x),
186            },
187        }
188    }
189}
190
191macro_rules! impl_unop {
192    ($Op:ident, $op:ident, $RefOp:ident, $ref_op:ident, $RefMutOp:ident, $ref_mut_op:ident) => {
193        impl<T> $Op for IsCow<'_, T>
194        where
195            T: ?Sized + ToOwned + $RefOp,
196            T::Owned: $Op<Output = T::Output>,
197        {
198            type Output = T::Output;
199
200            fn $op(self) -> Self::Output {
201                match self {
202                    IsCow::Owned(x) => x.$op(),
203                    IsCow::Borrowed(x) => x.$ref_op(),
204                }
205            }
206        }
207
208        impl<T> $Op for &IsCow<'_, T>
209        where
210            T: ?Sized + ToOwned + $RefOp,
211        {
212            type Output = T::Output;
213
214            fn $op(self) -> Self::Output {
215                (**self).$ref_op()
216            }
217        }
218
219        impl<T> $Op for &mut IsCow<'_, T>
220        where
221            T: ?Sized + ToOwnedMut + $RefOp + $RefMutOp<Output = <T as $RefOp>::Output>,
222        {
223            type Output = <T as $RefOp>::Output;
224
225            fn $op(self) -> Self::Output {
226                match self {
227                    IsCow::Owned(x) => x.borrow_mut().$ref_mut_op(),
228                    IsCow::Borrowed(x) => x.$ref_op(),
229                }
230            }
231        }
232    };
233}
234
235impl_unop!(Neg, neg, RefNeg, ref_neg, RefMutNeg, ref_mut_neg);
236impl_unop!(Not, not, RefNot, ref_not, RefMutNot, ref_mut_not);
237
238macro_rules! impl_binop {
239    ($Op:ident, $op:ident, $RefOp:ident, $ref_op:ident, $RefMutOp:ident, $ref_mut_op:ident) => {
240        impl<T, U, O> $Op<U> for IsCow<'_, T>
241        where
242            T: ?Sized
243                + ToOwned
244                + $RefOp<Owned<U>, Output = O>
245                + for<'a> $RefOp<&'a U::Is, Output = O>
246                + for<'a> $RefOp<&'a mut U::Is, Output = O>,
247            U: AsIs,
248            T::Owned: $Op<Owned<U>, Output = O>
249                + for<'a> $Op<&'a U::Is, Output = O>
250                + for<'a> $Op<&'a mut U::Is, Output = O>,
251        {
252            type Output = O;
253
254            fn $op(self, rhs: U) -> Self::Output {
255                match self {
256                    IsCow::Owned(x) => match rhs.as_is() {
257                        Is::Owned(y) => x.$op(y),
258                        Is::Borrowed(y) => x.$op(y),
259                        Is::MutBorrowed(y) => x.$op(y),
260                    },
261                    IsCow::Borrowed(x) => match rhs.as_is() {
262                        Is::Owned(y) => x.$ref_op(y),
263                        Is::Borrowed(y) => x.$ref_op(y),
264                        Is::MutBorrowed(y) => x.$ref_op(y),
265                    },
266                }
267            }
268        }
269
270        impl<T, U, O> $Op<U> for &IsCow<'_, T>
271        where
272            T: ?Sized
273                + ToOwned
274                + $RefOp<Owned<U>, Output = O>
275                + for<'a> $RefOp<&'a U::Is, Output = O>
276                + for<'a> $RefOp<&'a mut U::Is, Output = O>,
277            U: AsIs,
278        {
279            type Output = O;
280
281            fn $op(self, rhs: U) -> Self::Output {
282                match rhs.as_is() {
283                    Is::Owned(y) => (**self).$ref_op(y),
284                    Is::Borrowed(y) => (**self).$ref_op(y),
285                    Is::MutBorrowed(y) => (**self).$ref_op(y),
286                }
287            }
288        }
289
290        impl<T, U, O> $Op<U> for &mut IsCow<'_, T>
291        where
292            T: ?Sized
293                + ToOwnedMut
294                + $RefOp<Owned<U>, Output = O>
295                + for<'a> $RefOp<&'a U::Is, Output = O>
296                + for<'a> $RefOp<&'a mut U::Is, Output = O>
297                + $RefMutOp<Owned<U>, Output = O>
298                + for<'a> $RefMutOp<&'a U::Is, Output = O>
299                + for<'a> $RefMutOp<&'a mut U::Is, Output = O>,
300            U: AsIs,
301        {
302            type Output = O;
303
304            fn $op(self, rhs: U) -> Self::Output {
305                match self {
306                    IsCow::Owned(x) => match rhs.as_is() {
307                        Is::Owned(y) => x.borrow_mut().$ref_mut_op(y),
308                        Is::Borrowed(y) => x.borrow_mut().$ref_mut_op(y),
309                        Is::MutBorrowed(y) => x.borrow_mut().$ref_mut_op(y),
310                    },
311                    IsCow::Borrowed(x) => match rhs.as_is() {
312                        Is::Owned(y) => x.$ref_op(y),
313                        Is::Borrowed(y) => x.$ref_op(y),
314                        Is::MutBorrowed(y) => x.$ref_op(y),
315                    },
316                }
317            }
318        }
319    };
320}
321
322impl_binop!(Add, add, RefAdd, ref_add, RefMutAdd, ref_mut_add);
323impl_binop!(Sub, sub, RefSub, ref_sub, RefMutSub, ref_mut_sub);
324impl_binop!(Mul, mul, RefMul, ref_mul, RefMutMul, ref_mut_mul);
325impl_binop!(Div, div, RefDiv, ref_div, RefMutDiv, ref_mut_div);
326impl_binop!(Rem, rem, RefRem, ref_rem, RefMutRem, ref_mut_rem);
327impl_binop!(Shl, shl, RefShl, ref_shl, RefMutShl, ref_mut_shl);
328impl_binop!(Shr, shr, RefShr, ref_shr, RefMutShr, ref_mut_shr);
329impl_binop!(
330    BitAnd,
331    bitand,
332    RefBitAnd,
333    ref_bitand,
334    RefMutBitAnd,
335    ref_mut_bitand
336);
337impl_binop!(
338    BitOr,
339    bitor,
340    RefBitOr,
341    ref_bitor,
342    RefMutBitOr,
343    ref_mut_bitor
344);
345impl_binop!(
346    BitXor,
347    bitxor,
348    RefBitXor,
349    ref_bitxor,
350    RefMutBitXor,
351    ref_mut_bitxor
352);