as_is/
is_mut.rs

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