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#[derive(Debug)]
18pub enum IsMut<'a, T>
19where
20 T: ?Sized + ToOwned,
21{
22 Owned(T::Owned),
24 MutBorrowed(&'a mut T),
26}
27
28impl<T> Default for IsMut<'_, T>
29where
30 T: ?Sized + ToOwned,
31 T::Owned: Default,
32{
33 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);