borrow_framework/
lib.rs

1//! A `no_std` set of utilities for more flexible borrowing than the ones
2//! provided by the standard library.
3//!
4//! Due to Rust's lack of complete support for Higher Kinded Types (HKTs),
5//! borrowing is not as powerful as it could be. Even with the introduction of
6//! limited Generic Associated Types (GATs) in Rust 1.65, the standard library
7//! has not gained useful APIs that take advantage of this functionality for
8//! better borrowing.
9//!
10//! This crate introduces more flexible traits for working with borrowed data,
11//! especially with types containing internal borrows, by relying on the HKT
12//! framework introduced by
13//! [generic-std](https://github.com/Ereski/generic-std). Compiler support for
14//! GATs is not required.
15//!
16//! # Features
17//!
18//! This crate replaces [std::borrow] with more flexible types and traits.
19//!
20//! ## More Flexible Borrowing
21//!
22//! [Borrow] and [BorrowMut] are similar to the ones provided by the standard
23//! library, but the borrowed type may be an arbitrary type. For example,
24//! [Borrow::borrow] might directly return an [std::borrow::Cow].
25//!
26//! ## Saner `ToOwned`
27//!
28//! [ToOwned] is not tied to the borrow trait anymore and provides a
29//! [ToOwned::into_owned] method. Also, no blanket implementation for `Clone`
30//! types so something like `Cow::<'a, T>::to_owned` is finally able to return
31//! the much saner `Cow<'static, T>`.
32//!
33//! ## Clone-On-Write For Types With Internal References
34//!
35//! [std::borrow::Cow] stores either the owned or the borrowed version of
36//! another type, but the borrowed variant is required to be a reference. The
37//! [Cow] type provided by this crate integrates with [Borrow] and [ToOwned],
38//! allowing the borrowed variant to contain a non-reference type with internal
39//! references.
40//!
41//! # Example
42//!
43//! Suppose you have a `Identifier<'a>` type that internally contains either a
44//! borrowed or an owned string and you would like to create an
45//! `Identifier<'static>` to store somewhere. This is not possible with
46//! [std::borrow::ToOwned] because [std::borrow::ToOwned::Owned] must implement
47//! [std::borrow::Borrow], and [std::borrow::Borrow::borrow] must return a
48//! reference, not `Identifier<'a>`. But doing this is trivial with this crate's
49//! [ToOwned]:
50//!
51//! ```rust
52//! # use borrow_framework::ToOwned;
53//! # struct Identifier<'a>(std::borrow::Cow<'a, str>);
54//! impl<'a> ToOwned for Identifier<'a> {
55//!     type Owned = Identifier<'static>;
56//!
57//!     fn to_owned(&self) -> Self::Owned {
58//!         // Returns an `Identifier<'static>`
59//!         # unimplemented!()
60//!     }
61//! }
62//! ```
63//!
64//! Similarly, this crate's [Borrow] can return `Identifier<'a>` directly in
65//! addition to normal references:
66//!
67//! ```rust
68//! # use borrow_framework::{Borrow, Borrowed, BorrowHkt};
69//! # struct Identifier<'a>(std::borrow::Cow<'a, str>);
70//! struct BorrowIdentifier;
71//!
72//! impl<'a> BorrowHkt<'a> for BorrowIdentifier {
73//!     type T = Identifier<'a>;
74//! }
75//!
76//! impl<'a> Borrow<'a, BorrowIdentifier> for Identifier<'a> {
77//!     fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowIdentifier>
78//!     where
79//!         'a: 'b
80//!     {
81//!         // Returns an `Identifier<'b>`
82//!         # unimplemented!()
83//!     }
84//! }
85//!
86//! struct BorrowIdentifierStr;
87//!
88//! impl<'a> BorrowHkt<'a> for BorrowIdentifierStr {
89//!     type T = &'a str;
90//! }
91//!
92//! impl<'a> Borrow<'a, BorrowIdentifierStr> for Identifier<'a> {
93//!     fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowIdentifierStr>
94//!     where
95//!         'a: 'b
96//!     {
97//!         // Returns a `&'b str`
98//!         # unimplemented!()
99//!     }
100//! }
101//! ```
102
103#![cfg_attr(not(feature = "std"), no_std)]
104
105use core::{
106    cmp::Ordering,
107    fmt::{self, Debug, Formatter},
108    hash::{Hash, Hasher},
109    marker::PhantomData,
110};
111
112/// Flexible borrowing trait.
113///
114/// This is similar to [std::borrow::Borrow] but allows non-reference types to
115/// be used.
116pub trait Borrow<'a, T>
117where
118    T: for<'b> BorrowHkt<'b>,
119{
120    /// Create a borrowed version of this type.
121    fn borrow<'b>(&'a self) -> Borrowed<'b, T>
122    where
123        'a: 'b;
124}
125
126impl<'a> Borrow<'a, BorrowString> for &str {
127    fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowString>
128    where
129        'a: 'b,
130    {
131        self
132    }
133}
134
135#[cfg(feature = "std")]
136impl<'a> Borrow<'a, BorrowString> for String {
137    fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowString>
138    where
139        'a: 'b,
140    {
141        self
142    }
143}
144
145/// Trait for resolving a concrete type from a given lifetime `'a`, where `'a`
146/// is the lifetime of the value being borrowed.
147pub trait BorrowHkt<'a> {
148    /// The borrowed type.
149    type T;
150}
151
152/// Marker type implementing [BorrowHkt] for [str].
153pub struct BorrowString;
154
155impl<'a> BorrowHkt<'a> for BorrowString {
156    type T = &'a str;
157}
158
159/// Type alias to extract the concrete borrowed type from a [BorrowHkt].
160pub type Borrowed<'a, T> = <T as BorrowHkt<'a>>::T;
161
162/// Flexible mutable borrowing trait.
163///
164/// This is similar to [std::borrow::BorrowMut] but allows non-reference types
165/// to be used.
166pub trait BorrowMut<'a, T>: Borrow<'a, T>
167where
168    T: for<'b> BorrowMutHkt<'b>,
169{
170    /// Create a borrowed version of this type.
171    fn borrow_mut<'b>(&'a mut self) -> BorrowedMut<'b, T>
172    where
173        'a: 'b;
174}
175
176/// Trait for resolving a concrete type from a given lifetime `'a`, where `'a`
177/// is the lifetime of the value being mutably borrowed.
178pub trait BorrowMutHkt<'a>: BorrowHkt<'a> {
179    /// The borrowed type.
180    type T;
181}
182
183/// Type alias to extract the concrete borrowed type from a [BorrowMutHkt].
184pub type BorrowedMut<'a, T> = <T as BorrowMutHkt<'a>>::T;
185
186/// Convert from a borrowed type into an owned type.
187///
188/// This is similar to [std::borrow::ToOwned] but is meant for types with
189/// internal references, with support for `into_owned` and an additional `Sized`
190/// constraint.
191pub trait ToOwned: Sized {
192    /// Owned type.
193    type Owned;
194
195    /// Create an owned version of this type by cloning if necessary.
196    fn to_owned(&self) -> Self::Owned;
197
198    /// Create an owned version of this type, consuming `self`.
199    fn into_owned(self) -> Self::Owned {
200        self.to_owned()
201    }
202}
203
204#[cfg(feature = "std")]
205impl ToOwned for &str {
206    type Owned = String;
207
208    fn to_owned(&self) -> Self::Owned {
209        std::borrow::ToOwned::to_owned(*self)
210    }
211}
212
213#[cfg(feature = "std")]
214impl ToOwned for String {
215    type Owned = String;
216
217    fn to_owned(&self) -> Self::Owned {
218        self.clone()
219    }
220
221    fn into_owned(self) -> Self::Owned {
222        self
223    }
224}
225
226#[cfg(feature = "std")]
227impl<T> ToOwned for std::borrow::Cow<'_, T>
228where
229    T: std::borrow::ToOwned + 'static,
230    T::Owned: Clone,
231{
232    type Owned = std::borrow::Cow<'static, T>;
233
234    fn to_owned(&self) -> std::borrow::Cow<'static, T> {
235        let owned = match self {
236            Self::Borrowed(x) => T::to_owned(x),
237            Self::Owned(x) => x.clone(),
238        };
239
240        std::borrow::Cow::Owned(owned)
241    }
242
243    fn into_owned(self) -> std::borrow::Cow<'static, T> {
244        let owned = match self {
245            Self::Borrowed(x) => T::to_owned(x),
246            Self::Owned(x) => x,
247        };
248
249        std::borrow::Cow::Owned(owned)
250    }
251}
252
253/// A clone-on-write container that contains either the owned or borrowed
254/// version of some data.
255///
256/// Unlike [std::borrow::Cow], this type may hold non-reference types with
257/// internal references in the borrowed variant. `T` is required to implement
258/// [Cowable].
259///
260/// # Notes
261///
262/// - **Important**: The implementations of [PartialEq], [Eq], [PartialOrd] and
263///   [Ord] assume that the results are the same regardless of which combination
264///   of borrowed and owned versions are being compared.
265/// - Some traits cannot have blanket implementations without support for
266///   specialization in Rust, such as the [From] trait. Where possible the
267///   functionality is provided by intrinsic methods instead.
268pub enum Cow<'a, T>
269where
270    T: Cowable,
271{
272    /// Borrowed variant.
273    Borrowed(CowableBorrowed<'a, T>),
274
275    /// Owned variant.
276    Owned(CowableOwned<T>),
277}
278
279impl<'a, T> Cow<'a, T>
280where
281    T: Cowable,
282{
283    /// Create a new [Cow] containing borrowed data.
284    pub fn borrowed(borrowed: impl Into<CowableBorrowed<'a, T>>) -> Self {
285        Self::Borrowed(borrowed.into())
286    }
287
288    /// Create a new [Cow] containing owned data.
289    pub fn owned(owned: impl Into<CowableOwned<T>>) -> Self {
290        Self::Owned(owned.into())
291    }
292
293    /// Return true if the data is borrowed.
294    pub fn is_borrowed(&self) -> bool {
295        matches!(self, Self::Borrowed(_))
296    }
297
298    /// Return true if the data is owned.
299    pub fn is_owned(&self) -> bool {
300        matches!(self, Self::Owned(_))
301    }
302
303    /// Unwrap the borrowed data, panicking if the data is owned.
304    pub fn unwrap_borrowed(self) -> CowableBorrowed<'a, T> {
305        match self {
306            Self::Borrowed(x) => x,
307            Self::Owned(_) => panic!("Cow contains owned data"),
308        }
309    }
310
311    /// Unwrap the owned data, panicking if the data is borrowed.
312    pub fn unwrap_owned(self) -> CowableOwned<T> {
313        match self {
314            Self::Borrowed(_) => panic!("Cow contains borrowed data"),
315            Self::Owned(x) => x,
316        }
317    }
318}
319
320impl<'a, T> Cow<'a, T>
321where
322    T: Cowable,
323    CowableBorrowed<'a, T>: ToOwned<Owned = CowableOwned<T>>,
324{
325    /// If this [Cow] contains and owned value, return a mutable reference to
326    /// it. If it contains a borrowed value, make it owned and return a mutable
327    /// reference to this new value.
328    pub fn to_mut(&mut self) -> &mut CowableOwned<T> {
329        match self {
330            Self::Borrowed(x) => {
331                // TODO: find a way to use `into_owned` here
332                *self = Cow::Owned(x.to_owned());
333
334                match self {
335                    Self::Borrowed(_) => unreachable!(),
336                    Self::Owned(x) => x,
337                }
338            }
339            Self::Owned(x) => x,
340        }
341    }
342
343    /// Unwrap this [Cow] into and owned value, calling [ToOwned::into_owned] if
344    /// the data is borrowed.
345    pub fn into_inner(self) -> CowableOwned<T> {
346        match self {
347            Self::Borrowed(x) => x.into_owned(),
348            Self::Owned(x) => x,
349        }
350    }
351}
352
353impl<'a, T> Borrow<'a, BorrowCow<T>> for Cow<'a, T>
354where
355    T: Cowable,
356    CowableBorrowed<'a, T>: Borrow<'a, T::BorrowHkt>,
357    CowableOwned<T>: Borrow<'a, T::BorrowHkt>,
358{
359    fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowCow<T>>
360    where
361        'a: 'b,
362    {
363        match self {
364            Self::Borrowed(x) => Cow::Borrowed(x.borrow()),
365            Self::Owned(x) => Cow::Borrowed(x.borrow()),
366        }
367    }
368}
369
370impl<'a, T> ToOwned for Cow<'a, T>
371where
372    T: Cowable,
373    CowableBorrowed<'a, T>: ToOwned<Owned = CowableOwned<T>>,
374    CowableOwned<T>: Clone,
375{
376    type Owned = Cow<'static, T>;
377
378    fn to_owned(&self) -> Cow<'static, T> {
379        match self {
380            Self::Borrowed(x) => Cow::Owned(x.to_owned()),
381            Self::Owned(x) => Cow::Owned(x.clone()),
382        }
383    }
384
385    fn into_owned(self) -> Cow<'static, T> {
386        match self {
387            Self::Borrowed(x) => Cow::Owned(x.into_owned()),
388            Self::Owned(x) => Cow::Owned(x),
389        }
390    }
391}
392
393impl<'a, T> Clone for Cow<'a, T>
394where
395    T: Cowable,
396    CowableBorrowed<'a, T>: Clone,
397    CowableOwned<T>: Clone,
398{
399    fn clone(&self) -> Self {
400        match self {
401            Self::Borrowed(x) => Self::Borrowed(x.clone()),
402            Self::Owned(x) => Self::Owned(x.clone()),
403        }
404    }
405}
406
407impl<'a, T> Copy for Cow<'a, T>
408where
409    T: Cowable,
410    CowableBorrowed<'a, T>: Copy,
411    CowableOwned<T>: Copy,
412{
413}
414
415impl<'a, T> Debug for Cow<'a, T>
416where
417    T: Cowable,
418    CowableBorrowed<'a, T>: Debug,
419    CowableOwned<T>: Debug,
420{
421    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
422        match self {
423            Self::Borrowed(x) => x.fmt(f),
424            Self::Owned(x) => x.fmt(f),
425        }
426    }
427}
428
429impl<T> Default for Cow<'_, T>
430where
431    T: Cowable,
432    CowableOwned<T>: Default,
433{
434    fn default() -> Self {
435        Self::Owned(Default::default())
436    }
437}
438
439impl<'a, T> Hash for Cow<'a, T>
440where
441    T: Cowable,
442    CowableBorrowed<'a, T>: Hash,
443    CowableOwned<T>: Hash,
444{
445    fn hash<H: Hasher>(&self, state: &mut H) {
446        match self {
447            Self::Borrowed(x) => x.hash(state),
448            Self::Owned(x) => x.hash(state),
449        }
450    }
451}
452
453impl<'a, T> PartialEq<Cow<'a, T>> for Cow<'a, T>
454where
455    T: Cowable,
456    CowableBorrowed<'a, T>: PartialEq + PartialEq<CowableOwned<T>>,
457    CowableOwned<T>: PartialEq + PartialEq<CowableBorrowed<'a, T>>,
458{
459    fn eq(&self, other: &Cow<'a, T>) -> bool {
460        match (self, other) {
461            (Self::Borrowed(a), Self::Borrowed(b)) => a.eq(b),
462            (Self::Borrowed(a), Self::Owned(b)) => a.eq(b),
463            (Self::Owned(a), Self::Borrowed(b)) => a.eq(b),
464            (Self::Owned(a), Self::Owned(b)) => a.eq(b),
465        }
466    }
467}
468
469impl<'a, T> Eq for Cow<'a, T>
470where
471    T: Cowable,
472    CowableBorrowed<'a, T>: Eq + PartialEq<CowableOwned<T>>,
473    CowableOwned<T>: Eq + PartialEq<CowableBorrowed<'a, T>>,
474{
475}
476
477impl<'a, T> PartialOrd for Cow<'a, T>
478where
479    T: Cowable,
480    CowableBorrowed<'a, T>: PartialOrd + PartialOrd<CowableOwned<T>>,
481    CowableOwned<T>: PartialOrd + PartialOrd<CowableBorrowed<'a, T>>,
482{
483    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
484        match (self, other) {
485            (Self::Borrowed(a), Self::Borrowed(b)) => a.partial_cmp(b),
486            (Self::Borrowed(a), Self::Owned(b)) => a.partial_cmp(b),
487            (Self::Owned(a), Self::Borrowed(b)) => a.partial_cmp(b),
488            (Self::Owned(a), Self::Owned(b)) => a.partial_cmp(b),
489        }
490    }
491
492    fn ge(&self, other: &Self) -> bool {
493        match (self, other) {
494            (Self::Borrowed(a), Self::Borrowed(b)) => a.ge(b),
495            (Self::Borrowed(a), Self::Owned(b)) => a.ge(b),
496            (Self::Owned(a), Self::Borrowed(b)) => a.ge(b),
497            (Self::Owned(a), Self::Owned(b)) => a.ge(b),
498        }
499    }
500
501    fn gt(&self, other: &Self) -> bool {
502        match (self, other) {
503            (Self::Borrowed(a), Self::Borrowed(b)) => a.gt(b),
504            (Self::Borrowed(a), Self::Owned(b)) => a.gt(b),
505            (Self::Owned(a), Self::Borrowed(b)) => a.gt(b),
506            (Self::Owned(a), Self::Owned(b)) => a.gt(b),
507        }
508    }
509
510    fn le(&self, other: &Self) -> bool {
511        match (self, other) {
512            (Self::Borrowed(a), Self::Borrowed(b)) => a.le(b),
513            (Self::Borrowed(a), Self::Owned(b)) => a.le(b),
514            (Self::Owned(a), Self::Borrowed(b)) => a.le(b),
515            (Self::Owned(a), Self::Owned(b)) => a.le(b),
516        }
517    }
518
519    fn lt(&self, other: &Self) -> bool {
520        match (self, other) {
521            (Self::Borrowed(a), Self::Borrowed(b)) => a.lt(b),
522            (Self::Borrowed(a), Self::Owned(b)) => a.lt(b),
523            (Self::Owned(a), Self::Borrowed(b)) => a.lt(b),
524            (Self::Owned(a), Self::Owned(b)) => a.lt(b),
525        }
526    }
527}
528
529impl<'a, T> Ord for Cow<'a, T>
530where
531    T: Cowable,
532    CowableBorrowed<'a, T>: Ord + PartialOrd<CowableOwned<T>>,
533    CowableOwned<T>: Ord + PartialOrd<CowableBorrowed<'a, T>>,
534{
535    fn cmp(&self, other: &Self) -> Ordering {
536        match (self, other) {
537            (Self::Borrowed(a), Self::Borrowed(b)) => a.cmp(b),
538            (Self::Borrowed(a), Self::Owned(b)) => a.partial_cmp(b).unwrap(),
539            (Self::Owned(a), Self::Borrowed(b)) => a.partial_cmp(b).unwrap(),
540            (Self::Owned(a), Self::Owned(b)) => a.cmp(b),
541        }
542    }
543}
544
545/// Marker type implementing [BorrowHkt] for [Cow].
546pub struct BorrowCow<T>(PhantomData<T>);
547
548impl<'a, T> BorrowHkt<'a> for BorrowCow<T>
549where
550    T: Cowable,
551{
552    type T = Cow<'a, T>;
553}
554
555/// Trait for types that can be used with [Cow] through a [BorrowHkt].
556///
557/// This trait is automatically implemented for types that implement
558/// [BorrowHkt] if [BorrowHkt::T] implements [ToOwned] for all lifetimes.
559pub trait Cowable {
560    /// The marker type implementing [BorrowHkt].
561    type BorrowHkt: for<'a> BorrowHkt<'a>;
562
563    /// The owned type.
564    type Owned;
565}
566
567// This implementation relies on Rust's unification to "find" the correct owned
568// type `O` for each `BorrowHkt`
569impl<B, O> Cowable for B
570where
571    B: for<'a> BorrowHkt<'a>,
572    for<'a> <B as BorrowHkt<'a>>::T: ToOwned<Owned = O>,
573{
574    type BorrowHkt = B;
575    type Owned = O;
576}
577
578/// Type alias to extract the concrete borrowed type from a [Cowable].
579pub type CowableBorrowed<'a, T> = Borrowed<'a, <T as Cowable>::BorrowHkt>;
580
581/// Type alias to extract the concrete owned type from a [Cowable].
582pub type CowableOwned<T> = <T as Cowable>::Owned;
583
584// Implement `Borrow`, `BorrowHkt` and `ToOwned` for simple `Copy` types
585macro_rules! simple_type {
586    ($ty:ty) => {
587        impl<'a> Borrow<'a, $ty> for $ty {
588            fn borrow<'b>(&'a self) -> Borrowed<'b, $ty>
589            where
590                'a: 'b,
591            {
592                *self
593            }
594        }
595
596        impl BorrowHkt<'_> for $ty {
597            type T = $ty;
598        }
599
600        impl ToOwned for $ty {
601            type Owned = $ty;
602
603            fn to_owned(&self) -> Self::Owned {
604                *self
605            }
606        }
607    };
608}
609
610simple_type!(());
611simple_type!(bool);
612simple_type!(char);
613simple_type!(i8);
614simple_type!(i16);
615simple_type!(i32);
616simple_type!(i64);
617simple_type!(i128);
618simple_type!(isize);
619simple_type!(u8);
620simple_type!(u16);
621simple_type!(u32);
622simple_type!(u64);
623simple_type!(u128);
624simple_type!(usize);
625simple_type!(f32);
626simple_type!(f64);