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