198 lines
5.5 KiB
Rust
198 lines
5.5 KiB
Rust
pub enum TriCow<'a, 'b, T>
|
|
where
|
|
T: ToOwned + ?Sized,
|
|
{
|
|
Borrowed(&'a T),
|
|
Ephemeral(&'b T),
|
|
Owned(<T as ToOwned>::Owned),
|
|
}
|
|
|
|
impl<'a, 'b, T> TriCow<'a, 'b, T>
|
|
where
|
|
T: ToOwned + ?Sized,
|
|
{
|
|
pub fn into_owned(self) -> T::Owned {
|
|
match self {
|
|
Self::Borrowed(t) => t.to_owned(),
|
|
Self::Ephemeral(t) => t.to_owned(),
|
|
Self::Owned(t) => t,
|
|
}
|
|
}
|
|
|
|
pub fn into_std(self) -> std::borrow::Cow<'a, T> {
|
|
match self {
|
|
Self::Borrowed(t) => std::borrow::Cow::Borrowed(t),
|
|
Self::Ephemeral(t) => std::borrow::Cow::Owned(t.to_owned()),
|
|
Self::Owned(t) => std::borrow::Cow::Owned(t),
|
|
}
|
|
}
|
|
|
|
pub fn to_mut(&mut self) -> &mut <T as ToOwned>::Owned {
|
|
match *self {
|
|
Self::Borrowed(t) => {
|
|
*self = Self::Owned(t.to_owned());
|
|
match self {
|
|
Self::Owned(ref mut t) => t,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
Self::Ephemeral(t) => {
|
|
*self = Self::Owned(t.to_owned());
|
|
match self {
|
|
Self::Owned(ref mut t) => t,
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
Self::Owned(ref mut t) => t,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b, T> AsRef<T> for TriCow<'a, 'b, T>
|
|
where
|
|
T: ToOwned + ?Sized,
|
|
T::Owned: std::borrow::Borrow<T>,
|
|
{
|
|
fn as_ref(&self) -> &T {
|
|
match self {
|
|
Self::Borrowed(t) => t,
|
|
Self::Ephemeral(t) => t,
|
|
Self::Owned(ref t) => std::borrow::Borrow::borrow(t),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::TriCow;
|
|
|
|
#[test]
|
|
fn a() {
|
|
let bytes = &[1, 2, 3, 4, 5, 6][..];
|
|
|
|
A::with_cow(TriCow::Borrowed(bytes));
|
|
A::with_cow(TriCow::Ephemeral(bytes));
|
|
A::with_cow(TriCow::Owned(Vec::from(bytes)));
|
|
}
|
|
|
|
#[test]
|
|
fn b() {
|
|
let bytes = &[1, 2, 3, 4, 5, 6][..];
|
|
|
|
B::with_cow(TriCow::Borrowed(bytes));
|
|
B::with_cow(TriCow::Ephemeral(bytes));
|
|
B::with_cow(TriCow::Owned(Vec::from(bytes)));
|
|
}
|
|
|
|
#[test]
|
|
fn c() {
|
|
let bytes = &[1, 2, 3, 4, 5, 6][..];
|
|
|
|
C::with_cow(TriCow::Borrowed(bytes));
|
|
C::with_cow(TriCow::Ephemeral(bytes));
|
|
C::with_cow(TriCow::Owned(Vec::from(bytes)));
|
|
}
|
|
|
|
#[test]
|
|
fn d() {
|
|
let bytes = &[1, 2, 3, 4, 5, 6][..];
|
|
|
|
D::with_cow(TriCow::Borrowed(bytes));
|
|
D::with_cow(TriCow::Ephemeral(bytes));
|
|
D::with_cow(TriCow::Owned(Vec::from(bytes)));
|
|
}
|
|
|
|
#[test]
|
|
fn e() {
|
|
let bytes = &[1, 2, 3, 4, 5, 6][..];
|
|
|
|
E::with_cow(TriCow::Borrowed(bytes));
|
|
E::with_cow(TriCow::Ephemeral(bytes));
|
|
E::with_cow(TriCow::Owned(Vec::from(bytes)));
|
|
}
|
|
|
|
trait WithCow<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self;
|
|
}
|
|
|
|
struct A<'a>(std::borrow::Cow<'a, [u8]>);
|
|
struct B<'a>(A<'a>);
|
|
struct C<'a>(B<'a>, std::borrow::Cow<'a, [u8]>);
|
|
struct D<'a>(C<'a>);
|
|
struct E<'a>(D<'a>, std::borrow::Cow<'a, [u8]>);
|
|
|
|
impl<'a> WithCow<'a> for A<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self {
|
|
Self(cow.into_std())
|
|
}
|
|
}
|
|
|
|
impl<'a> WithCow<'a> for B<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self {
|
|
Self(A::with_cow(cow))
|
|
}
|
|
}
|
|
|
|
impl<'a> WithCow<'a> for C<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self {
|
|
match cow {
|
|
TriCow::Borrowed(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
B::with_cow(TriCow::Borrowed(first)),
|
|
std::borrow::Cow::Borrowed(second),
|
|
)
|
|
}
|
|
TriCow::Ephemeral(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
B::with_cow(TriCow::Ephemeral(first)),
|
|
std::borrow::Cow::Owned(Vec::from(second)),
|
|
)
|
|
}
|
|
TriCow::Owned(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
B::with_cow(TriCow::Ephemeral(first)),
|
|
std::borrow::Cow::Owned(Vec::from(second)),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> WithCow<'a> for D<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self {
|
|
Self(C::with_cow(cow))
|
|
}
|
|
}
|
|
|
|
impl<'a> WithCow<'a> for E<'a> {
|
|
fn with_cow<'b>(cow: TriCow<'a, 'b, [u8]>) -> Self {
|
|
match cow {
|
|
TriCow::Borrowed(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
D::with_cow(TriCow::Borrowed(first)),
|
|
std::borrow::Cow::Borrowed(second),
|
|
)
|
|
}
|
|
TriCow::Ephemeral(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
D::with_cow(TriCow::Ephemeral(first)),
|
|
std::borrow::Cow::Owned(Vec::from(second)),
|
|
)
|
|
}
|
|
TriCow::Owned(bytes) => {
|
|
let (first, second) = bytes.split_at(2);
|
|
Self(
|
|
D::with_cow(TriCow::Ephemeral(first)),
|
|
std::borrow::Cow::Owned(Vec::from(second)),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|