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