borrowned 0.6.0

Borrow-or-owned values
Documentation
//! Borrow-or-owned values.
//!
//! This package contains types that let you use both borrowed and owned values interchangeably.
//! Differs from `Cow` mainly in that it borrows mutably, and doesn't convert the borrowed type
//! into the owned type on write.

#![deny(anonymous_parameters)]
#![deny(elided_lifetimes_in_paths)]
#![deny(ellipsis_inclusive_range_patterns)]
#![deny(nonstandard_style)]
#![deny(rust_2018_idioms)]
#![deny(trivial_numeric_casts)]
#![warn(unsafe_code)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(unused)]
//
// Warn (try not to do this)
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(variant_size_differences)]
//
// Clippy
#![warn(clippy::pedantic)]

#[macro_use]
mod util;
pub mod read_only;

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

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

impl<'b, T> Borrowned<'b, T> {
    /// Returns `true` if the contained value is owned.
    ///
    /// # Examples
    /// ```
    /// # use borrowned::Borrowned;
    /// let x: Borrowned<u32> = Borrowned::Owned(2);
    /// assert_eq!(x.is_owned(), true);
    ///
    /// let mut y = 2;
    /// let x: Borrowned<u32> = Borrowned::Borrowed(&mut 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::Borrowned;
    /// let x: Borrowned<u32> = Borrowned::Owned(2);
    /// assert_eq!(x.is_borrowed(), false);
    ///
    /// let mut y = 2;
    /// let x: Borrowned<u32> = Borrowned::Borrowed(&mut 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 mut 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,
        }
    }

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

shared_impls!();

impl<'b, T> DerefMut for Borrowned<'b, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner_mut()
    }
}

impl<'b, T> BorrowMut<T> for Borrowned<'b, T> {
    fn borrow_mut(&mut self) -> &mut T {
        self.inner_mut()
    }
}

impl<'b, T> AsMut<T> for Borrowned<'b, T> {
    fn as_mut(&mut self) -> &mut T {
        self.inner_mut()
    }
}

impl<'i, 'b, T> IntoIterator for &'i mut Borrowned<'b, T>
where
    &'i mut T: IntoIterator,
{
    type Item = <&'i mut T as IntoIterator>::Item;

    type IntoIter = <&'i mut T as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.inner_mut().into_iter()
    }
}

#[cfg(test)]
mod tests {
    use crate::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 mut hw = "Hello World".to_string();
        let ob = Borrowned::Borrowed(&mut hw);
        let hw2 = ob.into_owned();

        assert!(hw2.is_err());
    }

    #[test]
    fn into_borrowed_gives_borrowed_when_borrowed() {
        let mut hw = "Hello World".to_string();
        let ob = Borrowned::Borrowed(&mut 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());
    }
}