use std::{
borrow::Cow,
ffi::{CStr, CString, OsStr, OsString},
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
};
pub trait Borrow<'a, T: 'a> {
fn borrow(&'a self) -> T;
}
impl<'a, T: ?Sized> Borrow<'a, &'a T> for Box<T> {
#[inline]
fn borrow(&'a self) -> &'a T {
&**self
}
}
impl<'a, T: ?Sized> Borrow<'a, &'a T> for Arc<T> {
#[inline]
fn borrow(&'a self) -> &'a T {
&**self
}
}
impl<'a, T: ?Sized> Borrow<'a, &'a T> for Rc<T> {
#[inline]
fn borrow(&'a self) -> &'a T {
&**self
}
}
impl<'a, T> Borrow<'a, &'a T> for T {
fn borrow(&'a self) -> &'a T {
self
}
}
impl<'a, T, R> Borrow<'a, Cow<'a, R>> for T
where
T: std::borrow::Borrow<R>,
R: ?Sized + ToOwned<Owned = T>,
{
fn borrow(&'a self) -> Cow<R> {
Cow::Borrowed(self.borrow())
}
}
impl<'a> Borrow<'a, &'a str> for String {
#[inline]
fn borrow(&'a self) -> &'a str {
self.as_str()
}
}
impl<'a> Borrow<'a, &'a [u8]> for String {
#[inline]
fn borrow(&'a self) -> &'a [u8] {
self.as_bytes()
}
}
impl<'a> Borrow<'a, &'a Path> for PathBuf {
#[inline]
fn borrow(&self) -> &Path {
self.as_path()
}
}
impl<'a, T> Borrow<'a, &'a [T]> for Vec<T> {
#[inline]
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<'a> Borrow<'a, &'a OsStr> for OsString {
#[inline]
fn borrow(&self) -> &OsStr {
self.as_os_str()
}
}
impl<'a> Borrow<'a, &'a OsStr> for PathBuf {
#[inline]
fn borrow(&self) -> &OsStr {
self.as_os_str()
}
}
impl<'a> Borrow<'a, &'a CStr> for CString {
#[inline]
fn borrow(&self) -> &CStr {
self.as_c_str()
}
}
impl<'a, 'b: 'a, T: ?Sized> Borrow<'a, &'a T> for &'b T {
#[inline]
fn borrow(&'a self) -> &'a T {
*self
}
}
#[cfg(unix)]
mod unix {
use super::*;
use std::os::unix::ffi::OsStrExt;
impl<'a> Borrow<'a, &'a [u8]> for OsString {
#[inline]
fn borrow(&self) -> &[u8] {
self.as_os_str().as_bytes()
}
}
impl<'a> Borrow<'a, &'a [u8]> for PathBuf {
#[inline]
fn borrow(&self) -> &[u8] {
self.as_os_str().as_bytes()
}
}
impl<'a> Take<OsString> for &'a [u8] {
fn to_owned(&self) -> OsString {
OsStr::from_bytes(self).to_os_string()
}
}
impl<'a> Take<PathBuf> for &'a [u8] {
fn to_owned(&self) -> PathBuf {
PathBuf::from(OsStr::from_bytes(self))
}
}
}
pub trait Take<O>: Sized {
fn own(self) -> O {
self.to_owned()
}
fn to_owned(&self) -> O;
}
impl<'a> Take<String> for &'a str {
fn to_owned(&self) -> String {
self.to_string()
}
}
impl<'a> Take<PathBuf> for &'a Path {
fn to_owned(&self) -> PathBuf {
self.to_path_buf()
}
}
impl<'a, T: Clone> Take<Vec<T>> for &'a [T] {
fn to_owned(&self) -> Vec<T> {
self.to_vec()
}
}
impl<'a> Take<OsString> for &'a OsStr {
fn to_owned(&self) -> OsString {
self.to_os_string()
}
}
impl<'a> Take<PathBuf> for &'a OsStr {
fn to_owned(&self) -> PathBuf {
PathBuf::from(self)
}
}
impl<'a, T: Clone> Take<T> for &'a T {
fn to_owned(&self) -> T {
(*self).clone()
}
}
impl<'a> Take<CString> for &'a CStr {
fn to_owned(&self) -> CString {
(*self).to_owned()
}
}
impl<'a, T: Clone> Take<Box<T>> for &'a T {
fn to_owned(&self) -> Box<T> {
Box::new((*self).clone())
}
}
impl<'a, T: Clone> Take<Rc<T>> for &'a T {
fn to_owned(&self) -> Rc<T> {
Rc::new((*self).clone())
}
}
impl<'a, T: Clone> Take<Arc<T>> for &'a T {
fn to_owned(&self) -> Arc<T> {
Arc::new((*self).clone())
}
}
impl<'a, R: ToOwned> Take<R::Owned> for Cow<'a, R> {
fn to_owned(&self) -> R::Owned {
self.clone().into_owned()
}
}
macro_rules!forward_trait{
(@impl@ $to:ty, $fn:ident ( $($decl:tt)* ) -> $out:ty => $wrap:ident($ftrait:ident::$ffn:ident($($use:tt)*)) ) => {
fn $fn( $($decl)* ) -> $out {
$wrap(<Self as $ftrait<$to>>::$ffn( $($use)* ))
}
};
(@fn@ TryInternRef $to:ty) => {
forward_trait!(@impl@ $to, try_intern_ref(&self) -> Option<$to> => Some(InternRef::intern_ref(self)));
};
(@fn@ TryIntern $to:ty) => {
forward_trait!(@impl@ $to, try_intern(self) -> Result<$to, Self> => Ok(Intern::intern(self)));
};
(
$(<
$($g:tt)+
>)?
$trait:ident,
$to:ty,
$from:ty
) => {
impl $(<$($g)+>)? $trait<$to> for $from {
forward_trait!(@fn@ $trait $to);
}
};
}
pub trait TryInternRef<T> {
fn try_intern_ref(&self) -> Option<T>;
}
forward_trait!(TryInternRef, Rc<str>, &'_ str);
forward_trait!(TryInternRef, Arc<str>, &'_ str);
pub trait InternRef<T>: TryInternRef<T> {
fn intern_ref(&self) -> T;
}
impl InternRef<Rc<str>> for &'_ str {
fn intern_ref(&self) -> Rc<str> {
Rc::from(*self)
}
}
impl InternRef<Arc<str>> for &'_ str {
fn intern_ref(&self) -> Arc<str> {
Arc::from(*self)
}
}
pub trait TryIntern<T>: Sized {
fn try_intern(self) -> Result<T, Self>;
}
forward_trait!(TryIntern, Rc<str>, String);
forward_trait!(TryIntern, Arc<str>, String);
pub trait Intern<T> {
fn intern(self) -> T;
}
impl Intern<Rc<str>> for String {
fn intern(self) -> Rc<str> {
Rc::from(self)
}
}
impl Intern<Arc<str>> for String {
fn intern(self) -> Arc<str> {
Arc::from(self)
}
}