borrowned 0.6.0

Borrow-or-owned values
Documentation
//! Borrow-or-owned values.
//!
//! This module contains the same type as in the root, except this one takes a `&T` instead of
//! a `&mut T`, so it can be used in situations where you only need read access to the contents,
//! or when you can only get a `&T`, not a `&mut T`.

use std::borrow::{Borrow, Cow};
use std::cmp::Ordering;
use std::fmt::Display;
use std::ops::Deref;

/// A smart pointer that either owns or borrows.
#[derive(Eq, Ord, Debug, Hash)]
pub enum Borrowned<'b, T> {
    /// Contains the owned value
    Owned(T),
    /// Contains the borrowed value
    Borrowed(&'b T),
}

impl<'b, T> Borrowned<'b, T> {
    /// Returns `true` if the contained value is owned.
    ///
    /// # Examples
    /// ```
    /// # use borrowned::read_only::Borrowned;
    /// let x: Borrowned<u32> = Borrowned::Owned(2);
    /// assert_eq!(x.is_owned(), true);
    ///
    /// let y = 2;
    /// let x: Borrowned<u32> = Borrowned::Borrowed(&y);
    /// assert_eq!(x.is_owned(), false);
    /// ```
    pub fn is_owned(&self) -> bool {
        matches!(*self, Self::Owned(_))
    }
    /// Returns `true` if the contained value is borrowed.
    ///
    /// # Examples
    /// ```
    /// # use borrowned::read_only::Borrowned;
    /// let x: Borrowned<u32> = Borrowned::Owned(2);
    /// assert_eq!(x.is_borrowed(), false);
    ///
    /// let y = 2;
    /// let x: Borrowned<u32> = Borrowned::Borrowed(&y);
    /// assert_eq!(x.is_borrowed(), true);
    /// ```
    pub fn is_borrowed(&self) -> bool {
        matches!(*self, Self::Borrowed(_))
    }

    /// Extracts the owned data.
    ///
    /// # Errors
    /// Returns `self` in `Err` if it's not owned.
    pub fn into_owned(self) -> Result<T, Self> {
        match self {
            Borrowned::Owned(owned) => Ok(owned),
            Borrowned::Borrowed(_) => Err(self),
        }
    }

    /// Extracts the borrowed data.
    ///
    /// # Errors
    /// Returns `self` in `Err` if it's not borrowed.
    pub fn into_borrowed(self) -> Result<&'b T, Self> {
        match self {
            Borrowned::Borrowed(borrowed) => Ok(borrowed),
            Borrowned::Owned(_) => Err(self),
        }
    }

    fn inner_ref(&self) -> &T {
        match self {
            Borrowned::Owned(owned) => owned,
            Borrowned::Borrowed(borrowed) => *borrowed,
        }
    }
}

shared_impls!();

#[doc(hidden)]
pub trait Reflective {
    type Same;
}

#[doc(hidden)]
impl<T> Reflective for T {
    type Same = Self;
}

impl<'b, T> From<Cow<'b, T>> for Borrowned<'b, T>
where
    T: Clone,
    <T as ToOwned>::Owned: Reflective<Same = T>,
{
    fn from(c: Cow<'b, T>) -> Self {
        match c {
            Cow::Borrowed(t) => Borrowned::Borrowed(t),
            Cow::Owned(t) => Borrowned::Owned(t),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::read_only::Borrowned;

    #[test]
    fn into_owned_gives_owned_when_owned() {
        let hw = "Hello World".to_string();
        let ob = Borrowned::Owned(hw.clone());
        let hw2 = ob.into_owned();

        assert_eq!(hw2, Ok(hw));
    }

    #[test]
    fn into_owned_gives_self_when_not_owned() {
        let hw = "Hello World".to_string();
        let ob = Borrowned::Borrowed(&hw);
        let hw2 = ob.into_owned();

        assert!(hw2.is_err());
    }

    #[test]
    fn into_borrowed_gives_borrowed_when_borrowed() {
        let hw = "Hello World".to_string();
        let ob = Borrowned::Borrowed(&hw);
        let hw2 = ob.into_borrowed();

        assert!(hw2.is_ok());
    }

    #[test]
    fn into_borrowed_gives_self_when_not_borrowed() {
        let hw = "Hello World".to_string();
        let ob = Borrowned::Owned(hw);
        let hw2 = ob.into_borrowed();

        assert!(hw2.is_err());
    }
}