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
//
// Copyright (C) 2020 Nathan Sharp.
//
// This file is available under either the terms of the Apache License, Version
// 2.0 or the MIT License, at your discretion.
//

#![cfg_attr(not(feature = "std"), no_std)]

//! `stable_borrow` provides a marker trait which indicates that the result of
//! [borrows] is address-stable.
//!
//! # Features
//! The `alloc` feature provides impls for compatible types from the [`alloc`
//! crate], which is part of the standard library.
//!
//! The `std` feature provides additional impls for compatible standard-library
//! types not already provided by the `alloc` feature. The `std` feature implies
//! `alloc`, because `alloc` is part of the standard library.
//!
//! # License
//! `stable_borrow` is licensed under the terms of the
//! [Apache License, Version 2.0][Apache2] or the [MIT License][MIT].
//!
//! # Development
//! `stable_borrow` is developed at [GitLab].
//!
//! [`alloc` crate]: alloc
//! [Apache2]: https://www.apache.org/licenses/LICENSE-2.0
//! [borrows]: core::borrow::Borrow::borrow
//! [GitLab]: https://gitlab.com/nwsharp/stable_borrow
//! [MIT]: https://opensource.org/licenses/MIT

#[cfg(feature = "alloc")]
extern crate alloc;

/// A marker trait which indicates that [borrows] are address-stable.
///
/// A type `T: `[`Borrow<U>`] is `StableBorrow<U>` if, for all instances of the
/// type, `x.borrow() as *const U` remains valid to dereference if `x` is moved
/// or immutably borrowed. This is true for most of the standard smart-pointer
/// types, but can be broken by types which borrow from their interior.
///
/// Additionally, if the type implements [`BorrowMut<U>`], `x.borrow_mut() as
/// &U` must be substitutable for `x.borrow()`.
///
/// # Safety
/// This trait is `unsafe` to implement because unsafe code is permitted to rely
/// on the guarantee made by this trait.
///
/// [`Borrow<U>`]: core::borrow::Borrow
/// [`BorrowMut<U>`]: core::borrow::BorrowMut
/// [borrows]: core::borrow::Borrow::borrow
/// [impls]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html#Implementors
pub unsafe trait StableBorrow<T: ?Sized>: core::borrow::Borrow<T> {}

unsafe impl<T: ?Sized> StableBorrow<T> for &T {}
unsafe impl<T: ?Sized> StableBorrow<T> for &mut T {}

#[cfg(feature = "alloc")]
unsafe impl StableBorrow<str> for alloc::string::String {}

#[cfg(feature = "alloc")]
unsafe impl<'a, T: alloc::borrow::ToOwned + ?Sized> StableBorrow<T> for alloc::borrow::Cow<'a, T>
    where T::Owned: StableBorrow<T> {}

#[cfg(feature = "alloc")]
unsafe impl<T> StableBorrow<[T]> for alloc::vec::Vec<T> {}

#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized> StableBorrow<T> for alloc::boxed::Box<T> {}

#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized> StableBorrow<T> for alloc::rc::Rc<T> {}

#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized> StableBorrow<T> for alloc::sync::Arc<T> {}

#[cfg(feature = "std")]
unsafe impl StableBorrow<std::ffi::CStr> for std::ffi::CString {}

#[cfg(feature = "std")]
unsafe impl StableBorrow<std::ffi::OsStr> for std::ffi::OsString {}

#[cfg(feature = "std")]
unsafe impl StableBorrow<std::path::Path> for std::path::PathBuf {}