as_is/
lib.rs

1//! **Development in progress**
2//!
3//! This crate provides a trait [`AsIs`], an enum [`Is<'a, T>`], and variants of them.
4//!
5//! [`AsIs`]: trait.AsIs.html
6//! [`Is<'a, T>`]: enum.Is.html
7
8#![no_std]
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13mod borrow;
14pub use borrow::{BorrowAsIs, BorrowMutAsIs, Owned, ToOwnedMut};
15
16#[cfg_attr(feature = "alloc", doc(no_inline))]
17pub use borrow::ToOwned;
18
19mod is;
20mod is_cow;
21mod is_mut;
22
23pub use is::Is;
24pub use is_cow::IsCow;
25pub use is_mut::IsMut;
26
27mod foreign;
28pub use foreign::{StringStub, VecStub};
29
30#[cfg(test)]
31mod tests;
32
33#[cfg(feature = "alloc")]
34use alloc::borrow::Cow;
35
36use core::borrow::{Borrow, BorrowMut};
37
38/// Used to do a cheap conversion into [`Is<'a, T>`] in generic contexts.
39///
40/// [`Is<'a, T>`]: enum.Is.html
41pub trait AsIs: Sized + BorrowAsIs {
42    /// Converts `self` into an [`Is<'a, Self::Is>`].
43    ///
44    /// [`Is<'a, Self::Is>`]: enum.Is.html
45    #[allow(clippy::wrong_self_convention)]
46    fn as_is<'a>(self) -> Is<'a, Self::Is>
47    where
48        Self: 'a;
49
50    /// Converts `self` into an [`Is<'a, B>`].
51    ///
52    /// [`Is<'a, B>`]: enum.Is.html
53    fn into_is<'a, B>(self) -> Is<'a, B>
54    where
55        Self: 'a,
56        Self::Is: BorrowMut<B>,
57        B: ?Sized + ToOwned<Owned = Owned<Self>>,
58    {
59        match self.as_is() {
60            Is::Owned(x) => Is::Owned(x),
61            Is::Borrowed(x) => Is::Borrowed(x.borrow()),
62            Is::MutBorrowed(x) => Is::MutBorrowed(x.borrow_mut()),
63        }
64    }
65
66    /// Converts `self` into an [`IsCow<'a, B>`].
67    ///
68    /// [`IsCow<'a, B>`]: enum.IsCow.html
69    fn into_is_cow<'a, B>(self) -> IsCow<'a, B>
70    where
71        Self: 'a,
72        Self::Is: Borrow<B>,
73        B: ?Sized + ToOwned<Owned = Owned<Self>>,
74    {
75        match self.as_is() {
76            Is::Owned(x) => IsCow::Owned(x),
77            Is::Borrowed(x) => IsCow::Borrowed(x.borrow()),
78            Is::MutBorrowed(x) => IsCow::Borrowed((*x).borrow()),
79        }
80    }
81
82    /// Converts `self` into an [`IsMut<'a, B>`] without cloning if possible.
83    ///
84    /// # Errors
85    ///
86    /// If `self` cannot be converted without cloning, returns `self` as [`Is<'a, Self::Is>`].
87    ///
88    /// [`IsMut<'a, B>`]: enum.IsMut.html
89    /// [`Is<'a, Self::Is>`]: enum.Is.html
90    fn try_into_is_mut<'a, B>(self) -> Result<IsMut<'a, B>, Is<'a, Self::Is>>
91    where
92        Self: 'a,
93        Self::Is: BorrowMut<B>,
94        B: ?Sized + ToOwned<Owned = Owned<Self>>,
95    {
96        match self.as_is() {
97            Is::Owned(x) => Ok(IsMut::Owned(x)),
98            Is::Borrowed(x) => Err(Is::Borrowed(x)),
99            Is::MutBorrowed(x) => Ok(IsMut::MutBorrowed(x.borrow_mut())),
100        }
101    }
102
103    /// Converts `self` into an owned data without cloning if possible.
104    ///
105    /// # Errors
106    ///
107    /// If `self` cannot be converted without cloning, returns `self` as [`Is<'a, Self::Is>`].
108    ///
109    /// [`Is<'a, Self::Is>`]: enum.Is.html
110    fn try_into_owned<'a>(self) -> Result<Owned<Self>, Is<'a, Self::Is>>
111    where
112        Self: 'a,
113    {
114        match self.as_is() {
115            Is::Owned(x) => Ok(x),
116            Is::Borrowed(x) => Err(Is::Borrowed(x)),
117            Is::MutBorrowed(x) => Err(Is::MutBorrowed(x)),
118        }
119    }
120
121    /// Converts `self` into a [`Cow<'a, B>`]. Only available if the `alloc` feature
122    /// is enabled.
123    ///
124    /// [`Cow<'a, B>`]: https://doc.rust-lang.org/alloc/borrow/enum.Cow.html
125    #[cfg(feature = "alloc")]
126    fn into_cow<'a, B>(self) -> Cow<'a, B>
127    where
128        Self: 'a,
129        Self::Is: Borrow<B>,
130        B: ?Sized + ToOwned<Owned = Owned<Self>>,
131    {
132        match self.as_is() {
133            Is::Owned(x) => Cow::Owned(x),
134            Is::Borrowed(x) => Cow::Borrowed(x.borrow()),
135            Is::MutBorrowed(x) => Cow::Borrowed((*x).borrow()),
136        }
137    }
138}
139
140impl<T> AsIs for &T
141where
142    Self: Borrow<T::Is>,
143    T: ?Sized + BorrowAsIs,
144{
145    fn as_is<'a>(self) -> Is<'a, T::Is>
146    where
147        Self: 'a,
148    {
149        match self.borrow_or_clone() {
150            IsCow::Owned(x) => Is::Owned(x),
151            IsCow::Borrowed(x) => Is::Borrowed(x),
152        }
153    }
154}
155
156impl<T> AsIs for &mut T
157where
158    Self: Borrow<T::Is>,
159    T: ?Sized + BorrowMutAsIs,
160{
161    fn as_is<'a>(self) -> Is<'a, T::Is>
162    where
163        Self: 'a,
164    {
165        match self.borrow_or_clone() {
166            IsCow::Owned(x) => Is::Owned(x),
167            IsCow::Borrowed(_) => Is::MutBorrowed(self.borrow_mut()),
168        }
169    }
170}
171
172/// Used to do a cheap conversion into [`IsMut<'a, T>`] in generic contexts.
173///
174/// [`IsMut<'a, T>`]: enum.IsMut.html
175pub trait AsIsMut: AsIs + BorrowMutAsIs {
176    /// Converts `self` into an [`IsMut<'a, Self::Is>`].
177    ///
178    /// # Panics
179    ///
180    /// If [`self.as_is()`] returns an [`Is::Borrowed`] variant.
181    ///
182    /// [`IsMut<'a, Self::Is>`]: enum.IsMut.html
183    /// [`self.as_is()`]: trait.AsIs.html#tymethod.as_is
184    /// [`Is::Borrowed`]: enum.Is.html#variant.Borrowed
185    #[allow(clippy::wrong_self_convention)]
186    fn as_is_mut<'a>(self) -> IsMut<'a, Self::Is>
187    where
188        Self: 'a,
189    {
190        match self.as_is() {
191            Is::Owned(x) => IsMut::Owned(x),
192            Is::Borrowed(_) => {
193                panic!("Is::Borrowed variant returned from an AsIsMut type")
194            }
195            Is::MutBorrowed(x) => IsMut::MutBorrowed(x),
196        }
197    }
198
199    /// Converts `self` into an [`IsMut<'a, B>`].
200    ///
201    /// [`IsMut<'a, B>`]: enum.IsMut.html
202    fn into_is_mut<'a, B>(self) -> IsMut<'a, B>
203    where
204        Self: 'a,
205        Self::Is: BorrowMut<B>,
206        B: ?Sized + ToOwned<Owned = Owned<Self>>,
207    {
208        match self.as_is_mut() {
209            IsMut::Owned(x) => IsMut::Owned(x),
210            IsMut::MutBorrowed(x) => IsMut::MutBorrowed(x.borrow_mut()),
211        }
212    }
213}
214
215impl<T> AsIsMut for T where Self: AsIs + BorrowMutAsIs {}