use std::{
borrow::Cow,
borrow::{Borrow, BorrowMut},
cmp::Ordering,
collections::HashMap,
ffi::{CStr, CString, OsStr, OsString},
fmt,
hash::Hash,
iter::FromIterator,
ops::{Add, AddAssign, Deref},
path::{Path, PathBuf},
sync::Arc,
};
pub type BoasTo<'b, B> = Boas<'b, B, <B as ToOwned>::Owned>;
pub type BoasBox<'b, T> = Boas<'b, T, Box<T>, T>;
pub type BoasVec<'b, T> = BoasTo<'b, [T]>;
pub type BoasStr<'b> = BoasTo<'b, str>;
#[non_exhaustive]
pub enum Boas<'b, B, O = B, S = O>
where
B: ?Sized,
B: 'static,
S: ?Sized,
{
Borrowed(&'b B),
Owned(O),
#[cfg(feature = "unstable")]
BorrowedArc(&'b Arc<S>),
Arc(Arc<S>),
Static(&'static B),
}
impl<'b, B: ?Sized, O, S: ?Sized> Boas<'b, B, O, S> {
#[inline]
pub fn into_owned(self) -> O
where
B: ToOwned<Owned = O>,
S: Clone + Into<O>,
{
match self {
Self::Borrowed(x) => x.to_owned(),
Self::Static(x) => x.to_owned(),
Self::Owned(x) => x,
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => x.deref().clone().into(),
Self::Arc(x) => Arc::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 {
Self::Borrowed(x) => {
*self = Self::Owned(x.to_owned());
self.to_mut()
}
Self::Static(x) => {
*self = Self::Owned(x.to_owned());
self.to_mut()
}
Self::Owned(x) => x,
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => {
*self = Self::Arc(S::clone(x).into());
self.to_mut()
}
Self::Arc(x) => Arc::make_mut(x).borrow_mut(),
}
}
#[inline]
pub fn into_static(self) -> Boas<'static, B, O, S>
where
B: ToOwned<Owned = O>,
{
match self {
Self::Borrowed(x) => Boas::Owned(x.to_owned()),
Self::Owned(x) => Boas::Owned(x),
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => Boas::Arc(x.clone()),
Self::Arc(x) => Boas::Arc(x),
Self::Static(x) => Boas::Static(x),
}
}
#[inline]
pub fn to_borrowed(&self) -> Boas<'_, B, O, S>
where
O: Borrow<B>,
{
match self {
Self::Borrowed(x) => Boas::Borrowed(x),
Self::Owned(x) => Boas::Borrowed(x.borrow()),
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => Boas::BorrowedArc(x),
#[cfg(feature = "unstable")]
Self::Arc(x) => Boas::BorrowedArc(x),
#[cfg(not(feature = "unstable"))]
Self::Arc(x) => Boas::Arc(x.clone()),
Self::Static(x) => Boas::Static(x),
}
}
#[inline]
pub fn into_shared(self) -> Self
where
O: Into<Arc<S>>,
{
match self {
Self::Owned(x) => Self::Arc(x.into()),
_ => self,
}
}
#[cfg(feature = "unstable")] #[inline]
pub fn clone_shared(&mut self) -> Self
where
O: Default + Clone + Into<Arc<S>>,
{
self.internal_make_shared();
self.clone()
}
#[inline]
pub fn make_shared(&mut self)
where
O: Default + Into<Arc<S>>,
{
self.internal_make_shared()
}
#[inline]
fn internal_make_shared(&mut self)
where
O: Default + Into<Arc<S>>,
{
if let Self::Owned(x) = self {
let x = std::mem::take(x);
*self = Self::Arc(x.into());
}
}
#[inline]
fn internal_borrow(&self) -> &B
where
O: Borrow<B>,
S: Borrow<B>,
{
match self {
Self::Borrowed(x) => x,
Self::Static(x) => x,
Self::Owned(x) => x.borrow(),
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => x.deref().deref().borrow(),
Self::Arc(x) => x.deref().borrow(),
}
}
}
impl<B: ?Sized, O, S: ?Sized> Boas<'static, B, O, S> {
pub fn ensure_static(&mut self) {
if let Self::Borrowed(x) = *self {
*self = Self::Static(x);
}
}
pub fn into_ensured_static(mut self) -> Self {
self.ensure_static();
self
}
}
impl<'b, B: ?Sized, O, S: ?Sized, Rhs> Add<Rhs> for Boas<'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 Boas<'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 Boas<'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 Boas<'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 Boas<'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 Boas<'b, B, O, S>
where
O: Clone,
{
#[inline]
fn clone(&self) -> Self {
match self {
Self::Borrowed(x) => Self::Borrowed(x),
Self::Static(x) => Self::Static(x),
Self::Owned(x) => Self::Owned(x.clone()),
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => Self::BorrowedArc(x),
Self::Arc(x) => Self::Arc(x.clone()),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Default for Boas<'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 Boas<'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 {
Boas::Borrowed(x) => f.debug_tuple("Boas::Borrowed").field(x).finish(),
Boas::Owned(x) => f.debug_tuple("Boas::Owned").field(x).finish(),
#[cfg(feature = "unstable")]
Boas::BorrowedArc(x) => f.debug_tuple("Boas::BorrowedArc").field(x).finish(),
Boas::Arc(x) => f.debug_tuple("Boas::Arc").field(x).finish(),
Boas::Static(x) => f.debug_tuple("Boas::Static").field(x).finish(),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> fmt::Display for Boas<'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 {
Self::Borrowed(x) => fmt::Display::fmt(x, f),
Self::Owned(x) => fmt::Display::fmt(x, f),
#[cfg(feature = "unstable")]
Self::BorrowedArc(x) => fmt::Display::fmt(x, f),
Self::Arc(x) => fmt::Display::fmt(x, f),
Self::Static(x) => fmt::Display::fmt(x, f),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> Hash for Boas<'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 Boas<'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 Boas<'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 Boas<'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 Boas<'b, B, O, S>
where
B: Eq,
O: Borrow<B>,
S: Borrow<B>,
{
}
impl<'b, B: ?Sized, O, S: ?Sized> PartialOrd<&B> for Boas<'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 Boas<'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 Boas<'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 Boas<'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, A, B: ?Sized, O, S: ?Sized> FromIterator<A> for Boas<'b, B, O, S>
where
O: FromIterator<A>,
{
#[inline]
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
Self::Owned(iter.into_iter().collect())
}
}
impl<'b, B: ToOwned + ?Sized + 'b> From<Cow<'b, B>> for Boas<'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),
}
}
}
impl<'b, B: ?Sized, O, S: ?Sized> From<&'b B> for Boas<'b, B, O, S> {
#[inline]
fn from(x: &'b B) -> Self {
Self::Borrowed(x)
}
}
impl<'b, B: ?Sized, O, S: ?Sized> From<Arc<S>> for Boas<'b, B, O, S> {
#[inline]
fn from(x: Arc<S>) -> Self {
Self::Arc(x)
}
}
impl<'b, T> From<Vec<T>> for Boas<'b, [T], Vec<T>> {
#[inline]
fn from(x: Vec<T>) -> Self {
Self::Owned(x)
}
}
impl<'b, T> From<Boas<'b, [T], Vec<T>>> for Vec<T>
where
T: Clone,
[T]: ToOwned<Owned = Vec<T>>,
Vec<T>: Clone,
{
#[inline]
fn from(x: Boas<'b, [T], Vec<T>>) -> Self {
x.into_owned()
}
}
impl<'b, K, V, S> From<HashMap<K, V, S>> for Boas<'b, HashMap<K, V, S>> {
#[inline]
fn from(x: HashMap<K, V, S>) -> Self {
Self::Owned(x)
}
}
impl<'b> From<String> for Boas<'b, str, String> {
#[inline]
fn from(x: String) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Boas<'b, str, String>> for String {
#[inline]
fn from(x: Boas<'b, str, String>) -> Self {
x.into_owned()
}
}
impl<'b> From<CString> for Boas<'b, CStr, CString> {
#[inline]
fn from(x: CString) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Boas<'b, CStr, CString>> for CString {
#[inline]
fn from(x: Boas<'b, CStr, CString>) -> Self {
x.into_owned()
}
}
impl<'b> From<OsString> for Boas<'b, OsStr, OsString> {
#[inline]
fn from(x: OsString) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Boas<'b, OsStr, OsString>> for OsString {
#[inline]
fn from(x: Boas<'b, OsStr, OsString>) -> Self {
x.into_owned()
}
}
impl<'b> From<PathBuf> for Boas<'b, Path, PathBuf> {
#[inline]
fn from(x: PathBuf) -> Self {
Self::Owned(x)
}
}
impl<'b> From<Boas<'b, Path, PathBuf>> for PathBuf {
#[inline]
fn from(x: Boas<'b, Path, PathBuf>) -> Self {
x.into_owned()
}
}
impl<'b, B, O, S, T, const N: usize> From<[T; N]> for Boas<'b, B, O, S>
where
B: ?Sized,
O: From<[T; N]>,
S: ?Sized,
{
#[inline]
fn from(x: [T; N]) -> Self {
Self::Owned(x.into())
}
}