1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#![warn(missing_docs, rust_2018_idioms)]
#![forbid(unsafe_code)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![no_std]

//! Traits for either borrowing or sharing data.
//!
//! # Walkthrough
//!
//! Suppose that you have a generic type that either owns some data or holds a reference to them.
//! You want to implement on this type a method taking `&self` that either borrows from `*self`
//! or from behind a reference it holds. A naive way to do this would be
//! to duplicate the method declaration:
//!
//! ```
//! struct Text<T>(T);
//!
//! impl Text<String> {
//!     // The returned reference is borrowed from `*self`
//!     // and lives as long as `self`.
//!     fn as_str(&self) -> &str {
//!         &self.0
//!     }
//! }
//!
//! impl<'a> Text<&'a str> {
//!     // The returned reference is borrowed from `*self.0`, lives
//!     // longer than `self` and is said to be shared with `*self`.
//!     fn as_str(&self) -> &'a str {
//!         self.0
//!     }
//! }
//! ```
//!
//! However, if you add more methods to `Text`, the code would become
//! intolerably verbose. This crate thus provides a [`BorrowOrShare`] trait
//! you can use to simplify the above code by making the `as_str` method
//! generic over `T`:
//!
//! ```
//! use borrow_or_share::BorrowOrShare;
//!
//! struct Text<T>(T);
//!
//! impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> Text<T> {
//!     fn as_str(&'i self) -> &'o str {
//!         self.0.borrow_or_share()
//!     }
//! }
//!
//! // The returned reference is borrowed from `*text`
//! // and lives as long as `text`.
//! fn borrow(text: &Text<String>) -> &str {
//!     text.as_str()
//! }
//!
//! // The returned reference is borrowed from `*text.0`, lives
//! // longer than `text` and is said to be shared with `*text`.
//! fn share<'a>(text: &Text<&'a str>) -> &'a str {
//!     text.as_str()
//! }
//! ```
//!
//! The [`BorrowOrShare`] trait takes two lifetime parameters `'i`, `'o`,
//! and a type parameter `T`. For `T = str` it is implemented on `String`
//! wherever `'i: 'o`, while on `&'a str` wherever `'a: 'i + 'o`.
//! The trait is also implemented on other types, which we'll cover later.
//!
//! On the trait is a [`borrow_or_share`] method that takes `&'i self`
//! and returns `&'o T`. You can use it to write your own
//! "data borrowing or sharing" functions. A typical usage would be
//! to put a `BorrowOrShare<'i, 'o, str>` bound on a type parameter `T`
//! taken by an `impl` block of your type. Within the block, you implement
//! a method that takes `&'i self` and returns something with lifetime `'o`,
//! by calling the [`borrow_or_share`] method on some `T`
//! contained in `self` and further processing the returned `&'o str`.
//!
//! [`borrow_or_share`]: BorrowOrShare::borrow_or_share
//!
//! While you're happy with the different behavior of the `as_str` method
//! on `Text<String>` (borrowing) and on `Text<&str>` (sharing), you still
//! have to fall back on borrowing when dealing with generic `Text<T>`.
//! For example, you may want to implement [`AsRef`] on `Text<T>`,
//! which requires an `as_ref` method that always borrows from `*self`.
//! The code won't compile, however, if you put the same [`BorrowOrShare`]
//! bound and write `self.as_str()` in the [`AsRef`] impl:
//!
//! ```compile_fail
//! use borrow_or_share::BorrowOrShare;
//!
//! struct Text<T>(T);
//!
//! impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> Text<T> {
//!     fn as_str(&'i self) -> &'o str {
//!         self.0.borrow_or_share()
//!     }
//! }
//!
//! impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> AsRef<str> for Text<T> {
//!     fn as_ref(&self) -> &str {
//!         self.as_str()
//!     }
//! }
//! ```
//!
//! The problem is that in the [`AsRef`] impl, the anonymous lifetime
//! `'1` of `self` does not satisfy the bounds `'1: 'i` and `'o: '1`.
//! The idiomatic solution is to put a [`Bos`] bound instead:
//!
//! ```
//! use borrow_or_share::{BorrowOrShare, Bos};
//!
//! struct Text<T>(T);
//!
//! impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> Text<T> {
//!     fn as_str(&'i self) -> &'o str {
//!         self.0.borrow_or_share()
//!     }
//! }
//!
//! impl<T: Bos<str>> AsRef<str> for Text<T> {
//!     fn as_ref(&self) -> &str {
//!         self.as_str()
//!     }
//! }
//! ```
//!
//! In the above example, the `as_str` method is also available on `Text<T>`
//! where `T: Bos<str>`, because [`BorrowOrShare`] is implemented on
//! all types that implement [`Bos`]. It also works the other way round
//! because [`Bos`] is a supertrait of [`BorrowOrShare`].
//!
//! This crate provides [`Bos`] (and [`BorrowOrShare`]) implementations
//! on [`&T`](reference), [`&mut T`](reference), [`[T; N]`](array),
//! [`Vec<T>`], [`String`], [`CString`], [`OsString`], [`PathBuf`],
//! [`Box<T>`], [`Cow<'_, B>`], [`Rc<T>`], and [`Arc<T>`]. If some of
//! these are out of scope, consider putting extra trait bounds in your
//! code, preferably on a function that constructs your type.
//!
//! [`Cow<'_, B>`]: Cow
//!
//! You can also implement [`Bos`] on your own type, for example:
//!
//! ```
//! use borrow_or_share::Bos;
//!
//! struct Text<'a>(&'a str);
//!
//! impl<'a> Bos<str> for Text<'a> {
//!     type Ref<'this> = &'a str where Self: 'this;
//!     
//!     fn borrow_or_share(this: &Self) -> Self::Ref<'_> {
//!         this.0
//!     }
//! }
//! ```
//!
//! # Limitations
//!
//! This crate only provides implementations of [`Bos`] on types that
//! currently implement [`Borrow`] in the standard library, not including
//! the blanket implementation. If this is too restrictive, feel free
//! to copy the code pattern from this crate as you wish.
//!
//! [`Borrow`]: core::borrow::Borrow
//!
//! # Crate features
//!
//! - `std` (disabled by default): Enables [`Bos`] implementations on
//!   [`OsString`] and [`PathBuf`].

