static_cow/
lib.rs

1// Copyright © 2023 Daniel Fox Franke
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3
4//! This crate provides a framework of traits for writing types that are generic
5//! over ownership of their contents.
6//!
7//! <div style="max-width: 20em; margin-left: auto; margin-right: auto;">
8//! <img src="https://raw.githubusercontent.com/dfoxfranke/static-cow/10cffdd130d62af2ee0c437bc06500cfe8123417/static-cow/images/mascot.webp" alt="Mascot"/>
9//! </div>
10//!
11//! # API Overview
12//! ## `ToOwning` and `IntoOwning`
13//! [`ToOwning`] and [`IntoOwning`] are the most general traits provided by this
14//! crate, and are the ones that you will implement on your own types.
15//! `ToOwning` is a generalization of [`std::borrow::ToOwned`](ToOwned):
16//!
17//! ```ignore
18//! pub trait ToOwning {
19//!     type Owning;
20//!     fn to_owning(&self) -> Self::Owning;
21//! }
22//! ```
23//!
24//! Unlike `ToOwned`, it doesn't require that `Owning: Borrow<Self>`. Hence
25//! `ToOwning` represents a type that can be converted into some version of
26//! itself which owns its contents,  but which does not necessarily let you get
27//! a reference to the original borrowing type back out from the owning one.
28//!
29//! `ToOwning` has a blanket implementation for `T where T : ToOwned + ?Sized`.
30//! The blanket implementation does the obvious thing of letting `Owning =
31//! Owned` and `to_owning = to_owned`.
32//!
33//! [`IntoOwning`], then is self-explanatory from its declaration:
34//!
35//! ```ignore
36//! pub trait IntoOwning ToOwning + Sized {
37//!     fn into_owning(self) -> Self::Owning;
38//! }
39//! ```
40//!
41//! `IntoOwning` has a blanket implementation for `T where T : Clone`, which
42//! makes `into_owning` the identity function. Therefore, if your type already
43//! implements [`Clone`], you get an `IntoOwning` implementation automatically.
44//! If you implement `IntoOwning` manually, you cannot implement `Clone`.
45//!
46//! User-defined types which implement `ToOwning` and `IntoOwning` generally
47//! should just call `.to_owning()` and `.into_owning()` on each of their
48//! fields. Eventually there will be derive macros for this, but I haven't
49//! written them yet.
50//!
51//! ## `StaticCow`
52//! [`StaticCow`], this crate's namesake, is [`std::borrow::Cow`](Cow) lifted to
53//! the type level. While `Cow` is an enum, `StaticCow` is a trait. While
54//! `Cow::Borrowed` and `Cow::Owned` are enum variants, this crate's
55//! [`Borrowed`] and [`Owned`] are tuple structs which implement `StaticCow` (so
56//! also does `Cow`). So instead of having a struct with a field `field: Cow<'a,
57//! B>`, you can declare that field as `field: S` and let `S` be a generic
58//! parameter `S: StaticCow<B>`. Then, wherever the ownedness of `S` is known at
59//! compile-time, the compiler can generate an appropriately-specialized version
60//! of the function.
61//!
62//! Like `Cow`, `StaticCow` requires `B : ToOwned`, which allows it to have
63//! `Deref<Target=B>` for a supertrait. `IntoOwning` is another supertrait of
64//! `StaticCow`.
65//!
66//! ## `Idempotent`
67//! Using [`Idempotent`] as a bound allows you to be generic over types that
68//! implement [`IntoOwning`] but not [`ToOwned`].
69//!
70//! [`StaticCow`]`<B>` has [`Deref`]`<Target=B>` as a supertrait, so you can do
71//! anything with a `StaticCow<B>` that you can do with a `&B`. However, in
72//! order to provide this supertrait, its implementations require that `B :
73//! ToOwned` so that they can rely on having `B::Owned : Borrow<B>`.
74//!
75//! `Idempotent` has weaker requirements, so its capabilities are necessarily
76//! weaker as well, and it does not inherit from `Deref`. [`ToOwning`]` places
77//! no constraints on `Owning`, which means that as far as the type system is
78//! concerned, `.into_owning()` is just a completely arbitrary conversion. So,
79//! you can't do anything useful with a type that might be `T` or might be
80//! `T::Owning` but you don't know which, because they don't promise to have any
81//! traits in common.
82//!
83//! `Idempotent` puts back just enough information that it can be a useful
84//! bound:
85//!
86//! 1. It can give you either a `T` or a `T::Owning`, *and tells you which*.
87//!
88//! 2. It constrains `T` such that `T::Owning::Owning = T::Owning`. This means
89//! that you can call `into_owning()` on it as many times as you please and it
90//! can *still* give you either a `T` or a `T::Owning`.
91//!
92//! `Idempotent<T>` is implemented by [`Change`]`<T>`, which holds a `T`;
93//! [`Keep`]`<T>`, which holds a `T::Owning`; and by [`ChangeOrKeep`]`<T>` which
94//! might hold either, determined at runtime. Calling `.to_owning()` or
95//! `.into_owning()` on an `Idempotent<T>` always gives a `Keep<T>`.
96//!
97//! # Example
98//! In this example, we'll implement a slice iterator which returns the slice's
99//! elements in reverse. Initially, it'll borrow the slice and clone its
100//! elements when returning them. But, it will implement [`IntoOwning`], so that
101//! at any time during iteration you can change it into an iterator which owns a
102//! [`Vec`](alloc::vec::Vec). It will then pop the elements it returns off the
103//! end of the `Vec`, without cloning them.
104//!
105//! For starters, we'll declare our flexible iterator:
106//! ```ignore
107//! struct FlexIter<S, E> {
108//!     inner: S,
109//!     index: usize,
110//!     _phantom: PhantomData<[E]>,
111//! }
112//! ```
113//!
114//! `E` is the type of the slice's elements. And although the constraint doesn't
115//! appear in the struct declaration, `S` will be an implementation of
116//! `StaticCow<[E]>`. Concretely, `S` will be either `Borrowed<'b, [E]>`, which
117//! wraps a `&'b [E]`, or it will be `Owned<[E]>`, which wraps a `Vec<E>`.
118//! `index` is one greater than the index of the next element we'll return, and
119//! `_phantom` is a zero-sized object which has to be there to satisfy the
120//! typechecker by having the parameter `E` appear somewhere in the struct's
121//! fields.
122//!
123//! Now we'll create [`ToOwning`] and [`IntoOwning`] instances for `FlexIter`.
124//! ```ignore
125//! impl<S, E> ToOwning for FlexIter<S, E>
126//! where
127//!     S: ToOwning,
128//! {
129//!     type Owning = FlexIter<S::Owning, E>;
130//!
131//!     fn to_owning(&self) -> Self::Owning {
132//!         FlexIter {
133//!             inner: self.inner.to_owning(),
134//!             index: self.index.to_owning(),
135//!             _phantom: self._phantom.to_owning()
136//!         }
137//!     }
138//! }
139//!
140//! impl<S, E> IntoOwning for FlexIter<S, E>
141//! where
142//!     S: IntoOwning,
143//! {
144//!     fn into_owning(self) -> Self::Owning {
145//!         FlexIter {
146//!             inner: self.inner.into_owning(),
147//!             index: self.index.into_owning(),
148//!             _phantom: self._phantom.into_owning()
149//!         }
150//!     }
151//! }
152//! ```
153//!
154//! You can see that these implementations are complely rote: we give an
155//! `Owning` type which is the same as `Self` but with `S` replaced by
156//! `S::Owning`, and `to_owning` and `into_owning` methods which simply apply
157//! the same method to each of their fields.
158//!
159//! Now we give a constructor for a borrowing iterator, which realizes
160//! `StaticCow<[E]>` with `Borrowed<'b, [E]>`.
161//!
162//! ```ignore
163//! impl<'b, E> FlexIter<'b, Borrowed<'b, [E]>, E> {
164//!     fn new(slice: &'b [E]) -> FlexIter<'b, Borrowed<'b, [E]>, E> {
165//!         FlexIter {
166//!             inner: Borrowed(slice),
167//!             index: slice.len(),
168//!             _phantom: CowPhantom::default(),
169//!         }
170//!     }
171//! }
172//! ```
173//!
174//! And now we can implement `Iterator`:
175//!
176//! ```ignore
177//! impl<S, E> Iterator for FlexIter<S, E>
178//! where
179//!     E: Clone,
180//!     S: StaticCow<[E]>,
181//! {
182//!     type Item = E;
183
184//!     fn next(&mut self) -> Option<Self::Item> {
185//!         // This is here to show that we can also access `inner` generically
186//!         // through its `Deref<Target=[E]>` implementation, without having to
187//!         // match on `mut_if_owned()`.
188//!         assert!(self.index <= self.inner.len());
189//!
190//!         match self.inner.mut_if_owned() {
191//!             // We're borrowing the slice, so we have to work inefficiently
192//!             // by cloning its elements before we return them.
193//!             MutIfOwned::Const(slice) => {
194//!                 if self.index == 0 {
195//!                     None
196//!                 } else {
197//!                     self.index -= 1;
198//!                     Some(slice[self.index].clone())
199//!                 }
200//!             }
201//!             // We own the slice as a `Vec`, so we can pop elements off of it
202//!             // without cloning.
203//!             MutIfOwned::Mut(vec) => {
204//!                 // It's necessary to make sure we first truncate the vector
205//!                 // to `index`, because we may have already started iterating
206//!                 // before `.into_owned()` was called, and this may be our
207//!                 // first time calling `.next()` since we took ownership. Of
208//!                 // course we could have had our `into_owned` implementation
209//!                 // do this instead of doing it here.
210//!                 vec.truncate(self.index);
211//!                 let ret = vec.pop()?;
212//!                 self.index -= 1;
213//!                 Some(ret)
214//!             }
215//!         }
216//!     }
217//! }
218//! ```
219//!
220//! And now let's see it in action:
221//!
222//! ```ignore
223//! fn main() {
224//!     let numbers = vec![1, 2, 3, 4, 5];
225//!     let mut borrowing_iter = FlexIter::new(numbers.borrow());
226//!
227//!     println!("Borrowing:");
228//!     println!("{}", borrowing_iter.next().unwrap());
229//!     println!("{}", borrowing_iter.next().unwrap());
230//!
231//!     let owning_iter = borrowing_iter.into_owning();
232//!     std::mem::drop(numbers);
233//!
234//!     println!("Owning:");
235//!     for item in owning_iter {
236//!         println!("{}", item);
237//!     }
238//! }
239//! ```
240//!
241//! Running this, we get the expected result:
242//! ```text
243//! Borrowing:
244//! 5
245//! 4
246//! Owning:
247//! 3
248//! 2
249//! 1
250//! ```
251//!
252//! This example is also available as `examples/flex_iter.rs` in the sources of
253//! this crate.
254
255#![warn(missing_docs)]
256#![no_std]
257extern crate alloc;
258use alloc::borrow::{Borrow, BorrowMut, Cow, ToOwned};
259use core::ops::{Deref, DerefMut};
260
261///A generalization of [`ToOwned`].
262///
263/// `ToOwning` is weaker than `ToOwned` because there is no constraint of
264/// `Owning : Borrow<Self>` as there is on `ToOwned::Owned`. Thus, `ToOwning`
265/// represents a type which can be converted from a reference into a related
266/// type that owns its contents, but unlike `ToOwned` doesn't necessarily let
267/// you get a reference to the original type back out.
268///
269/// `ToOwning` has a blanket implementation for `T where T : ToOwned`, wherein
270/// `Owning = Owned` and `to_owning = to_owned`. User-defined types which
271/// implement `ToOwning` but not `ToOwned` typically should do so by calling
272/// `.to_owning()` on all their fields.
273pub trait ToOwning {
274    /// The resulting type after obtaining ownership of `self`'s contents.
275    type Owning;
276    /// Creates an object which owns its contents from one which borrows them.
277    fn to_owning(&self) -> Self::Owning;
278}
279
280impl<B> ToOwning for B
281where
282    B: ToOwned + ?Sized,
283{
284    type Owning = B::Owned;
285
286    #[inline]
287    fn to_owning(&self) -> Self::Owning {
288        self.to_owned()
289    }
290}
291
292/// A trait for types that can be converted into ones which own their contents.
293///
294/// `IntoOwning` has a blanket implementation for `T where T : Clone`, wherein
295/// `into_owning` is the identity function. User-defined types which implement
296/// `IntoOwning` but not [`Clone`] typically should do so by calling
297/// `into_owning()` on all their fields.
298pub trait IntoOwning: ToOwning + Sized {
299    /// Converts an object which owns its contents into one which borrows them.
300    fn into_owning(self) -> Self::Owning;
301}
302
303impl<B> IntoOwning for B
304where
305    B: Clone,
306{
307    #[inline]
308    fn into_owning(self) -> Self::Owning {
309        self
310    }
311}
312
313/// Trait for [`Cow`]-like types whose owned-ness might be known at
314/// compile-time.
315///
316/// [`StaticCow`] is [`std::borrow::Cow`](Cow) lifted to the type level. While
317/// `Cow` is an enum, `StaticCow` is a trait. While `Cow::Borrowed` and
318/// `Cow::Owned` are enum variants, this crate's [`Borrowed`] and [`Owned`] are
319/// tuple structs which implement `StaticCow` (so also does `Cow`). oS instead
320/// of having a struct with a field `field: Cow<'a, B>`, you can declare that
321/// field as `field: S` and let `S` be a generic parameter `S: StaticCow<B>`
322pub trait StaticCow<B>: Deref<Target = B> + IntoOwning
323where
324    B: ToOwned + ?Sized,
325{
326    /// Returns either an immutable reference to an object that is borrowed, or
327    /// a mutable reference to one which is owned.
328    ///
329    /// This method is useful if you are implementing an object that does not
330    /// need to mutate its contents, but can implement optimizations if allowed
331    /// to.
332    ///
333    /// [`Borrowed`]::`mut_if_owned()` always returns `MutIfOwned::Const(_)`,
334    /// [`Owned`]::`mut_if_owned()` always returns `MutIfOwned::Mut(_)`, and
335    /// both of these method implementations are compiled with
336    /// `#[inline(always)]`. Therefore, if you have code that is generic over
337    /// `StaticCow`, there is zero cost to calling `.mut_if_owned()` and
338    /// matching on the result, because the dead branch will reliably be
339    /// optimized out.
340    fn mut_if_owned(&mut self) -> MutIfOwned<'_, B>;
341
342    /// Returns true iff the data is owned, i.e. if `self.into_owning()` would
343    /// be a no-op.
344    fn is_owned(&self) -> bool;
345
346    /// Returns true iff the data is borrowed, i.e. if `self.into_owning()`
347    /// would clone it.
348    fn is_borrowed(&self) -> bool {
349        !self.is_owned()
350    }
351
352    /// Converts `self` into its dynamic equivalent as a [`Cow`].
353    fn into_cow<'a>(self) -> Cow<'a, B>
354    where
355        Self: 'a,
356        Self::Owning: 'a;
357
358    /// Converts `self` into a `B::Owned`, cloning only if necessary.
359    fn into_owned(self) -> B::Owned;
360}
361
362#[derive(Debug, PartialEq, Eq)]
363/// Either an immutable reference to a borrowing object, or a mutable reference to
364/// an owning one.
365///
366/// Returned by [`StaticCow::mut_if_owned`].
367pub enum MutIfOwned<'a, B>
368where
369    B: ToOwned + ?Sized,
370{
371    /// An immutable reference to a borrowing object.
372    Const(&'a B),
373    /// A mutable reference to an owning object.
374    Mut(&'a mut B::Owned),
375}
376
377/// A [`StaticCow`] implementation which wraps an immutable reference.
378#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
379pub struct Borrowed<'b, B: ?Sized>(pub &'b B);
380
381/// A [`StaticCow`] implementation which wraps an owned type.
382#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
383pub struct Owned<B>(pub B::Owning)
384where
385    B: ToOwning + ?Sized;
386
387impl<'b, B: ?Sized> AsRef<B> for Borrowed<'b, B> {
388    fn as_ref(&self) -> &B {
389        self.0
390    }
391}
392
393impl<'b, B: ?Sized> Borrow<B> for Borrowed<'b, B> {
394    fn borrow(&self) -> &B {
395        self.0
396    }
397}
398
399impl<'b, B: ?Sized> Deref for Borrowed<'b, B> {
400    type Target = B;
401
402    #[inline]
403    fn deref(&self) -> &Self::Target {
404        self.0
405    }
406}
407
408impl<'b, B> ToOwning for Borrowed<'b, B>
409where
410    B: ToOwning + ?Sized,
411{
412    type Owning = Owned<B>;
413
414    #[inline]
415    fn to_owning(&self) -> Self::Owning {
416        Owned(self.0.to_owning())
417    }
418}
419
420impl<'b, B> IntoOwning for Borrowed<'b, B>
421where
422    B: ToOwning + ?Sized,
423{
424    #[inline]
425    fn into_owning(self) -> Self::Owning {
426        Owned(self.0.to_owning())
427    }
428}
429
430impl<'b, B> StaticCow<B> for Borrowed<'b, B>
431where
432    B: ToOwned + ?Sized,
433{
434    #[inline]
435    fn is_owned(&self) -> bool {
436        false
437    }
438
439    #[inline(always)]
440    fn mut_if_owned(&mut self) -> MutIfOwned<'_, <Self as Deref>::Target> {
441        MutIfOwned::Const(self.0)
442    }
443    #[inline]
444    fn into_cow<'a>(self) -> Cow<'a, B>
445    where
446        Self: 'a,
447        Self::Owning: 'a,
448    {
449        Cow::Borrowed(self.0)
450    }
451
452    fn into_owned(self) -> B::Owned {
453        self.0.to_owned()
454    }
455}
456
457impl<B> Deref for Owned<B>
458where
459    B: ToOwning + ?Sized,
460    B::Owning: Borrow<B>,
461{
462    type Target = B;
463
464    #[inline]
465    fn deref(&self) -> &Self::Target {
466        self.0.borrow()
467    }
468}
469
470impl<B> DerefMut for Owned<B>
471where
472    B: ToOwning + ?Sized,
473    B::Owning: BorrowMut<B>,
474{
475    #[inline]
476    fn deref_mut(&mut self) -> &mut Self::Target {
477        self.0.borrow_mut()
478    }
479}
480
481impl<B> ToOwning for Owned<B>
482where
483    B: ToOwning + ?Sized,
484    B::Owning: Borrow<B>,
485{
486    type Owning = Self;
487
488    #[inline]
489    fn to_owning(&self) -> Self::Owning {
490        Owned(self.0.borrow().to_owning())
491    }
492}
493
494impl<B> IntoOwning for Owned<B>
495where
496    B: ToOwning + ?Sized,
497    B::Owning: Borrow<B>,
498{
499    #[inline]
500    fn into_owning(self) -> Self::Owning {
501        self
502    }
503}
504
505impl<B> StaticCow<B> for Owned<B>
506where
507    B: ToOwned + ?Sized,
508{
509    #[inline]
510    fn is_owned(&self) -> bool {
511        true
512    }
513
514    #[inline(always)]
515    fn mut_if_owned(&mut self) -> MutIfOwned<'_, B> {
516        MutIfOwned::Mut(&mut self.0)
517    }
518
519    #[inline]
520    fn into_cow<'a>(self) -> Cow<'a, B>
521    where
522        Self: 'a,
523        Self::Owning: 'a,
524    {
525        Cow::Owned(self.0)
526    }
527
528    #[inline]
529    fn into_owned(self) -> <B as ToOwned>::Owned {
530        self.0
531    }
532}
533
534impl<'a, B> StaticCow<B> for Cow<'a, B>
535where
536    B: 'a + ToOwned + ?Sized,
537{
538    #[inline]
539    fn is_owned(&self) -> bool {
540        match self {
541            Cow::Borrowed(_) => false,
542            Cow::Owned(_) => true,
543        }
544    }
545
546    #[inline]
547    fn mut_if_owned(&mut self) -> MutIfOwned<'_, B> {
548        match self {
549            Cow::Borrowed(borrowed) => MutIfOwned::Const(*borrowed),
550            Cow::Owned(owned) => MutIfOwned::Mut(owned),
551        }
552    }
553    #[inline]
554    fn into_cow<'b>(self) -> Cow<'b, B>
555    where
556        Self: 'b,
557    {
558        self
559    }
560
561    #[inline]
562    fn into_owned(self) -> <B as ToOwned>::Owned {
563        self.into_owned()
564    }
565}
566
567/// A trait which guarantees `Self::Owning::Owning = Self::Owning`.
568///
569/// Using `Idempotent` as a bound allows you to be generic over types that
570/// implement [`IntoOwning`] but not [`ToOwned`].
571///
572/// [`StaticCow`]`<B>` has [`Deref`]`<Target=B>` as a supertrait, so you can do
573/// anything with a `StaticCow<B>` that you can do with a `&B`. However, in
574/// order to provide this supertrait, its implementations require that `B :
575/// ToOwned` so that they can rely on having `B::Owned : Borrow<B>`.
576///
577/// `Idempotent` has weaker requirements, so its capabilities are necessarily
578/// weaker as well, and it does not inherit from `Deref`. [`ToOwning`]
579/// places no constraints on `Owning` which means that as far as the type system
580/// is concerned, `.into_owning()` is just a completely arbitrary conversion.
581/// So, you can't do anything useful with a type that might be `T` or might be
582/// `T::Owning` but you don't know which, because they don't promise to have any
583/// traits in common.
584///
585/// `Idempotent` puts back just enough information that it can be a useful
586/// bound:
587///
588/// 1. It can give you either a `T` or a `T::Owning`, *and tells you which*.
589///
590/// 2. It constrains `T` such that `T::Owning::Owning = T::Owning`. This means
591/// that you can call `into_owning()` on it as many times as you please and it
592/// can *still* give you either a `T` or a `T::Owning`.
593///
594/// `Idempotent<T>` is implemented by [`Change`]`<T>`, which holds a `T`;
595/// [`Keep`]`<T>`, which holds a `T::Owning`; and by [`ChangeOrKeep`]`<T>` which
596/// might hold either, determined at runtime. Calling `.to_owning()` or
597/// `.into_owning()` on an `Idempotent<T>` always gives a `Keep<T>`.
598pub trait Idempotent<T>: IntoOwning<Owning = Keep<T>>
599where
600    T: ToOwning,
601    T::Owning: ToOwning<Owning = T::Owning>,
602{
603    /// Get a reference to either a `T` or a `T::Owning`.
604    fn to_ref(&self) -> IdemRef<'_, T>;
605
606    /// Get a mutable reference to either a `T` or a `T::Owning`.
607    fn to_mut(&mut self) -> IdemMut<'_, T>;
608
609    /// Converts `self` into a `T::Owning`; equivalent to `into_owning().0`.
610    #[inline]
611    fn into_kept(self) -> T::Owning {
612        self.into_owning().0
613    }
614}
615
616/// Provides an inmutable reference to either a `T` or a `T::Owning`.
617#[derive(Debug, PartialEq, Eq)]
618pub enum IdemRef<'a, T>
619where
620    T: ToOwning,
621{
622    /// Provides a mutable reference to a `T`.
623    Change(&'a T),
624    /// Provides a mutable reference to a `T::Owning`.
625    Keep(&'a T::Owning),
626}
627
628/// Provides a mutable reference to either a `T` or a `T::Owning`.
629#[derive(Debug, PartialEq, Eq)]
630pub enum IdemMut<'a, T>
631where
632    T: ToOwning,
633{
634    /// Provides a mutable reference to a `T`.
635    Change(&'a mut T),
636    /// Provides a mutable reference to a `T::Owning`.
637    Keep(&'a mut T::Owning),
638}
639
640/// An [`Idempotent`] implementation which wraps a type that is already
641/// `Owning`.
642///
643/// `Keep` has an additional function outside of its use with `Idempotent`,
644/// which is that it implements [`Clone`]. Recall that all types which implement
645/// `Clone` have a blanket implementation of [`IntoOwning`] which is just the
646/// identity function. Contrapositively, therefore, any type with a
647/// *non-trivial* `IntoOwning` implementation cannot implement `Clone`. Usually,
648/// the conversion target of a struct's or enum's `IntoOwning` implementation is
649/// the same struct or enum with different generic parameters. You might wish to
650/// be able to clone such an object after it has already been converted into its
651/// owning form, but this is not possible because it breaks Rust's rules about
652/// conflicting trait implementations. If you already know you have a type that
653/// `IntoOwning` (and therefore implements its supertrait [`ToOwning`]), then you
654/// can work around this by calling `.to_owning()` instead of `.clone()` and
655/// this will do the same thing. However, if you need to pass the object to
656/// something whose generic bounds require a `Clone` implementation, wrapping it
657/// with `Keep` can be a convenient solution.
658#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
659pub struct Keep<T>(pub T::Owning)
660where
661    T: ToOwning;
662
663/// An [`Idempotent`] implementation whose owning-ness is determined at runtime.
664pub enum ChangeOrKeep<T>
665where
666    T: ToOwning,
667{
668    /// A `T` that has not yet been transformed.
669    Change(T),
670    /// A `T::Owning` which has already been transformed from a `T`.
671    Keep(T::Owning),
672}
673
674/// An [`Idempotent`] implementation which wraps a type that may yet be converted to `Owning`.
675pub struct Change<T>(pub T);
676impl<T> Deref for Change<T> {
677    type Target = T;
678
679    #[inline]
680    fn deref(&self) -> &Self::Target {
681        &self.0
682    }
683}
684
685impl<T> DerefMut for Change<T> {
686    #[inline]
687    fn deref_mut(&mut self) -> &mut Self::Target {
688        &mut self.0
689    }
690}
691
692impl<T> ToOwning for Change<T>
693where
694    T: ToOwning,
695{
696    type Owning = Keep<T>;
697
698    fn to_owning(&self) -> Self::Owning {
699        Keep(self.0.to_owning())
700    }
701}
702
703impl<T> IntoOwning for Change<T>
704where
705    T: IntoOwning,
706{
707    fn into_owning(self) -> Self::Owning {
708        Keep(self.0.into_owning())
709    }
710}
711
712impl<T> Idempotent<T> for Change<T>
713where
714    T: IntoOwning,
715    T::Owning: ToOwning<Owning = T::Owning>,
716{
717    #[inline(always)]
718    fn to_ref(&self) -> IdemRef<'_, T> {
719        IdemRef::Change(&self.0)
720    }
721    #[inline(always)]
722    fn to_mut(&mut self) -> IdemMut<'_, T> {
723        IdemMut::Change(&mut self.0)
724    }
725}
726
727impl<T> Deref for Keep<T>
728where
729    T: ToOwning,
730{
731    type Target = T::Owning;
732
733    #[inline]
734    fn deref(&self) -> &Self::Target {
735        &self.0
736    }
737}
738
739impl<T> DerefMut for Keep<T>
740where
741    T: ToOwning,
742{
743    #[inline]
744    fn deref_mut(&mut self) -> &mut Self::Target {
745        &mut self.0
746    }
747}
748
749impl<T> Clone for Keep<T>
750where
751    T: ToOwning,
752    T::Owning: ToOwning<Owning = T::Owning>,
753{
754    #[inline]
755    fn clone(&self) -> Self {
756        Keep(self.0.to_owning())
757    }
758}
759
760impl<T> Idempotent<T> for Keep<T>
761where
762    T: IntoOwning,
763    T::Owning: ToOwning<Owning = T::Owning>,
764{
765    #[inline(always)]
766    fn to_ref(&self) -> IdemRef<'_, T> {
767        IdemRef::Keep(&self.0)
768    }
769
770    #[inline(always)]
771    fn to_mut(&mut self) -> IdemMut<'_, T> {
772        IdemMut::Keep(&mut self.0)
773    }
774}
775
776impl<T> ToOwning for ChangeOrKeep<T>
777where
778    T: ToOwning,
779    T::Owning: ToOwning<Owning = T::Owning>,
780{
781    type Owning = Keep<T>;
782
783    fn to_owning(&self) -> Self::Owning {
784        match self {
785            ChangeOrKeep::Change(o) => Keep(o.to_owning()),
786            ChangeOrKeep::Keep(o) => Keep(o.to_owning()),
787        }
788    }
789}
790
791impl<T> IntoOwning for ChangeOrKeep<T>
792where
793    T: IntoOwning,
794    T::Owning: ToOwning<Owning = T::Owning>,
795{
796    fn into_owning(self) -> Self::Owning {
797        match self {
798            ChangeOrKeep::Change(o) => Keep(o.into_owning()),
799            ChangeOrKeep::Keep(o) => Keep(o),
800        }
801    }
802}
803
804impl<T> Idempotent<T> for ChangeOrKeep<T>
805where
806    T: IntoOwning,
807    T::Owning: ToOwning<Owning = T::Owning>,
808{
809    fn to_ref(&self) -> IdemRef<'_, T> {
810        match self {
811            ChangeOrKeep::Change(o) => IdemRef::Change(o),
812            ChangeOrKeep::Keep(o) => IdemRef::Keep(o),
813        }
814    }
815
816    fn to_mut(&mut self) -> IdemMut<'_, T> {
817        match self {
818            ChangeOrKeep::Change(o) => IdemMut::Change(o),
819            ChangeOrKeep::Keep(o) => IdemMut::Keep(o),
820        }
821    }
822}
823
824/// Constructs a [`Keep`], assisting with type inference.
825///
826/// This function takes an object `o : T` such that `T::Owning = T`, and gives
827/// you back a `Keep<T>`. It is most useful when you have a `T` that implements
828/// `ToOwning<Owning=T>` but not `Clone`, and you need to wrap it in something
829/// that will give you a `Clone` implementation.
830///
831/// You should *not* use this function in the constructor of a type that is
832/// generic over `Idempotent<T>` and give it a `T::Owning`, because that will
833/// result in a `Keep<T::Owning>` when what you want is a `Keep<T>`. In this
834/// context you should use `Keep`'s primitive constructor instead.
835pub fn keep<T>(o: T) -> Keep<T>
836where
837    T: ToOwning<Owning = T>,
838{
839    Keep(o)
840}