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