summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Lam <yukl@google.com>2023-02-09 21:51:50 +0000
committerMaurice Lam <yukl@google.com>2023-02-09 21:52:34 +0000
commit6c71cc3835a332225f80cd000480b93488908d53 (patch)
treead37f0ccb6bc1e2e0d6ca1b305974b6b6a4914b6
parente03c0304d7cd1620795cdf4decf1bd4e90304a8a (diff)
downloadaliasable-6c71cc3835a332225f80cd000480b93488908d53.tar.gz
Import aliasable crate
Bug: 267375624 Test: None, this CL doesn't add any build files yet Change-Id: I04115d35c7bf19abba9f76bb177a3e2d19069b94
-rw-r--r--.cargo_vcs_info.json5
-rw-r--r--CHANGELOG.md13
-rw-r--r--Cargo.toml40
-rw-r--r--Cargo.toml.orig26
-rw-r--r--LICENSE21
-rw-r--r--METADATA19
-rw-r--r--MODULE_LICENSE_MIT0
-rw-r--r--OWNERS1
-rw-r--r--README.md36
-rw-r--r--src/boxed.rs161
-rw-r--r--src/lib.rs60
-rw-r--r--src/mut_ref.rs160
-rw-r--r--src/string.rs157
-rw-r--r--src/vec.rs180
14 files changed, 879 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..608f0a2
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+ "git": {
+ "sha1": "ddb6958345aae7fef0686f00a592ef37e944a4ad"
+ }
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..58bfeb5
--- /dev/null
+++ b/CHANGELOG.md
@@ -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)).
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..db72cd2
--- /dev/null
+++ b/Cargo.toml
@@ -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"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..d845db2
--- /dev/null
+++ b/Cargo.toml.orig
@@ -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"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..097846f
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..4dc4499
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "aliasable"
+description: "Basic aliasable (non unique pointer) types"
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://crates.io/crates/aliasable"
+ }
+ url {
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/aliasable/aliasable-0.1.3.crate"
+ }
+ version: "0.1.3"
+ license_type: NOTICE
+ last_upgrade_date {
+ year: 2023
+ month: 2
+ day: 9
+ }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..45dc4dd
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c008bc9
--- /dev/null
+++ b/README.md
@@ -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);
+```
diff --git a/src/boxed.rs b/src/boxed.rs
new file mode 100644
index 0000000..3455fbd
--- /dev/null
+++ b/src/boxed.rs
@@ -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");
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f96c25a
--- /dev/null
+++ b/src/lib.rs
@@ -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;
diff --git a/src/mut_ref.rs b/src/mut_ref.rs
new file mode 100644
index 0000000..c901db3
--- /dev/null
+++ b/src/mut_ref.rs
@@ -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");
+ }
+}
diff --git a/src/string.rs b/src/string.rs
new file mode 100644
index 0000000..f9864af
--- /dev/null
+++ b/src/string.rs
@@ -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']
+ );
+ }
+}
diff --git a/src/vec.rs b/src/vec.rs
new file mode 100644
index 0000000..d6abb5d
--- /dev/null
+++ b/src/vec.rs
@@ -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]");
+ }
+}