Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
{"$comment":"This file only protects against accidental modifications. It is not a security mechanism and does not protect against malicious changes.","files":{".cargo_vcs_info.json":"dbdab8408c56ef8f522225aa32f713ccb29fcea5999c2c5814652b36da18f06f","CHANGELOG.md":"91d40b13c6c4db7c85b061d2aedb4f8195559bdccadf43010b979fa85d9f2750","Cargo.toml":"12af6fdf9d5cd840b40335f36ae5e21c2eed80c4b92ad268cb55cc5b77c7ab34","Cargo.toml.orig":"3bd03379d9e9164f19a7bcc4e3b21ea25420e7b1babafb0258166636450f8609","LICENSE":"b6e8f9bd07084b3ed3a061cd0e9f0c5d5fb46667ef007684c87573a7c8090a34","README.md":"f8e2c8be5cff022d1a3958293ebfb23c5e174f416e959060a90df2d329986bba","src/boxed.rs":"c4f381710fb24569959b20f52525f4b3121faf6038ee7f10c874bb4097695de8","src/lib.rs":"0d97508e89b34fa204f5c7569baaf1f6943dc4768539c905bca43a323cb7da51","src/mut_ref.rs":"102f17dbc2e360b15b1ee4f86622197ec4d5aa6b52da7b52858953c61e0c7070","src/string.rs":"2780c84c5199def8d280d9d4c195bae4b09bf94caf9a825be0a7a6a130b0e990","src/vec.rs":"9025256abed54f0d8fb9e2703bd5f9f5f59902177f392968704d17c8dadf1f4f"},"package":"250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"}
+5
View File
@@ -0,0 +1,5 @@
{
"git": {
"sha1": "ddb6958345aae7fef0686f00a592ef37e944a4ad"
}
}
+13
View File
@@ -0,0 +1,13 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.3] - 2020-01-10
### Added
- `prelude` module.
- `AliasableMut` (thanks [@Koxiaet](https://github.com/Koxiaet)).
+40
View File
@@ -0,0 +1,40 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "aliasable"
version = "0.1.3"
authors = ["avitex <avitex@wfxlabs.com>"]
include = ["src/**/*", "README.md", "CHANGELOG.md", "LICENSE", "Cargo.toml"]
description = "Basic aliasable (non unique pointer) types"
homepage = "https://github.com/avitex/rust-aliasable"
documentation = "https://docs.rs/aliasable"
readme = "README.md"
categories = ["no-std", "data-structures"]
license = "MIT"
repository = "https://github.com/avitex/rust-aliasable"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies.aliasable_deref_trait]
version = "0.2"
optional = true
[dependencies.stable_deref_trait]
version = "1.2"
optional = true
[features]
alloc = []
default = ["alloc"]
traits = ["stable_deref_trait", "aliasable_deref_trait"]
+26
View File
@@ -0,0 +1,26 @@
[package]
name = "aliasable"
version = "0.1.3"
authors = ["avitex <avitex@wfxlabs.com>"]
edition = "2018"
description = "Basic aliasable (non unique pointer) types"
categories = ["no-std", "data-structures"]
documentation = "https://docs.rs/aliasable"
homepage = "https://github.com/avitex/rust-aliasable"
repository = "https://github.com/avitex/rust-aliasable"
license = "MIT"
readme = "README.md"
include = ["src/**/*", "README.md", "CHANGELOG.md", "LICENSE", "Cargo.toml"]
[features]
default = ["alloc"]
alloc = []
traits = ["stable_deref_trait", "aliasable_deref_trait"]
[dependencies]
stable_deref_trait = { version = "1.2", optional = true }
aliasable_deref_trait = { version = "0.2", optional = true }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2020 James Dyson <avitex@wfxlabs.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+36
View File
@@ -0,0 +1,36 @@
[![Build Status](https://github.com/avitex/rust-aliasable/workflows/build/badge.svg)](https://github.com/avitex/rust-aliasable/actions?query=workflow:build)
[![Coverage Status](https://codecov.io/gh/avitex/rust-aliasable/branch/master/graph/badge.svg?token=X2LXHI8VYL)](https://codecov.io/gh/avitex/rust-aliasable)
[![Crate](https://img.shields.io/crates/v/aliasable.svg)](https://crates.io/crates/aliasable)
[![Docs](https://docs.rs/aliasable/badge.svg)](https://docs.rs/aliasable)
# rust-aliasable
**Rust library providing basic aliasable (non `core::ptr::Unique`) types**
Documentation hosted on [docs.rs](https://docs.rs/aliasable).
```toml
aliasable = "0.1"
```
## Why?
Used for escaping `noalias` when multiple raw pointers may point to the same
data.
## Goals
`aliasable` is not designed to provide a full interface for container types,
simply to provide aliasable (non `core::ptr::Unique`) alternatives for
dereferencing their owned data. When converting from a unique to an aliasable
alternative, no data referenced is mutated (one-to-one internal representation
aside from the non `core::ptr::Unique` pointer).
## Usage
```rust
use aliasable::vec::AliasableVec;
// Re-exported via `aliasable::vec::UniqueVec`
let unique = Vec::from(&[1, 2, 3][..]);
let aliasable = AliasableVec::from(unique);
```
+161
View File
@@ -0,0 +1,161 @@
//! Aliasable `Box`.
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr::NonNull;
use core::{fmt, mem};
pub use alloc::boxed::Box as UniqueBox;
/// Basic aliasable (non `core::ptr::Unique`) alternative to
/// [`alloc::boxed::Box`].
pub struct AliasableBox<T: ?Sized>(NonNull<T>);
impl<T: ?Sized> AliasableBox<T> {
/// Construct an `AliasableBox` from a [`UniqueBox`].
pub fn from_unique(ptr: UniqueBox<T>) -> Self {
let ptr = unsafe { NonNull::new_unchecked(UniqueBox::into_raw(ptr)) };
Self(ptr)
}
/// Consumes `self` and converts it into a non-aliasable [`UniqueBox`].
#[inline]
pub fn into_unique(mut ptr: AliasableBox<T>) -> UniqueBox<T> {
// As we are consuming the `Box` structure we can safely assume any
// aliasing has ended and convert the aliasable `Box` back to into an
// unaliasable `UniqueBox`.
let unique = unsafe { ptr.reclaim_as_unique_box() };
// Forget the aliasable `Box` so the allocation behind the `UniqueBox`
// is not deallocated.
mem::forget(ptr);
// Return the `UniqueBox`.
unique
}
/// Convert a pinned [`AliasableBox`] to a `core::ptr::Unique` backed pinned
/// [`UniqueBox`].
pub fn into_unique_pin(pin: Pin<AliasableBox<T>>) -> Pin<UniqueBox<T>> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let aliasable = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableBox::into_unique(aliasable))
}
}
/// Convert a pinned `core::ptr::Unique` backed [`UniqueBox`] to a
/// pinned [`AliasableBox`].
pub fn from_unique_pin(pin: Pin<UniqueBox<T>>) -> Pin<AliasableBox<T>> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let unique = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableBox::from(unique))
}
}
#[inline]
unsafe fn reclaim_as_unique_box(&mut self) -> UniqueBox<T> {
UniqueBox::from_raw(self.0.as_ptr())
}
}
impl<T: ?Sized> From<UniqueBox<T>> for AliasableBox<T> {
fn from(ptr: UniqueBox<T>) -> Self {
Self::from_unique(ptr)
}
}
impl<T: ?Sized> Drop for AliasableBox<T> {
fn drop(&mut self) {
// SAFETY: As `self` is being dropped we can safely assume any aliasing
// has ended and convert the `AliasableBox` back to into an unaliasable
// `UniqueBox` to handle the deallocation.
let _ = unsafe { self.reclaim_as_unique_box() };
}
}
impl<T: ?Sized> Deref for AliasableBox<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
// SAFETY: We own the data, so we can return a reference to it.
unsafe { self.0.as_ref() }
}
}
impl<T: ?Sized> DerefMut for AliasableBox<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
// SAFETY: We own the data, so we can return a reference to it.
unsafe { self.0.as_mut() }
}
}
impl<T: ?Sized> AsRef<T> for AliasableBox<T> {
#[inline]
fn as_ref(&self) -> &T {
&*self
}
}
impl<T: ?Sized> AsMut<T> for AliasableBox<T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
}
}
impl<T: ?Sized> fmt::Debug for AliasableBox<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_ref(), f)
}
}
unsafe impl<T: ?Sized> Send for AliasableBox<T> where T: Send {}
unsafe impl<T: ?Sized> Sync for AliasableBox<T> where T: Sync {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::StableDeref for AliasableBox<T> {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::AliasableDeref for AliasableBox<T> {}
#[cfg(test)]
mod tests {
use super::{AliasableBox, UniqueBox};
use alloc::format;
#[test]
fn test_new() {
let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
assert_eq!(*aliasable, 10);
let unique = AliasableBox::into_unique(aliasable);
assert_eq!(*unique, 10);
}
#[test]
fn test_new_pin() {
let aliasable = AliasableBox::from_unique_pin(UniqueBox::pin(10));
assert_eq!(*aliasable, 10);
let unique = AliasableBox::into_unique_pin(aliasable);
assert_eq!(*unique, 10);
}
#[test]
fn test_refs() {
let mut aliasable = AliasableBox::from_unique(UniqueBox::new(10));
let ptr: *const u8 = &*aliasable;
let as_mut_ptr: *const u8 = aliasable.as_mut();
let as_ref_ptr: *const u8 = aliasable.as_ref();
assert_eq!(ptr, as_mut_ptr);
assert_eq!(ptr, as_ref_ptr);
}
#[test]
fn test_debug() {
let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
assert_eq!(format!("{:?}", aliasable), "10");
}
}
+60
View File
@@ -0,0 +1,60 @@
//! Basic aliasable (non `core::ptr::Unique`) types.
//!
//! # Why?
//!
//! Used for escaping `noalias` when multiple raw pointers may point to the same
//! data.
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![forbid(
clippy::pedantic,
rust_2018_idioms,
anonymous_parameters,
unused_qualifications,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_results,
warnings
)]
#![allow(
clippy::needless_pass_by_value,
clippy::wrong_self_convention,
clippy::must_use_candidate,
clippy::module_name_repetitions
)]
#[cfg(any(test, feature = "alloc"))]
extern crate alloc;
mod mut_ref;
#[cfg(feature = "alloc")]
pub mod boxed;
#[cfg(feature = "alloc")]
pub mod string;
#[cfg(feature = "alloc")]
pub mod vec;
pub use crate::mut_ref::AliasableMut;
/// Export of all types enabled.
pub mod prelude {
#[cfg(feature = "alloc")]
pub use crate::boxed::*;
#[cfg(feature = "alloc")]
pub use crate::string::*;
#[cfg(feature = "alloc")]
pub use crate::vec::*;
pub use crate::mut_ref::*;
}
#[cfg(feature = "traits")]
pub use aliasable_deref_trait::AliasableDeref;
#[cfg(feature = "traits")]
pub use stable_deref_trait::StableDeref;
+160
View File
@@ -0,0 +1,160 @@
//! Aliasable `&mut`.
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr::NonNull;
/// Basic aliasable alternative to `&mut`.
///
/// Note that this does not circumvent the core aliasing rules of Rust; if you use this to create
/// multiple mutable references to a memory location at the same time, that is still UB. This type
/// just adds a few abilities:
///
/// - You may hold any number of `AliasableMut`s and no references to a location.
/// - You may hold any number of `AliasableMut`s and any number of shared references to a location
/// at once.
/// - You may hold any number of `AliasableMut`s and one mutable reference to a location at once.
pub struct AliasableMut<'a, T: ?Sized> {
inner: NonNull<T>,
_lifetime: PhantomData<&'a ()>,
}
impl<'a, T: ?Sized> AliasableMut<'a, T> {
/// Construct an `AliasableMut` from an `&mut`.
#[inline]
pub fn from_unique(ptr: &'a mut T) -> Self {
Self {
inner: NonNull::from(ptr),
_lifetime: PhantomData,
}
}
/// Consumes `self` and converts it into a non-aliasable `&mut`.
#[inline]
pub fn into_unique(ptr: Self) -> &'a mut T {
unsafe { &mut *ptr.inner.as_ptr() }
}
/// Convert a pinned `AliasableMut` to a pinned `&mut`.
pub fn into_unique_pin(pin: Pin<Self>) -> Pin<&'a mut T> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let aliasable = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(Self::into_unique(aliasable))
}
}
/// Convert a pinned `&mut` to a pinned `AliasableMut`.
pub fn from_unique_pin(pin: Pin<&'a mut T>) -> Pin<Self> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let unique = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(Self::from_unique(unique))
}
}
}
impl<'a, T: ?Sized> From<&'a mut T> for AliasableMut<'a, T> {
fn from(ptr: &'a mut T) -> Self {
Self::from_unique(ptr)
}
}
impl<T: ?Sized> Deref for AliasableMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
// SAFETY: It is the callers responsibility to make sure that there are no `&mut`
// references at this point.
unsafe { self.inner.as_ref() }
}
}
impl<T: ?Sized> DerefMut for AliasableMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
// SAFETY: It is the callers responsibility to make sure that there are no `&mut`
// references at this point.
unsafe { self.inner.as_mut() }
}
}
impl<T: ?Sized> AsRef<T> for AliasableMut<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized> AsMut<T> for AliasableMut<'_, T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T: ?Sized> fmt::Debug for AliasableMut<'_, T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
unsafe impl<T: ?Sized> Send for AliasableMut<'_, T> where T: Send {}
unsafe impl<T: ?Sized> Sync for AliasableMut<'_, T> where T: Sync {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::StableDeref for AliasableMut<'_, T> {}
#[cfg(feature = "traits")]
unsafe impl<T: ?Sized> crate::AliasableDeref for AliasableMut<'_, T> {}
#[cfg(test)]
mod tests {
use super::AliasableMut;
use alloc::boxed::Box;
use alloc::format;
use core::pin::Pin;
#[test]
fn test_new() {
let mut data = Box::new(10);
let aliasable = AliasableMut::from_unique(&mut data);
assert_eq!(**aliasable, 10);
let unique = AliasableMut::into_unique(aliasable);
assert_eq!(**unique, 10);
}
#[test]
fn test_new_pin() {
let mut data = Box::new(10);
let data = unsafe { Pin::new_unchecked(&mut data) };
let aliasable = AliasableMut::from_unique_pin(data);
assert_eq!(**aliasable, 10);
let unique = AliasableMut::into_unique_pin(aliasable);
assert_eq!(**unique, 10);
}
#[test]
fn test_refs() {
let mut data = Box::new(10);
let mut aliasable = AliasableMut::from_unique(&mut data);
let ptr: *const Box<u8> = &mut *aliasable;
let as_mut_ptr: *const Box<u8> = aliasable.as_mut();
let as_ref_ptr: *const Box<u8> = aliasable.as_ref();
assert_eq!(ptr, as_mut_ptr);
assert_eq!(ptr, as_ref_ptr);
}
#[test]
fn test_debug() {
let mut data = 10;
let aliasable = AliasableMut::from_unique(&mut data);
assert_eq!(format!("{:?}", aliasable), "10");
}
}
+157
View File
@@ -0,0 +1,157 @@
//! Aliasable `String`.
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::{fmt, str};
use crate::vec::AliasableVec;
pub use alloc::string::String as UniqueString;
/// Basic aliasable (non `core::ptr::Unique`) alternative to
/// [`alloc::string::String`].
pub struct AliasableString(AliasableVec<u8>);
impl AliasableString {
/// Consumes `self` into an [`AliasableVec`] of UTF-8 bytes.
pub fn into_bytes(self) -> AliasableVec<u8> {
self.0
}
/// Construct an `AliasableString` from a [`UniqueString`].
pub fn from_unique(s: UniqueString) -> Self {
Self(s.into_bytes().into())
}
/// Consumes `self` and converts it into a non-aliasable [`UniqueString`].
#[inline]
pub fn into_unique(s: AliasableString) -> UniqueString {
let unique_bytes = s.into_bytes().into();
unsafe { UniqueString::from_utf8_unchecked(unique_bytes) }
}
/// Convert a pinned [`AliasableString`] to a `core::ptr::Unique` backed pinned
/// [`UniqueString`].
pub fn into_unique_pin(pin: Pin<AliasableString>) -> Pin<UniqueString> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let aliasable = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableString::into_unique(aliasable))
}
}
/// Convert a pinned `core::ptr::Unique` backed [`UniqueString`] to a
/// pinned [`AliasableString`].
pub fn from_unique_pin(pin: Pin<UniqueString>) -> Pin<AliasableString> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let unique = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableString::from(unique))
}
}
}
impl From<UniqueString> for AliasableString {
#[inline]
fn from(s: UniqueString) -> Self {
Self::from_unique(s)
}
}
impl From<AliasableString> for UniqueString {
#[inline]
fn from(s: AliasableString) -> Self {
AliasableString::into_unique(s)
}
}
impl Deref for AliasableString {
type Target = str;
#[inline]
fn deref(&self) -> &str {
// SAFETY: `AliasableString` will only ever contain UTF-8.
unsafe { str::from_utf8_unchecked(&*self.0) }
}
}
impl DerefMut for AliasableString {
#[inline]
fn deref_mut(&mut self) -> &mut str {
// SAFETY: `AliasableString` will only ever contain UTF-8.
unsafe { str::from_utf8_unchecked_mut(&mut *self.0) }
}
}
impl AsRef<str> for AliasableString {
#[inline]
fn as_ref(&self) -> &str {
&*self
}
}
impl AsMut<str> for AliasableString {
fn as_mut(&mut self) -> &mut str {
&mut *self
}
}
impl fmt::Debug for AliasableString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_ref(), f)
}
}
#[cfg(feature = "traits")]
unsafe impl crate::StableDeref for AliasableString {}
#[cfg(feature = "traits")]
unsafe impl crate::AliasableDeref for AliasableString {}
#[cfg(test)]
mod tests {
use super::{AliasableString, AliasableVec, UniqueString};
use alloc::{format, vec};
use core::pin::Pin;
#[test]
fn test_new() {
let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
assert_eq!(&*aliasable, &"hello"[..]);
let unique = AliasableString::into_unique(aliasable);
assert_eq!(&*unique, &"hello"[..]);
}
#[test]
fn test_new_pin() {
let aliasable = AliasableString::from_unique_pin(Pin::new(UniqueString::from("hello")));
assert_eq!(&*aliasable, &"hello"[..]);
let unique = AliasableString::into_unique_pin(aliasable);
assert_eq!(&*unique, &"hello"[..]);
}
#[test]
fn test_refs() {
let mut aliasable = AliasableString::from_unique(UniqueString::from("hello"));
let ptr: *const str = &*aliasable;
let as_mut_ptr: *const str = aliasable.as_mut();
let as_ref_ptr: *const str = aliasable.as_ref();
assert_eq!(ptr, as_mut_ptr);
assert_eq!(ptr, as_ref_ptr);
}
#[test]
fn test_debug() {
let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
assert_eq!(format!("{:?}", aliasable), "\"hello\"");
}
#[test]
fn test_into_bytes() {
let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
assert_eq!(
AliasableVec::into_unique(aliasable.into_bytes()),
vec![b'h', b'e', b'l', b'l', b'o']
);
}
}
+180
View File
@@ -0,0 +1,180 @@
//! Aliasable `Vec`.
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::ptr::NonNull;
use core::{fmt, mem, slice};
pub use alloc::vec::Vec as UniqueVec;
/// Basic aliasable (non `core::ptr::Unique`) alternative to
/// [`alloc::vec::Vec`].
pub struct AliasableVec<T> {
ptr: NonNull<T>,
len: usize,
cap: usize,
}
impl<T> AliasableVec<T> {
/// Construct an `AliasableVec` from a [`UniqueVec`].
pub fn from_unique(mut vec: UniqueVec<T>) -> Self {
let ptr = vec.as_mut_ptr();
let len = vec.len();
let cap = vec.capacity();
mem::forget(vec);
let ptr = unsafe { NonNull::new_unchecked(ptr) };
Self { ptr, len, cap }
}
/// Consumes the [`AliasableVec`] and converts it back into a
/// non-aliasable [`UniqueVec`].
#[inline]
pub fn into_unique(mut vec: AliasableVec<T>) -> UniqueVec<T> {
// SAFETY: As we are consuming the `Vec` structure we can safely assume
// any aliasing has ended and convert the aliasable `Vec` back to into
// an unaliasable `UniqueVec`.
let unique = unsafe { vec.reclaim_as_unique_vec() };
// Forget the aliasable `Vec` so the allocation behind the `UniqueVec`
// is not deallocated.
mem::forget(vec);
// Return the `UniqueVec`.
unique
}
/// Convert a pinned [`AliasableVec`] to a `core::ptr::Unique` backed pinned
/// [`UniqueVec`].
pub fn into_unique_pin(pin: Pin<AliasableVec<T>>) -> Pin<UniqueVec<T>> {
// SAFETY: The pointer is not changed, just the container.
unsafe {
let aliasable = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableVec::into_unique(aliasable))
}
}
/// Convert a pinned `core::ptr::Unique` backed [`UniqueVec`] to a
/// pinned [`AliasableVec`].
pub fn from_unique_pin(pin: Pin<UniqueVec<T>>) -> Pin<AliasableVec<T>> {
unsafe {
let unique = Pin::into_inner_unchecked(pin);
Pin::new_unchecked(AliasableVec::from(unique))
}
}
#[inline]
unsafe fn reclaim_as_unique_vec(&mut self) -> UniqueVec<T> {
UniqueVec::from_raw_parts(self.ptr.as_mut(), self.len, self.cap)
}
}
impl<T> From<UniqueVec<T>> for AliasableVec<T> {
#[inline]
fn from(vec: UniqueVec<T>) -> Self {
Self::from_unique(vec)
}
}
impl<T> From<AliasableVec<T>> for UniqueVec<T> {
#[inline]
fn from(vec: AliasableVec<T>) -> Self {
AliasableVec::into_unique(vec)
}
}
impl<T> Drop for AliasableVec<T> {
fn drop(&mut self) {
// As the `Vec` structure is being dropped we can safely assume any
// aliasing has ended and convert the aliasable `Vec` back to into an
// unaliasable `UniqueVec` to handle the deallocation.
let _ = unsafe { self.reclaim_as_unique_vec() };
}
}
impl<T> Deref for AliasableVec<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
// SAFETY: We own the data, so we can return a reference to it.
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
}
impl<T> DerefMut for AliasableVec<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
// SAFETY: We own the data, so we can return a reference to it.
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}
}
impl<T> AsRef<[T]> for AliasableVec<T> {
fn as_ref(&self) -> &[T] {
&*self
}
}
impl<T> AsMut<[T]> for AliasableVec<T> {
fn as_mut(&mut self) -> &mut [T] {
&mut *self
}
}
impl<T> fmt::Debug for AliasableVec<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_ref(), f)
}
}
unsafe impl<T> Send for AliasableVec<T> where T: Send {}
unsafe impl<T> Sync for AliasableVec<T> where T: Sync {}
#[cfg(feature = "traits")]
unsafe impl<T> crate::StableDeref for AliasableVec<T> {}
#[cfg(feature = "traits")]
unsafe impl<T> crate::AliasableDeref for AliasableVec<T> {}
#[cfg(test)]
mod tests {
use super::AliasableVec;
use alloc::{format, vec};
use core::pin::Pin;
#[test]
fn test_new() {
let aliasable = AliasableVec::from_unique(vec![10]);
assert_eq!(&*aliasable, &[10]);
let unique = AliasableVec::into_unique(aliasable);
assert_eq!(&*unique, &[10]);
}
#[test]
fn test_new_pin() {
let aliasable = AliasableVec::from_unique_pin(Pin::new(vec![10]));
assert_eq!(&*aliasable, &[10]);
let unique = AliasableVec::into_unique_pin(aliasable);
assert_eq!(&*unique, &[10]);
}
#[test]
fn test_refs() {
let mut aliasable = AliasableVec::from_unique(vec![10]);
let ptr: *const [u8] = &*aliasable;
let as_mut_ptr: *const [u8] = aliasable.as_mut();
let as_ref_ptr: *const [u8] = aliasable.as_ref();
assert_eq!(ptr, as_mut_ptr);
assert_eq!(ptr, as_ref_ptr);
}
#[test]
fn test_debug() {
let aliasable = AliasableVec::from_unique(vec![10]);
assert_eq!(format!("{:?}", aliasable), "[10]");
}
}