#![no_std]
#![warn(clippy::pedantic)]
#![doc(html_root_url = "https://docs.rs/cervine/0.0.6")]
#[cfg(doctest)]
pub mod readme {
doc_comment::doctest!("../README.md");
}
use core::{
borrow::Borrow,
cmp::Ordering,
convert::{TryFrom, TryInto as _},
fmt::{self, Display, Formatter},
hash::{Hash, Hasher},
ops::Deref,
};
#[cfg(feature = "serde")]
use serde::{de, ser};
#[derive(Debug)]
pub enum Cow<'a, T, R: ?Sized> {
Owned(T),
Borrowed(&'a R),
}
impl<'a, T: Borrow<R>, R: ?Sized> Cow<'a, T, R> {
pub fn is_borrowed(&self) -> bool {
matches!(self, Cow::Borrowed(_))
}
pub fn is_owned(&self) -> bool {
matches!(self, Cow::Owned(_))
}
}
impl<'a, T: From<&'a R>, R: ?Sized> Cow<'a, T, R> {
pub fn into_owned(self) -> T {
match self {
Cow::Owned(t) => t,
Cow::Borrowed(r) => r.into(),
}
}
pub fn make_mut(&mut self) -> &mut T {
match self {
Cow::Owned(t) => t,
Cow::Borrowed(r) => {
*self = Cow::Owned((*r).into());
match self {
Cow::Owned(t) => t,
Cow::Borrowed(_) => unreachable!(),
}
}
}
}
}
impl<'a, T: TryFrom<&'a R>, R: ?Sized> Cow<'a, T, R> {
pub fn try_into_owned(self) -> Result<T, T::Error> {
match self {
Cow::Owned(t) => Ok(t),
Cow::Borrowed(r) => r.try_into(),
}
}
pub fn try_make_mut(&mut self) -> Result<&mut T, T::Error> {
match self {
Cow::Owned(t) => Ok(t),
Cow::Borrowed(r) => {
*self = Cow::Owned((*r).try_into()?);
match self {
Cow::Owned(t) => Ok(t),
Cow::Borrowed(_) => unreachable!(),
}
}
}
}
}
impl<'a, T: AsRef<R>, R: ?Sized> AsRef<R> for Cow<'a, T, R> {
fn as_ref(&self) -> &R {
match self {
Cow::Owned(t) => t.as_ref(),
Cow::Borrowed(r) => r,
}
}
}
impl<'a, T: Deref<Target = R>, R: ?Sized> Deref for Cow<'a, T, R> {
type Target = R;
fn deref(&self) -> &Self::Target {
match self {
Cow::Owned(t) => t,
Cow::Borrowed(r) => r,
}
}
}
impl<'a, T: Borrow<R>, R: ?Sized> Borrow<R> for Cow<'a, T, R> {
fn borrow(&self) -> &R {
match self {
Cow::Owned(t) => t.borrow(),
Cow::Borrowed(r) => r,
}
}
}
impl<'a, T: Borrow<R>, R: Display + ?Sized> Display for Cow<'a, T, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Borrow::<R>::borrow(self).fmt(f)
}
}
impl<'a, T: Copy, R: ?Sized> Copy for Cow<'a, T, R> {}
impl<'a, T: Clone, R: ?Sized> Clone for Cow<'a, T, R> {
fn clone(&self) -> Self {
match self {
Cow::Owned(t) => Self::Owned(t.clone()),
Cow::Borrowed(r) => Self::Borrowed(r),
}
}
}
impl<'a, T: Default, R: ?Sized> Default for Cow<'a, T, R> {
fn default() -> Self {
Cow::Owned(T::default())
}
}
impl<'a, T: Borrow<R>, R: PartialEq + ?Sized> PartialEq<R> for Cow<'a, T, R> {
fn eq(&self, other: &R) -> bool {
Borrow::<R>::borrow(self) == other
}
}
impl<'a, T: Borrow<R>, R: PartialEq + ?Sized> PartialEq for Cow<'a, T, R> {
fn eq(&self, other: &Self) -> bool {
Borrow::<R>::borrow(self) == other.borrow()
}
}
impl<'a, T: Borrow<R>, R: Eq + ?Sized> Eq for Cow<'a, T, R> {}
impl<'a, T: Borrow<R>, R: PartialOrd + ?Sized> PartialOrd<R> for Cow<'a, T, R> {
fn partial_cmp(&self, other: &R) -> Option<Ordering> {
Borrow::<R>::borrow(self).partial_cmp(other)
}
fn lt(&self, other: &R) -> bool {
Borrow::<R>::borrow(self).lt(other)
}
fn le(&self, other: &R) -> bool {
Borrow::<R>::borrow(self).le(other)
}
fn gt(&self, other: &R) -> bool {
Borrow::<R>::borrow(self).gt(other)
}
fn ge(&self, other: &R) -> bool {
Borrow::<R>::borrow(self).ge(other)
}
}
impl<'a, T: Borrow<R>, R: PartialOrd + ?Sized> PartialOrd for Cow<'a, T, R> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Borrow::<R>::borrow(self).partial_cmp(other.borrow())
}
fn lt(&self, other: &Self) -> bool {
Borrow::<R>::borrow(self).lt(other.borrow())
}
fn le(&self, other: &Self) -> bool {
Borrow::<R>::borrow(self).le(other.borrow())
}
fn gt(&self, other: &Self) -> bool {
Borrow::<R>::borrow(self).gt(other.borrow())
}
fn ge(&self, other: &Self) -> bool {
Borrow::<R>::borrow(self).ge(other.borrow())
}
}
impl<'a, T: Borrow<R>, R: Ord + ?Sized> Ord for Cow<'a, T, R> {
fn cmp(&self, other: &Self) -> Ordering {
Borrow::<R>::borrow(self).cmp(other.borrow())
}
}
impl<'a, T: Borrow<R>, R: Hash + ?Sized> Hash for Cow<'a, T, R> {
fn hash<H: Hasher>(&self, state: &mut H) {
Borrow::<R>::borrow(self).hash(state)
}
}
#[cfg(feature = "serde")]
impl<'a, T: Borrow<R>, R: ser::Serialize + ?Sized> ser::Serialize for Cow<'a, T, R> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
Borrow::<R>::borrow(self).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'a, 'de, T: de::Deserialize<'de>, R: ?Sized> de::Deserialize<'de> for Cow<'a, T, R> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(Cow::Owned)
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: serde::Deserializer<'de>,
{
match place {
Cow::Owned(t) => T::deserialize_in_place(deserializer, t),
Cow::Borrowed(_) => serde::Deserialize::deserialize(deserializer).map(|de| *place = de),
}
}
}