use std::borrow::Cow;
use std::ops::Deref;
fn as_deref_cow<T>(input: Cow<T>) -> Cow<<T as Deref>::Target>
where
T: Deref + ToOwned,
<T as Deref>::Target: ToOwned,
<<T as Deref>::Target as ToOwned>::Owned: From<<T as ToOwned>::Owned>,
{
match input {
Cow::Borrowed(input) => Cow::Borrowed(input.deref()),
Cow::Owned(input) => Cow::Owned(input.into()),
}
}
pub trait AsDerefCow<'cow, T>
where
T: Deref,
<T as Deref>::Target: ToOwned,
{
fn as_deref(self) -> Cow<'cow, <T as Deref>::Target>;
}
impl<'cow, T> AsDerefCow<'cow, T> for Cow<'cow, T>
where
T: Deref + ToOwned,
<T as Deref>::Target: ToOwned,
<<T as Deref>::Target as ToOwned>::Owned: From<<T as ToOwned>::Owned>,
{
fn as_deref(self) -> Cow<'cow, <T as Deref>::Target> {
as_deref_cow(self)
}
}
#[cfg(test)]
mod flatten_fn {
use super::*;
#[test]
fn as_deref_cow_string_owned() {
let input: Cow<String> = Cow::Owned(String::from("foo"));
let output: Cow<str> = as_deref_cow(input);
assert!(matches!(output, Cow::Owned(_)));
assert_eq!(output, "foo");
}
#[test]
fn as_deref_cow_string_borrowed() {
let tmp = String::from("bar");
let input: Cow<String> = Cow::Borrowed(&tmp);
let output: Cow<str> = as_deref_cow(input);
assert!(matches!(output, Cow::Borrowed(_)));
assert_eq!(output, "bar");
}
#[test]
fn as_deref_cow_box_str_owned() {
let input: Cow<Box<str>> = Cow::Owned(Box::from("foo"));
let output: Cow<str> = as_deref_cow(input);
assert!(matches!(output, Cow::Owned(_)));
assert_eq!(output, "foo");
}
#[test]
fn as_deref_cow_box_str_borrowed() {
let tmp = Box::from("bar");
let input: Cow<Box<str>> = Cow::Borrowed(&tmp);
let output: Cow<str> = as_deref_cow(input);
assert!(matches!(output, Cow::Borrowed(_)));
assert_eq!(output, "bar");
}
}