borrowned/
lib.rs

1//! Borrow-or-owned values.
2//!
3//! This package contains types that let you use both borrowed and owned values interchangeably.
4//! Differs from `Cow` mainly in that it borrows mutably, and doesn't convert the borrowed type
5//! into the owned type on write.
6
7#![deny(anonymous_parameters)]
8#![deny(elided_lifetimes_in_paths)]
9#![deny(ellipsis_inclusive_range_patterns)]
10#![deny(nonstandard_style)]
11#![deny(rust_2018_idioms)]
12#![deny(trivial_numeric_casts)]
13#![warn(unsafe_code)]
14#![deny(rustdoc::broken_intra_doc_links)]
15#![deny(unused)]
16//
17// Warn (try not to do this)
18#![warn(missing_copy_implementations)]
19#![warn(missing_debug_implementations)]
20#![warn(variant_size_differences)]
21//
22// Clippy
23#![warn(clippy::pedantic)]
24
25#[macro_use]
26mod util;
27pub mod read_only;
28
29use std::borrow::{Borrow, BorrowMut};
30use std::cmp::Ordering;
31use std::fmt::Display;
32use std::ops::{Deref, DerefMut};
33
34/// A smart pointer that either owns or mutably borrows.
35#[derive(Eq, Ord, Debug, Hash)]
36pub enum Borrowned<'b, T> {
37    /// Contains the owned value
38    Owned(T),
39    /// Contains the borrowed value
40    Borrowed(&'b mut T),
41}
42
43impl<'b, T> Borrowned<'b, T> {
44    /// Returns `true` if the contained value is owned.
45    ///
46    /// # Examples
47    /// ```
48    /// # use borrowned::Borrowned;
49    /// let x: Borrowned<u32> = Borrowned::Owned(2);
50    /// assert_eq!(x.is_owned(), true);
51    ///
52    /// let mut y = 2;
53    /// let x: Borrowned<u32> = Borrowned::Borrowed(&mut y);
54    /// assert_eq!(x.is_owned(), false);
55    /// ```
56    pub fn is_owned(&self) -> bool {
57        matches!(*self, Self::Owned(_))
58    }
59    /// Returns `true` if the contained value is borrowed.
60    ///
61    /// # Examples
62    /// ```
63    /// # use borrowned::Borrowned;
64    /// let x: Borrowned<u32> = Borrowned::Owned(2);
65    /// assert_eq!(x.is_borrowed(), false);
66    ///
67    /// let mut y = 2;
68    /// let x: Borrowned<u32> = Borrowned::Borrowed(&mut y);
69    /// assert_eq!(x.is_borrowed(), true);
70    /// ```
71    pub fn is_borrowed(&self) -> bool {
72        matches!(*self, Self::Borrowed(_))
73    }
74
75    /// Extracts the owned data.
76    ///
77    /// # Errors
78    /// Returns `self` in `Err` if it's not owned.
79    pub fn into_owned(self) -> Result<T, Self> {
80        match self {
81            Borrowned::Owned(owned) => Ok(owned),
82            Borrowned::Borrowed(_) => Err(self),
83        }
84    }
85
86    /// Extracts the borrowed data.
87    ///
88    /// # Errors
89    /// Returns `self` in `Err` if it's not borrowed.
90    pub fn into_borrowed(self) -> Result<&'b mut T, Self> {
91        match self {
92            Borrowned::Borrowed(borrowed) => Ok(borrowed),
93            Borrowned::Owned(_) => Err(self),
94        }
95    }
96
97    fn inner_ref(&self) -> &T {
98        match self {
99            Borrowned::Owned(owned) => owned,
100            Borrowned::Borrowed(borrowed) => *borrowed,
101        }
102    }
103
104    fn inner_mut(&mut self) -> &mut T {
105        match self {
106            Borrowned::Owned(owned) => owned,
107            Borrowned::Borrowed(borrowed) => *borrowed,
108        }
109    }
110}
111
112shared_impls!();
113
114impl<'b, T> DerefMut for Borrowned<'b, T> {
115    fn deref_mut(&mut self) -> &mut Self::Target {
116        self.inner_mut()
117    }
118}
119
120impl<'b, T> BorrowMut<T> for Borrowned<'b, T> {
121    fn borrow_mut(&mut self) -> &mut T {
122        self.inner_mut()
123    }
124}
125
126impl<'b, T> AsMut<T> for Borrowned<'b, T> {
127    fn as_mut(&mut self) -> &mut T {
128        self.inner_mut()
129    }
130}
131
132impl<'i, 'b, T> IntoIterator for &'i mut Borrowned<'b, T>
133where
134    &'i mut T: IntoIterator,
135{
136    type Item = <&'i mut T as IntoIterator>::Item;
137
138    type IntoIter = <&'i mut T as IntoIterator>::IntoIter;
139
140    fn into_iter(self) -> Self::IntoIter {
141        self.inner_mut().into_iter()
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use crate::Borrowned;
148
149    #[test]
150    fn into_owned_gives_owned_when_owned() {
151        let hw = "Hello World".to_string();
152        let ob = Borrowned::Owned(hw.clone());
153        let hw2 = ob.into_owned();
154
155        assert_eq!(hw2, Ok(hw));
156    }
157
158    #[test]
159    fn into_owned_gives_self_when_not_owned() {
160        let mut hw = "Hello World".to_string();
161        let ob = Borrowned::Borrowed(&mut hw);
162        let hw2 = ob.into_owned();
163
164        assert!(hw2.is_err());
165    }
166
167    #[test]
168    fn into_borrowed_gives_borrowed_when_borrowed() {
169        let mut hw = "Hello World".to_string();
170        let ob = Borrowned::Borrowed(&mut hw);
171        let hw2 = ob.into_borrowed();
172
173        assert!(hw2.is_ok());
174    }
175
176    #[test]
177    fn into_borrowed_gives_self_when_not_borrowed() {
178        let hw = "Hello World".to_string();
179        let ob = Borrowned::Owned(hw);
180        let hw2 = ob.into_borrowed();
181
182        assert!(hw2.is_err());
183    }
184}