kutil_std/borrow/
calf.rs

1use std::borrow::*;
2
3//
4// Calf
5//
6
7/// A read-only container for either an owned value or a reference to one.
8///
9/// Similar to [Cow], but does not support [ToOwned] (and does not require your
10/// value to support it), nor does it support [BorrowMut].
11///
12/// It's a baby cow!
13///
14/// Note that after coming up with the idea for this, I discovered that someone
15/// else did, too. Check out [maybe-owned](https://github.com/rustonaut/maybe-owned)
16/// for an identical type that comes with a zillion more trait implementations.
17pub enum Calf<'own, BorrowedT> {
18    /// Borrowed.
19    Borrowed(&'own BorrowedT),
20
21    /// Owned.
22    Owned(BorrowedT),
23}
24
25impl<'own, BorrowedT> Calf<'own, BorrowedT> {
26    /// Are we borrowed?
27    pub fn is_borrowed(&self) -> bool {
28        match self {
29            Self::Borrowed(_) => true,
30            Self::Owned(_) => false,
31        }
32    }
33
34    /// Are we owned?
35    pub fn is_owned(&self) -> bool {
36        match self {
37            Self::Borrowed(_) => false,
38            Self::Owned(_) => true,
39        }
40    }
41}
42
43impl<'own, BorrowedT> Borrow<BorrowedT> for Calf<'own, BorrowedT> {
44    fn borrow(&self) -> &BorrowedT {
45        match self {
46            Self::Owned(owned) => owned,
47            Self::Borrowed(borrowed) => *borrowed,
48        }
49    }
50}
51
52// Experimental
53
54impl<'own, BorrowedT, OwnedT> Calf<'own, BorrowedT>
55where
56    BorrowedT: ToOwned<Owned = OwnedT>,
57{
58    /// Into owned.
59    pub fn into_owned(self) -> <BorrowedT as ToOwned>::Owned {
60        match self {
61            Self::Owned(owned) => owned.to_owned(),
62            Self::Borrowed(borrowed) => borrowed.to_owned(),
63        }
64    }
65}
66
67impl<'own, BorrowedT> BorrowMut<BorrowedT> for Calf<'own, BorrowedT>
68where
69    &'own BorrowedT: AsMut<&'own mut BorrowedT>,
70{
71    fn borrow_mut(&mut self) -> &mut BorrowedT {
72        match self {
73            Self::Owned(owned) => owned,
74            Self::Borrowed(borrowed) => borrowed.as_mut(),
75        }
76    }
77}
78
79impl<'own, BorrowedT, OwnedT> ToOwned for Calf<'own, BorrowedT>
80where
81    BorrowedT: ToOwned<Owned = OwnedT>,
82    OwnedT: Borrow<Self>,
83{
84    type Owned = OwnedT;
85
86    fn to_owned(&self) -> OwnedT {
87        match self {
88            Self::Owned(owned) => owned.to_owned(),
89            Self::Borrowed(borrowed) => (*borrowed).to_owned(),
90        }
91    }
92}
93
94// Conversions
95
96impl<'own, BorrowedT> From<Cow<'own, BorrowedT>> for Calf<'own, BorrowedT>
97where
98    BorrowedT: ToOwned<Owned = BorrowedT>,
99{
100    fn from(cow: Cow<'own, BorrowedT>) -> Self {
101        match cow {
102            Cow::Owned(owned) => Calf::Owned(owned),
103            Cow::Borrowed(borrowed) => Calf::Borrowed(borrowed),
104        }
105    }
106}
107
108impl<'own, BorrowedT> Into<Cow<'own, BorrowedT>> for Calf<'own, BorrowedT>
109where
110    BorrowedT: ToOwned<Owned = BorrowedT>,
111{
112    fn into(self) -> Cow<'own, BorrowedT> {
113        match self {
114            Self::Owned(owned) => Cow::Owned(owned),
115            Self::Borrowed(borrowed) => Cow::Borrowed(borrowed),
116        }
117    }
118}