1 unstable release

new 0.1.0 Dec 16, 2024

#1858 in Rust patterns

Download history 117/week @ 2024-12-12

117 downloads per month

MIT license

17KB
294 lines

A no_std set of utilities for more flexible borrowing than the ones provided by the standard library.

Due to Rust's lack of complete support for Higher Kinded Types (HKTs), borrowing is not as powerful as it could be. Even with the introduction of limited Generic Associated Types (GATs) in Rust 1.65, the standard library has not gained useful APIs that take advantage of this functionality for better borrowing.

This crate introduces more flexible traits for working with borrowed data, especially with types containing internal borrows, by relying on the HKT framework introduced by generic-std. Compiler support for GATs is not required.

Features

This crate replaces std::borrow with more flexible types and traits.

More Flexible Borrowing

[Borrow] and [BorrowMut] are similar to the ones provided by the standard library, but the borrowed type may be an arbitrary type. For example, Borrow::borrow might directly return an std::borrow::Cow.

Saner ToOwned

[ToOwned] is not tied to the borrow trait anymore and provides a ToOwned::into_owned method. Also, no blanket implementation for Clone types so something like Cow::<'a, T>::to_owned is finally able to return the much saner Cow<'static, T>.

Clone-On-Write For Types With Internal References

std::borrow::Cow stores either the owned or the borrowed version of another type, but the borrowed variant is required to be a reference. The [Cow] type provided by this crate integrates with [Borrow] and [ToOwned], allowing the borrowed variant to contain a non-reference type with internal references.

Example

Suppose you have a Identifier<'a> type that internally contains either a borrowed or an owned string and you would like to create an Identifier<'static> to store somewhere. This is not possible with std::borrow::ToOwned because std::borrow::ToOwned::Owned must implement std::borrow::Borrow, and std::borrow::Borrow::borrow must return a reference, not Identifier<'a>. But doing this is trivial with this crate's [ToOwned]:

impl<'a> ToOwned for Identifier<'a> {
    type Owned = Identifier<'static>;

    fn to_owned(&self) -> Self::Owned {
        // Returns an `Identifier<'static>`
        # unimplemented!()
    }
}

Similarly, this crate's [Borrow] can return Identifier<'a> directly in addition to normal references:

struct BorrowIdentifier;

impl<'a> BorrowHkt<'a> for BorrowIdentifier {
    type T = Identifier<'a>;
}

impl<'a> Borrow<'a, BorrowIdentifier> for Identifier<'a> {
    fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowIdentifier>
    where
        'a: 'b
    {
        // Returns an `Identifier<'b>`
        # unimplemented!()
    }
}

struct BorrowIdentifierStr;

impl<'a> BorrowHkt<'a> for BorrowIdentifierStr {
    type T = &'a str;
}

impl<'a> Borrow<'a, BorrowIdentifierStr> for Identifier<'a> {
    fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowIdentifierStr>
    where
        'a: 'b
    {
        // Returns a `&'b str`
        # unimplemented!()
    }
}

No runtime deps

Features