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}