use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList};
use std::ffi::{CStr, CString, OsStr, OsString};
use std::hash::Hash;
use std::path::{Path, PathBuf};
use crate::Borrow;
impl Borrow for String {
type Target<'a> = &'a str;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
self.as_str()
}
}
impl<B> Borrow for Cow<'static, B>
where
B: ?Sized + std::borrow::ToOwned,
{
type Target<'a> = Cow<'a, B>;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
Cow::Borrowed(self)
}
}
macro_rules! deref {
($from:ty, $to:ty) => {
impl Borrow for $from {
type Target<'a> = &'a $to where Self: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
self
}
}
};
}
deref!(PathBuf, Path);
deref!(OsString, OsStr);
deref!(CString, CStr);
impl<T: ?Sized> Borrow for Box<T> {
type Target<'a> = &'a T where T: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
self
}
}
macro_rules! seq {
(cap $seq:ident, $insert:ident $(, $trait:path)* $(,)?) => {
impl<T> Borrow for $seq<T>
where
T: Borrow,
$(for<'a> T::Target<'a>: $trait,)*
{
type Target<'a> = $seq<T::Target<'a>> where T: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
let mut out = <$seq<_>>::with_capacity(self.len());
for value in self {
out.$insert(value.borrow());
}
out
}
}
};
($seq:ident, $insert:ident $(, $trait:path)* $(,)?) => {
impl<T> Borrow for $seq<T>
where
T: Borrow,
$(for<'a> T::Target<'a>: $trait,)*
{
type Target<'a> = $seq<T::Target<'a>> where T: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
let mut out = <$seq<_>>::new();
for value in self {
out.$insert(value.borrow());
}
out
}
}
};
}
macro_rules! map {
(cap $map:ident, $insert:ident $(, $trait:path)* $(,)?) => {
impl<K, V> Borrow for $map<K, V>
where
K: Borrow,
V: Borrow,
$(for<'a> K::Target<'a>: $trait,)*
{
type Target<'a> = $map<K::Target<'a>, V::Target<'a>> where K: 'a, V: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
let mut out = <$map<_, _>>::with_capacity(self.len());
for (key, value) in self {
out.$insert(key.borrow(), value.borrow());
}
out
}
}
};
($map:ident, $insert:ident $(, $trait:path)* $(,)?) => {
impl<K, V> Borrow for $map<K, V>
where
K: Borrow,
V: Borrow,
$(for<'a> K::Target<'a>: $trait,)*
{
type Target<'a> = $map<K::Target<'a>, V::Target<'a>> where K: 'a, V: 'a;
#[inline]
fn borrow(&self) -> Self::Target<'_> {
let mut out = <$map<_, _>>::new();
for (key, value) in self {
out.$insert(key.borrow(), value.borrow());
}
out
}
}
};
}
seq!(cap Vec, push);
seq!(cap HashSet, insert, Hash, Eq);
seq!(BTreeSet, insert, PartialOrd, Ord, Eq);
seq!(LinkedList, push_back);
map!(cap HashMap, insert, Hash, Eq);
map!(BTreeMap, insert, PartialOrd, Ord, Eq);