as_is/
is.rs

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