#![warn(missing_docs)]
use std::borrow::{Borrow, Cow};
use std::cmp;
use std::fmt;
use std::hash;
use std::ops::Deref;
#[repr(transparent)]
pub struct Owned<B>(pub <B as ToOwned>::Owned)
where
B: ?Sized + ToOwned;
impl<B> Clone for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: Clone,
{
fn clone(&self) -> Self {
Self(self.0.clone())
}
fn clone_from(&mut self, source: &Self) {
self.0 = source.0.clone();
}
}
impl<B> Default for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: Default,
{
fn default() -> Self {
Self(Default::default())
}
}
impl<B, C> PartialEq<Owned<C>> for Owned<B>
where
B: ?Sized + ToOwned,
C: ?Sized + ToOwned,
<B as ToOwned>::Owned: PartialEq<<C as ToOwned>::Owned>,
{
fn eq(&self, other: &Owned<C>) -> bool {
self.0.eq(&other.0)
}
fn ne(&self, other: &Owned<C>) -> bool {
self.0.ne(&other.0)
}
}
impl<B> Eq for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: Eq,
{
}
impl<B, C> cmp::PartialOrd<Owned<C>> for Owned<B>
where
B: ?Sized + ToOwned,
C: ?Sized + ToOwned,
<B as ToOwned>::Owned: cmp::PartialOrd<<C as ToOwned>::Owned>,
{
fn partial_cmp(&self, other: &Owned<C>) -> Option<cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
fn lt(&self, other: &Owned<C>) -> bool {
self.0.lt(&other.0)
}
fn le(&self, other: &Owned<C>) -> bool {
self.0.le(&other.0)
}
fn gt(&self, other: &Owned<C>) -> bool {
self.0.gt(&other.0)
}
fn ge(&self, other: &Owned<C>) -> bool {
self.0.ge(&other.0)
}
}
impl<B> cmp::Ord for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: cmp::Ord,
{
fn cmp(&self, other: &Owned<B>) -> cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<B> hash::Hash for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: hash::Hash,
{
fn hash<H>(&self, state: &mut H)
where
H: hash::Hasher,
{
self.0.hash(state)
}
}
impl<B> Deref for Owned<B>
where
B: ?Sized + ToOwned,
{
type Target = B;
fn deref(&self) -> &B {
self.0.borrow()
}
}
impl<B> Borrow<B> for Owned<B>
where
B: ?Sized + ToOwned,
{
fn borrow(&self) -> &B {
self.0.borrow()
}
}
impl<B, U> AsRef<U> for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: AsRef<U>,
U: ?Sized,
{
fn as_ref(&self) -> &U {
self.0.as_ref()
}
}
impl<B: fmt::Display> fmt::Display for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl<B: fmt::Debug> fmt::Debug for Owned<B>
where
B: ?Sized + ToOwned,
<B as ToOwned>::Owned: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
pub trait GenericCow
where
Self: Sized,
Self: Borrow<Self::Borrowed>,
Self: Deref<Target = Self::Borrowed>,
{
type Borrowed: ?Sized + ToOwned;
fn into_owned(self) -> <Self::Borrowed as ToOwned>::Owned;
}
impl<'a, B> GenericCow for &'a B
where
B: ?Sized + ToOwned,
{
type Borrowed = B;
fn into_owned(self) -> <B as ToOwned>::Owned {
self.to_owned()
}
}
impl<'a, B> GenericCow for Cow<'a, B>
where
B: ?Sized + ToOwned,
{
type Borrowed = B;
fn into_owned(self) -> <B as ToOwned>::Owned {
Cow::into_owned(self)
}
}
impl<B> GenericCow for Owned<B>
where
B: ?Sized + ToOwned,
{
type Borrowed = B;
fn into_owned(self) -> <B as ToOwned>::Owned {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::borrow::Cow;
#[test]
fn test_owned() {
let wrapped: Owned<str> = Owned("Alpha".to_string());
let reference: &str = &*wrapped;
assert_eq!(reference, "Alpha");
let owned: String = wrapped.into_owned();
assert_eq!(owned, "Alpha".to_string());
}
#[test]
fn test_cow() {
let cow_owned: Cow<'static, str> = Cow::Owned("Bravo".to_string());
assert_eq!(GenericCow::into_owned(cow_owned), "Bravo".to_string());
let cow_borrowed: Cow<'static, str> = Cow::Borrowed("Charlie");
assert_eq!(GenericCow::into_owned(cow_borrowed), "Charlie".to_string());
}
#[test]
fn test_ref() {
let reference: &str = "Delta";
assert_eq!(GenericCow::into_owned(reference), "Delta".to_string());
}
#[test]
fn test_vec() {
let wrapped: Owned<[i32]> = Owned(vec![1, 2, 3]);
assert_eq!(&*wrapped, &[1, 2, 3] as &[i32]);
assert_eq!(wrapped.into_owned(), vec![1, 2, 3]);
}
#[test]
fn test_generic_fn() {
fn generic_fn(arg: impl GenericCow<Borrowed = str>) {
let reference1: &str = &*arg;
assert_eq!(reference1, "Echo");
let reference2: &str = arg.borrow();
assert_eq!(reference2, "Echo");
let owned: String = arg.into_owned();
assert_eq!(owned, "Echo".to_string());
}
generic_fn(Owned("Echo".to_string()));
generic_fn(Cow::Owned("Echo".to_string()));
generic_fn(Cow::Borrowed("Echo"));
generic_fn("Echo");
}
#[test]
fn test_vec_borrow() {
let wrapped: Owned<[i32]> = Owned(vec![2, 7, 4]);
let slice_ref: &[i32] = wrapped.borrow();
assert_eq!(slice_ref, &[2, 7, 4] as &[i32]);
}
#[test]
fn test_int_borrow() {
let wrapped: Owned<i32> = Owned(5);
let reference: &i32 = wrapped.borrow();
assert_eq!(reference, &5);
}
}