use std::{
borrow::{Borrow, BorrowMut, Cow},
cmp::Ordering,
ffi::{CStr, CString, OsStr, OsString},
fmt,
hash::Hash,
ops::{Add, AddAssign, Deref},
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
};
#[non_exhaustive]
pub enum Bos<'b, B, O = B, S = O>
where
B: 'static + ?Sized,
O: 'static,
S: 'static + ?Sized,
{
#[cfg(feature = "unstable")] Static(&'static B),
Borrowed(&'b B),
Owned(O),
BorrowedArc(&'b Arc<S>),
Arc(Arc<S>),
BorrowedRc(&'b Rc<S>),
Rc(Rc<S>),
}
impl<'b, B: ?Sized, O, S: ?Sized> Bos<'b, B, O, S> {
#[inline]
pub fn into_owned(self) -> O
where
B: ToOwned<Owned = O>,
S: Clone + Into<O>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => x.to_owned(),
Self::Borrowed(x) => x.to_owned(),
Self::Owned(x) => x,
Self::BorrowedArc(x) => x.deref().clone().into(),
Self::Arc(x) => Arc::try_unwrap(x)
.unwrap_or_else(|x| x.deref().clone())
.into(),
Self::BorrowedRc(x) => x.deref().clone().into(),
Self::Rc(x) => Rc::try_unwrap(x)
.unwrap_or_else(|x| x.deref().clone())
.into(),
}
}
#[inline]
pub fn to_mut(&mut self) -> &mut O
where
B: ToOwned<Owned = O>,
S: Clone + BorrowMut<O>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => {
*self = Self::Owned(x.to_owned());
self.to_mut()
}
Self::Borrowed(x) => {
*self = Self::Owned(x.to_owned());
self.to_mut()
}
Self::Owned(x) => x,
Self::BorrowedArc(x) => {
*self = Self::Arc(S::clone(x).into());
self.to_mut()
}
Self::Arc(x) => Arc::make_mut(x).borrow_mut(),
Self::BorrowedRc(x) => {
*self = Self::Rc(S::clone(x).into());
self.to_mut()
}
Self::Rc(x) => Rc::make_mut(x).borrow_mut(),
}
}
#[inline]
pub fn into_static(self) -> Bos<'static, B, O, S>
where
B: ToOwned<Owned = O>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => Bos::Static(x),
Self::Borrowed(x) => Bos::Owned(x.to_owned()),
Self::Owned(x) => Bos::Owned(x),
Self::BorrowedArc(x) => Bos::Arc(x.clone()),
Self::Arc(x) => Bos::Arc(x),
Self::BorrowedRc(x) => Bos::Rc(x.clone()),
Self::Rc(x) => Bos::Rc(x),
}
}
#[cfg(feature = "unstable")] #[inline]
pub fn map_shared_to_owned(self) -> Bos<'b, B, O, O>
where
S: Borrow<B>,
B: ToOwned<Owned = O>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => Bos::Static(x),
Self::Borrowed(x) => Bos::Borrowed(x),
Self::Owned(x) => Bos::Owned(x),
Self::BorrowedArc(x) => Bos::Arc(x.deref().borrow().to_owned().into()),
Self::Arc(x) => Bos::Arc(x.deref().borrow().to_owned().into()),
Self::BorrowedRc(x) => Bos::Rc(x.deref().borrow().to_owned().into()),
Self::Rc(x) => Bos::Rc(x.deref().borrow().to_owned().into()),
}
}
#[cfg(feature = "unstable")] #[inline]
pub fn map_shared_to_borrowed(self) -> Bos<'b, B, O, B>
where
S: Borrow<B>,
for<'a> &'a B: Into<Arc<B>>,
for<'a> &'a B: Into<Rc<B>>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => Bos::Static(x),
Self::Borrowed(x) => Bos::Borrowed(x),
Self::Owned(x) => Bos::Owned(x),
Self::BorrowedArc(x) => Bos::Arc(x.deref().borrow().into()),
Self::Arc(x) => Bos::Arc(x.deref().borrow().into()),
Self::BorrowedRc(x) => Bos::Rc(x.deref().borrow().into()),
Self::Rc(x) => Bos::Rc(x.deref().borrow().into()),
}
}
#[inline]
pub fn to_borrowed(&self) -> Bos<'_, B, O, S>
where
O: Borrow<B>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => Bos::Static(x),
Self::Borrowed(x) => Bos::Borrowed(x),
Self::Owned(x) => Bos::Borrowed(x.borrow()),
Self::BorrowedArc(x) => Bos::BorrowedArc(x),
Self::Arc(x) => Bos::BorrowedArc(x),
Self::BorrowedRc(x) => Bos::BorrowedRc(x),
Self::Rc(x) => Bos::BorrowedRc(x),
}
}
#[inline]
pub fn into_shared(self) -> Self
where
O: Into<Rc<S>>,
{
match self {
Self::Owned(x) => Self::Rc(x.into()),
_ => self,
}
}
#[cfg(feature = "unstable")] #[inline]
pub fn clone_shared(&mut self) -> Self
where
O: Default + Clone + Into<Rc<S>>,
{
self.internal_make_shared();
self.clone()
}
#[inline]
pub fn make_shared(&mut self)
where
O: Default,
O: Into<Rc<S>>,
{
self.internal_make_shared()
}
#[inline]
fn internal_make_shared(&mut self)
where
O: Default,
O: Into<Rc<S>>,
{
if let Self::Owned(x) = self {
let x = std::mem::take(x);
*self = Self::Rc(x.into());
}
}
#[inline]
fn internal_borrow(&self) -> &B
where
O: Borrow<B>,
S: Borrow<B>,
{
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => x,
Self::Borrowed(x) => x,
Self::Owned(x) => x.borrow(),
Self::BorrowedArc(x) => x.deref().deref().borrow(),
Self::Arc(x) => x.deref().borrow(),
Self::BorrowedRc(x) => x.deref().deref().borrow(),
Self::Rc(x) => x.deref().borrow(),
}
}
}
#[cfg(feature = "lifetime")]
impl<'b, B: ?Sized, O, S: ?Sized> lifetime::IntoStatic for Bos<'b, B, O, S>
where
B: ToOwned<Owned = O>,
{
type Static = Bos<'static, B, O, S>;
fn into_static(self) -> Bos<'static, B, O, S> {
self.into_static()
}
}
#[cfg(feature = "lifetime")]
impl<'r, 'b, B: ?Sized, O, S: ?Sized> lifetime::ToBorrowed for &'r Bos<'b, B, O, S>
where
O: Borrow<B>,
{
type Borrowed = Bos<'r, B, O, S>;
fn to_borrowed(self) -> Bos<'r, B, O, S> {
self.to_borrowed()
}
}
impl<'b, B: ?Sized, O, S: ?Sized, Rhs> Add<Rhs> for Bos<'b, B, O, S>
where
O: Add<Rhs>,
B: ToOwned<Owned = O>,
S: Clone + Into<O>,
{
type Output = <O as Add<Rhs>>::Output;
#[inline]
fn add(self, rhs: Rhs) -> <O as Add<Rhs>>::Output {
self.into_owned() + rhs
}
}
impl<'b, B: ?Sized, O, S: ?Sized, Rhs> AddAssign<Rhs> for Bos<'b, B, O, S>
where
O: AddAssign<Rhs>,
B: ToOwned<Owned = O>,
S: Clone + BorrowMut<O>,
{
#[inline]
fn add_assign(&mut self, rhs: Rhs) {
*self.to_mut() += rhs;
}
}
impl<'b, B: ?Sized, O, S: ?Sized> AsRef<B> for Bos<'b, B, O, S>
where
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn as_ref(&self) -> &B {
self.internal_borrow()
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Borrow<B> for Bos<'b, B, O, S>
where
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn borrow(&self) -> &B {
self.internal_borrow()
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Deref for Bos<'b, B, O, S>
where
O: Borrow<B>,
S: Borrow<B>,
{
type Target = B;
#[inline]
fn deref(&self) -> &Self::Target {
self.internal_borrow()
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Clone for Bos<'b, B, O, S>
where
O: Clone,
{
#[inline]
fn clone(&self) -> Self {
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => Self::Static(x),
Self::Borrowed(x) => Self::Borrowed(x),
Self::Owned(x) => Self::Owned(x.clone()),
Self::BorrowedArc(x) => Self::BorrowedArc(x),
Self::Arc(x) => Self::Arc(x.clone()),
Self::BorrowedRc(x) => Self::BorrowedRc(x),
Self::Rc(x) => Self::Rc(x.clone()),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Default for Bos<'b, B, O, S>
where
O: Default,
{
#[inline]
fn default() -> Self {
Self::Owned(O::default())
}
}
impl<'b, B: ?Sized, O, S: ?Sized> fmt::Debug for Bos<'b, B, O, S>
where
B: fmt::Debug,
O: fmt::Debug,
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "unstable")]
Bos::Static(x) => f.debug_tuple("Bos::Static").field(x).finish(),
Bos::Borrowed(x) => f.debug_tuple("Bos::Borrowed").field(x).finish(),
Bos::Owned(x) => f.debug_tuple("Bos::Owned").field(x).finish(),
Bos::BorrowedArc(x) => f.debug_tuple("Bos::BorrowedArc").field(x).finish(),
Bos::Arc(x) => f.debug_tuple("Bos::Arc").field(x).finish(),
Bos::BorrowedRc(x) => f.debug_tuple("Bos::BorrowedRc").field(x).finish(),
Bos::Rc(x) => f.debug_tuple("Bos::Rc").field(x).finish(),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> fmt::Display for Bos<'b, B, O, S>
where
B: fmt::Display,
O: fmt::Display,
S: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "unstable")]
Self::Static(x) => fmt::Display::fmt(x, f),
Self::Borrowed(x) => fmt::Display::fmt(x, f),
Self::Owned(x) => fmt::Display::fmt(x, f),
Self::BorrowedArc(x) => fmt::Display::fmt(x, f),
Self::Arc(x) => fmt::Display::fmt(x, f),
Self::BorrowedRc(x) => fmt::Display::fmt(x, f),
Self::Rc(x) => fmt::Display::fmt(x, f),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Hash for Bos<'b, B, O, S>
where
B: Hash,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.internal_borrow().hash(state)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialEq<&B> for Bos<'b, B, O, S>
where
B: PartialEq,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn eq(&self, other: &&B) -> bool {
self.internal_borrow() == *other
}
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialEq<B> for Bos<'b, B, O, S>
where
B: PartialEq,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn eq(&self, other: &B) -> bool {
self.internal_borrow() == other
}
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialEq for Bos<'b, B, O, S>
where
B: PartialEq,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.internal_borrow() == other.internal_borrow()
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Eq for Bos<'b, B, O, S>
where
B: Eq,
O: Borrow<B>,
S: Borrow<B>,
{
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialOrd<&B> for Bos<'b, B, O, S>
where
B: PartialOrd,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
self.internal_borrow().partial_cmp(*other)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialOrd<B> for Bos<'b, B, O, S>
where
B: PartialOrd,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn partial_cmp(&self, other: &B) -> Option<Ordering> {
self.internal_borrow().partial_cmp(other)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialOrd for Bos<'b, B, O, S>
where
B: PartialOrd,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.internal_borrow().partial_cmp(other.internal_borrow())
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Ord for Bos<'b, B, O, S>
where
B: Ord,
O: Borrow<B>,
S: Borrow<B>,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.internal_borrow().cmp(other.internal_borrow())
}
}
impl<'b, B: ToOwned + ?Sized + 'b> From<Cow<'b, B>> for Bos<'b, B, B::Owned, B::Owned> {
#[inline]
fn from(p: Cow<'b, B>) -> Self {
match p {
Cow::Borrowed(x) => Self::Borrowed(x),
Cow::Owned(x) => Self::Owned(x),
}
}
}
#[cfg(feature = "unstable")] impl<B: ?Sized, O, S: ?Sized> From<&'static B> for Bos<'static, B, O, S> {
#[inline]
fn from(x: &'static B) -> Self {
Self::Static(x)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> From<Arc<S>> for Bos<'b, B, O, S> {
#[inline]
fn from(x: Arc<S>) -> Self {
Self::Arc(x)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> From<Rc<S>> for Bos<'b, B, O, S> {
#[inline]
fn from(x: Rc<S>) -> Self {
Self::Rc(x)
}
}
impl<'b, T> From<Vec<T>> for Bos<'b, [T], Vec<T>> {
#[inline]
fn from(x: Vec<T>) -> Self {
Self::Owned(x)
}
}
impl<'b, T> From<Bos<'b, [T], Vec<T>>> for Vec<T>
where
T: Clone,
[T]: ToOwned<Owned = Vec<T>>,
Vec<T>: Clone,
{
#[inline]
fn from(x: Bos<'b, [T], Vec<T>>) -> Self {
x.into_owned()
}
}
impl<'b> From<String> for Bos<'b, str, String> {
#[inline]
fn from(x: String) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Bos<'b, str, String>> for String {
#[inline]
fn from(x: Bos<'b, str, String>) -> Self {
x.into_owned()
}
}
impl<'b> From<CString> for Bos<'b, CStr, CString> {
#[inline]
fn from(x: CString) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Bos<'b, CStr, CString>> for CString {
#[inline]
fn from(x: Bos<'b, CStr, CString>) -> Self {
x.into_owned()
}
}
impl<'b> From<OsString> for Bos<'b, OsStr, OsString> {
#[inline]
fn from(x: OsString) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Bos<'b, OsStr, OsString>> for OsString {
#[inline]
fn from(x: Bos<'b, OsStr, OsString>) -> Self {
x.into_owned()
}
}
impl<'b> From<PathBuf> for Bos<'b, Path, PathBuf> {
#[inline]
fn from(x: PathBuf) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Bos<'b, Path, PathBuf>> for PathBuf {
#[inline]
fn from(x: Bos<'b, Path, PathBuf>) -> Self {
x.into_owned()
}
}