1cfd8a4d2SNick Fitzgerald use super::*;
2cfd8a4d2SNick Fitzgerald use core::{cmp, fmt, hash, ops::Deref};
3cfd8a4d2SNick Fitzgerald use std_alloc::borrow::Borrow;
4cfd8a4d2SNick Fitzgerald 
5cfd8a4d2SNick Fitzgerald /// Like [`std::borrow::ToOwned`] but returns an [`OutOfMemory`] error on
6cfd8a4d2SNick Fitzgerald /// allocation failure.
7cfd8a4d2SNick Fitzgerald pub trait TryToOwned {
8cfd8a4d2SNick Fitzgerald     /// The owned version of this type.
9cfd8a4d2SNick Fitzgerald     type Owned: Borrow<Self>;
10cfd8a4d2SNick Fitzgerald 
11cfd8a4d2SNick Fitzgerald     /// Try to allocate an owned version of `self`.
try_to_owned(&self) -> Result<Self::Owned, OutOfMemory>12cfd8a4d2SNick Fitzgerald     fn try_to_owned(&self) -> Result<Self::Owned, OutOfMemory>;
13cfd8a4d2SNick Fitzgerald }
14cfd8a4d2SNick Fitzgerald 
15cfd8a4d2SNick Fitzgerald impl TryToOwned for str {
16d8e213f7SNick Fitzgerald     type Owned = TryString;
17cfd8a4d2SNick Fitzgerald 
try_to_owned(&self) -> Result<Self::Owned, OutOfMemory>18cfd8a4d2SNick Fitzgerald     fn try_to_owned(&self) -> Result<Self::Owned, OutOfMemory> {
19d8e213f7SNick Fitzgerald         let mut s = TryString::new();
20cfd8a4d2SNick Fitzgerald         s.push_str(self)?;
21cfd8a4d2SNick Fitzgerald         Ok(s)
22cfd8a4d2SNick Fitzgerald     }
23cfd8a4d2SNick Fitzgerald }
24cfd8a4d2SNick Fitzgerald 
25cfd8a4d2SNick Fitzgerald impl<T> TryToOwned for [T]
26cfd8a4d2SNick Fitzgerald where
27cfd8a4d2SNick Fitzgerald     T: TryClone,
28cfd8a4d2SNick Fitzgerald {
29*183891f0SNick Fitzgerald     type Owned = TryVec<T>;
30cfd8a4d2SNick Fitzgerald 
try_to_owned(&self) -> Result<Self::Owned, OutOfMemory>31cfd8a4d2SNick Fitzgerald     fn try_to_owned(&self) -> Result<Self::Owned, OutOfMemory> {
32*183891f0SNick Fitzgerald         let mut v = TryVec::with_capacity(self.len())?;
33cfd8a4d2SNick Fitzgerald         for x in self {
34cfd8a4d2SNick Fitzgerald             v.push(x.try_clone()?)?;
35cfd8a4d2SNick Fitzgerald         }
36cfd8a4d2SNick Fitzgerald         Ok(v)
37cfd8a4d2SNick Fitzgerald     }
38cfd8a4d2SNick Fitzgerald }
39cfd8a4d2SNick Fitzgerald 
40cfd8a4d2SNick Fitzgerald impl<T> TryToOwned for T
41cfd8a4d2SNick Fitzgerald where
42cfd8a4d2SNick Fitzgerald     T: TryClone,
43cfd8a4d2SNick Fitzgerald {
44cfd8a4d2SNick Fitzgerald     type Owned = Self;
45cfd8a4d2SNick Fitzgerald 
try_to_owned(&self) -> Result<Self::Owned, OutOfMemory>46cfd8a4d2SNick Fitzgerald     fn try_to_owned(&self) -> Result<Self::Owned, OutOfMemory> {
47cfd8a4d2SNick Fitzgerald         self.try_clone()
48cfd8a4d2SNick Fitzgerald     }
49cfd8a4d2SNick Fitzgerald }
50cfd8a4d2SNick Fitzgerald 
51cfd8a4d2SNick Fitzgerald /// Like [`std::borrow::Cow`] but returns [`OutOfMemory`] errors for various
52cfd8a4d2SNick Fitzgerald /// APIs that force allocation of an owned copy.
53cfd8a4d2SNick Fitzgerald pub enum TryCow<'a, B>
54cfd8a4d2SNick Fitzgerald where
55cfd8a4d2SNick Fitzgerald     B: 'a + TryToOwned + ?Sized,
56cfd8a4d2SNick Fitzgerald {
57cfd8a4d2SNick Fitzgerald     /// Borrowed data.
58cfd8a4d2SNick Fitzgerald     Borrowed(&'a B),
59cfd8a4d2SNick Fitzgerald 
60cfd8a4d2SNick Fitzgerald     /// Owned data.
61cfd8a4d2SNick Fitzgerald     Owned(<B as TryToOwned>::Owned),
62cfd8a4d2SNick Fitzgerald }
63cfd8a4d2SNick Fitzgerald 
64cfd8a4d2SNick Fitzgerald impl<'a, B> From<&'a B> for TryCow<'a, B>
65cfd8a4d2SNick Fitzgerald where
66cfd8a4d2SNick Fitzgerald     B: 'a + ?Sized + TryToOwned,
67cfd8a4d2SNick Fitzgerald {
from(b: &'a B) -> Self68cfd8a4d2SNick Fitzgerald     fn from(b: &'a B) -> Self {
69cfd8a4d2SNick Fitzgerald         Self::Borrowed(b)
70cfd8a4d2SNick Fitzgerald     }
71cfd8a4d2SNick Fitzgerald }
72cfd8a4d2SNick Fitzgerald 
73cfd8a4d2SNick Fitzgerald impl<B> Default for TryCow<'_, B>
74cfd8a4d2SNick Fitzgerald where
75cfd8a4d2SNick Fitzgerald     B: ?Sized + TryToOwned<Owned: Default>,
76cfd8a4d2SNick Fitzgerald {
default() -> Self77cfd8a4d2SNick Fitzgerald     fn default() -> Self {
78cfd8a4d2SNick Fitzgerald         Self::Owned(<B as TryToOwned>::Owned::default())
79cfd8a4d2SNick Fitzgerald     }
80cfd8a4d2SNick Fitzgerald }
81cfd8a4d2SNick Fitzgerald 
82cfd8a4d2SNick Fitzgerald impl<B> fmt::Debug for TryCow<'_, B>
83cfd8a4d2SNick Fitzgerald where
84cfd8a4d2SNick Fitzgerald     B: ?Sized + fmt::Debug + TryToOwned<Owned: fmt::Debug>,
85cfd8a4d2SNick Fitzgerald {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result86cfd8a4d2SNick Fitzgerald     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87cfd8a4d2SNick Fitzgerald         match self {
88cfd8a4d2SNick Fitzgerald             Self::Borrowed(b) => fmt::Debug::fmt(b, f),
89cfd8a4d2SNick Fitzgerald             Self::Owned(o) => fmt::Debug::fmt(o, f),
90cfd8a4d2SNick Fitzgerald         }
91cfd8a4d2SNick Fitzgerald     }
92cfd8a4d2SNick Fitzgerald }
93cfd8a4d2SNick Fitzgerald 
94cfd8a4d2SNick Fitzgerald impl<B> TryClone for TryCow<'_, B>
95cfd8a4d2SNick Fitzgerald where
96cfd8a4d2SNick Fitzgerald     B: ?Sized + TryToOwned,
97cfd8a4d2SNick Fitzgerald {
try_clone(&self) -> Result<Self, OutOfMemory>98cfd8a4d2SNick Fitzgerald     fn try_clone(&self) -> Result<Self, OutOfMemory> {
99cfd8a4d2SNick Fitzgerald         match self {
100cfd8a4d2SNick Fitzgerald             Self::Borrowed(b) => Ok(Self::Borrowed(b)),
101cfd8a4d2SNick Fitzgerald             Self::Owned(o) => {
102cfd8a4d2SNick Fitzgerald                 let b: &B = o.borrow();
103cfd8a4d2SNick Fitzgerald                 Ok(Self::Owned(b.try_to_owned()?))
104cfd8a4d2SNick Fitzgerald             }
105cfd8a4d2SNick Fitzgerald         }
106cfd8a4d2SNick Fitzgerald     }
107cfd8a4d2SNick Fitzgerald }
108cfd8a4d2SNick Fitzgerald 
109cfd8a4d2SNick Fitzgerald impl<B> Deref for TryCow<'_, B>
110cfd8a4d2SNick Fitzgerald where
111cfd8a4d2SNick Fitzgerald     B: ?Sized + TryToOwned,
112cfd8a4d2SNick Fitzgerald {
113cfd8a4d2SNick Fitzgerald     type Target = B;
114cfd8a4d2SNick Fitzgerald 
deref(&self) -> &B115cfd8a4d2SNick Fitzgerald     fn deref(&self) -> &B {
116cfd8a4d2SNick Fitzgerald         match self {
117cfd8a4d2SNick Fitzgerald             Self::Borrowed(b) => b,
118cfd8a4d2SNick Fitzgerald             Self::Owned(o) => o.borrow(),
119cfd8a4d2SNick Fitzgerald         }
120cfd8a4d2SNick Fitzgerald     }
121cfd8a4d2SNick Fitzgerald }
122cfd8a4d2SNick Fitzgerald 
123cfd8a4d2SNick Fitzgerald impl<B> AsRef<B> for TryCow<'_, B>
124cfd8a4d2SNick Fitzgerald where
125cfd8a4d2SNick Fitzgerald     B: ?Sized + TryToOwned,
126cfd8a4d2SNick Fitzgerald {
as_ref(&self) -> &B127cfd8a4d2SNick Fitzgerald     fn as_ref(&self) -> &B {
128cfd8a4d2SNick Fitzgerald         self
129cfd8a4d2SNick Fitzgerald     }
130cfd8a4d2SNick Fitzgerald }
131cfd8a4d2SNick Fitzgerald 
132cfd8a4d2SNick Fitzgerald impl<'a, B> Borrow<B> for TryCow<'a, B>
133cfd8a4d2SNick Fitzgerald where
134cfd8a4d2SNick Fitzgerald     B: ?Sized + TryToOwned,
135cfd8a4d2SNick Fitzgerald {
borrow(&self) -> &B136cfd8a4d2SNick Fitzgerald     fn borrow(&self) -> &B {
137cfd8a4d2SNick Fitzgerald         &**self
138cfd8a4d2SNick Fitzgerald     }
139cfd8a4d2SNick Fitzgerald }
140cfd8a4d2SNick Fitzgerald 
141cfd8a4d2SNick Fitzgerald impl<B> hash::Hash for TryCow<'_, B>
142cfd8a4d2SNick Fitzgerald where
143cfd8a4d2SNick Fitzgerald     B: ?Sized + hash::Hash + TryToOwned,
144cfd8a4d2SNick Fitzgerald {
hash<H>(&self, state: &mut H) where H: hash::Hasher,145cfd8a4d2SNick Fitzgerald     fn hash<H>(&self, state: &mut H)
146cfd8a4d2SNick Fitzgerald     where
147cfd8a4d2SNick Fitzgerald         H: hash::Hasher,
148cfd8a4d2SNick Fitzgerald     {
149cfd8a4d2SNick Fitzgerald         hash::Hash::hash(&**self, state)
150cfd8a4d2SNick Fitzgerald     }
151cfd8a4d2SNick Fitzgerald }
152cfd8a4d2SNick Fitzgerald 
153cfd8a4d2SNick Fitzgerald impl<B> PartialEq for TryCow<'_, B>
154cfd8a4d2SNick Fitzgerald where
155cfd8a4d2SNick Fitzgerald     B: ?Sized + PartialEq + TryToOwned,
156cfd8a4d2SNick Fitzgerald {
eq(&self, other: &Self) -> bool157cfd8a4d2SNick Fitzgerald     fn eq(&self, other: &Self) -> bool {
158cfd8a4d2SNick Fitzgerald         PartialEq::eq(&**self, &**other)
159cfd8a4d2SNick Fitzgerald     }
160cfd8a4d2SNick Fitzgerald }
161cfd8a4d2SNick Fitzgerald 
162cfd8a4d2SNick Fitzgerald impl<B> Eq for TryCow<'_, B> where B: ?Sized + Eq + TryToOwned {}
163cfd8a4d2SNick Fitzgerald 
164cfd8a4d2SNick Fitzgerald impl<B> PartialOrd for TryCow<'_, B>
165cfd8a4d2SNick Fitzgerald where
166cfd8a4d2SNick Fitzgerald     B: ?Sized + PartialOrd + TryToOwned,
167cfd8a4d2SNick Fitzgerald {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>168cfd8a4d2SNick Fitzgerald     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
169cfd8a4d2SNick Fitzgerald         PartialOrd::partial_cmp(&**self, &**other)
170cfd8a4d2SNick Fitzgerald     }
171cfd8a4d2SNick Fitzgerald }
172cfd8a4d2SNick Fitzgerald 
173cfd8a4d2SNick Fitzgerald impl<B> Ord for TryCow<'_, B>
174cfd8a4d2SNick Fitzgerald where
175cfd8a4d2SNick Fitzgerald     B: ?Sized + Ord + TryToOwned,
176cfd8a4d2SNick Fitzgerald {
cmp(&self, other: &Self) -> cmp::Ordering177cfd8a4d2SNick Fitzgerald     fn cmp(&self, other: &Self) -> cmp::Ordering {
178cfd8a4d2SNick Fitzgerald         Ord::cmp(&**self, &**other)
179cfd8a4d2SNick Fitzgerald     }
180cfd8a4d2SNick Fitzgerald }
181cfd8a4d2SNick Fitzgerald 
182cfd8a4d2SNick Fitzgerald impl<'a, B> TryCow<'a, B>
183cfd8a4d2SNick Fitzgerald where
184cfd8a4d2SNick Fitzgerald     B: TryToOwned + ?Sized,
185cfd8a4d2SNick Fitzgerald {
186cfd8a4d2SNick Fitzgerald     /// Same as [`std::borrow::Cow::to_mut`] but returns an [`OutOfMemory`]
187cfd8a4d2SNick Fitzgerald     /// error on allocation failure.
to_mut(&mut self) -> Result<&mut <B as TryToOwned>::Owned, OutOfMemory>188cfd8a4d2SNick Fitzgerald     pub fn to_mut(&mut self) -> Result<&mut <B as TryToOwned>::Owned, OutOfMemory> {
189cfd8a4d2SNick Fitzgerald         if let Self::Borrowed(b) = self {
190cfd8a4d2SNick Fitzgerald             *self = Self::Owned(b.try_to_owned()?);
191cfd8a4d2SNick Fitzgerald         }
192cfd8a4d2SNick Fitzgerald         match self {
193cfd8a4d2SNick Fitzgerald             TryCow::Owned(x) => Ok(x),
194cfd8a4d2SNick Fitzgerald             TryCow::Borrowed(_) => unreachable!(),
195cfd8a4d2SNick Fitzgerald         }
196cfd8a4d2SNick Fitzgerald     }
197cfd8a4d2SNick Fitzgerald 
198cfd8a4d2SNick Fitzgerald     /// Same as [`std::borrow::Cow::into_owned`] but returns an [`OutOfMemory`]
199cfd8a4d2SNick Fitzgerald     /// error on allocation failure.
into_owned(self) -> Result<<B as TryToOwned>::Owned, OutOfMemory>200cfd8a4d2SNick Fitzgerald     pub fn into_owned(self) -> Result<<B as TryToOwned>::Owned, OutOfMemory> {
201cfd8a4d2SNick Fitzgerald         match self {
202cfd8a4d2SNick Fitzgerald             TryCow::Borrowed(b) => b.try_to_owned(),
203cfd8a4d2SNick Fitzgerald             TryCow::Owned(x) => Ok(x),
204cfd8a4d2SNick Fitzgerald         }
205cfd8a4d2SNick Fitzgerald     }
206cfd8a4d2SNick Fitzgerald }
207cfd8a4d2SNick Fitzgerald 
208cfd8a4d2SNick Fitzgerald #[cfg(test)]
209cfd8a4d2SNick Fitzgerald mod tests {
210cfd8a4d2SNick Fitzgerald     use super::*;
211cfd8a4d2SNick Fitzgerald     use crate::error::Result;
212cfd8a4d2SNick Fitzgerald 
213cfd8a4d2SNick Fitzgerald     #[test]
to_mut() -> Result<()>214cfd8a4d2SNick Fitzgerald     fn to_mut() -> Result<()> {
215cfd8a4d2SNick Fitzgerald         let mut s = TryCow::Borrowed("hello");
216cfd8a4d2SNick Fitzgerald         s.to_mut()?.push_str(", world!")?;
217cfd8a4d2SNick Fitzgerald         assert!(matches!(s, TryCow::Owned(_)));
218cfd8a4d2SNick Fitzgerald         assert_eq!(&*s, "hello, world!");
219cfd8a4d2SNick Fitzgerald         Ok(())
220cfd8a4d2SNick Fitzgerald     }
221cfd8a4d2SNick Fitzgerald 
222cfd8a4d2SNick Fitzgerald     #[test]
into_owned() -> Result<()>223cfd8a4d2SNick Fitzgerald     fn into_owned() -> Result<()> {
224cfd8a4d2SNick Fitzgerald         let v = TryCow::Borrowed(&[42u8, 36][..]);
225*183891f0SNick Fitzgerald         let v: TryVec<u8> = v.into_owned()?;
226cfd8a4d2SNick Fitzgerald         assert_eq!(&*v, &[42, 36]);
227cfd8a4d2SNick Fitzgerald         Ok(())
228cfd8a4d2SNick Fitzgerald     }
229cfd8a4d2SNick Fitzgerald }
230