extern crate alloc;
#[cfg(any(feature = "std", doc))]
extern crate std;

mod internal {
    pub trait Ref<T: ?Sized> {
        fn cast<'a>(self) -> &'a T
        where
            Self: 'a;
    }

    impl<T: ?Sized> Ref<T> for &T {
        #[inline]
        fn cast<'a>(self) -> &'a T
        where
            Self: 'a,
        {
            self
        }
    }
}

use alloc::{
    borrow::{Cow, ToOwned},
    boxed::Box,
    ffi::CString,
    rc::Rc,
    string::String,
    sync::Arc,
    vec::Vec,
};
use core::ffi::CStr;
use internal::Ref;

#[cfg(any(feature = "std", doc))]
use std::{
    ffi::{OsStr, OsString},
    path::{Path, PathBuf},
};

/// A trait for either borrowing or sharing data.
///
/// See the [crate-level documentation](crate) for more details.
pub trait Bos<T: ?Sized> {
    /// The resulting reference type. May only be `&T`.
    type Ref<'this>: Ref<T>
    where
        Self: 'this;

    /// Borrows from `*this` or from behind a reference it holds,
    /// returning a reference of type [`Self::Ref`].
    ///
    /// In the latter case, the returned reference is said to be *shared* with `*this`.
    fn borrow_or_share(this: &Self) -> Self::Ref<'_>;
}

/// A helper trait for writing "data borrowing or sharing" functions.
///
/// See the [crate-level documentation](crate) for more details.
pub trait BorrowOrShare<'i, 'o, T: ?Sized>: Bos<T> {
    /// Borrows from `*self` or from behind a reference it holds.
    ///
    /// In the latter case, the returned reference is said to be *shared* with `*self`.
    fn borrow_or_share(&'i self) -> &'o T;
}

impl<'i, 'o, T: ?Sized, B> BorrowOrShare<'i, 'o, T> for B
where
    B: Bos<T> + ?Sized + 'i,
    B::Ref<'i>: 'o,
{
    #[inline]
    fn borrow_or_share(&'i self) -> &'o T {
        (B::borrow_or_share(self) as B::Ref<'i>).cast()
    }
}

impl<'a, T: ?Sized> Bos<T> for &'a T {
    type Ref<'this> = &'a T where Self: 'this;

    #[inline]
    fn borrow_or_share(this: &Self) -> Self::Ref<'_> {
        this
    }
}

macro_rules! impl_bos {
    ($($(#[$attr:meta])? $({$($params:tt)*})? $ty:ty => $target:ty)*) => {
        $(
            $(#[$attr])?
            impl $(<$($params)*>)? Bos<$target> for $ty {
                type Ref<'this> = &'this $target where Self: 'this;

                #[inline]
                fn borrow_or_share(this: &Self) -> Self::Ref<'_> {
                    this
                }
            }
        )*
    };
}

impl_bos! {
    // A blanket impl would show up everywhere in the
    // documentation of a dependent crate, which is noisy.
    // So we're omitting it for the moment.
    // {T: ?Sized} T => T

    {T: ?Sized} &mut T => T

    {T, const N: usize} [T; N] => [T]
    {T} Vec<T> => [T]

    String => str
    CString => CStr

    #[cfg(feature = "std")]
    OsString => OsStr
    #[cfg(feature = "std")]
    PathBuf => Path

    {T: ?Sized} Box<T> => T
    {B: ?Sized + ToOwned} Cow<'_, B> => B

    {T: ?Sized} Rc<T> => T
    {T: ?Sized} Arc<T> => T
}