diff options
Diffstat (limited to 'vendor/ref-cast/src/lib.rs')
| -rw-r--r-- | vendor/ref-cast/src/lib.rs | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/vendor/ref-cast/src/lib.rs b/vendor/ref-cast/src/lib.rs new file mode 100644 index 00000000..71914feb --- /dev/null +++ b/vendor/ref-cast/src/lib.rs @@ -0,0 +1,194 @@ +//! [![github]](https://github.com/dtolnay/ref-cast) [![crates-io]](https://crates.io/crates/ref-cast) [![docs-rs]](https://docs.rs/ref-cast) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//! <br> +//! +//! This crate provides a derive macro for generating safe conversions from `&T` +//! to `&U` where the struct `U` contains a single field of type `T`. +//! +//! # Basic example +//! +//! ``` +//! use ref_cast::RefCast; +//! +//! #[derive(RefCast)] +//! #[repr(transparent)] +//! struct U(String); +//! +//! fn main() { +//! let s = String::new(); +//! +//! // Safely cast from `&String` to `&U`. +//! let u = U::ref_cast(&s); +//! } +//! ``` +//! +//! Note that `#[repr(transparent)]` is required in order for the conversion to +//! be sound. The derive macro will refuse to compile if that is not present. +//! +//! # Realistic example +//! +//! Suppose we have a multidimensional array represented in a flat buffer in +//! row-major order for performance reasons, but we want to expose an indexing +//! operation that works in column-major order because it is more intuitive in +//! the context of our application. +//! +//! ``` +//! const MAP_WIDTH: usize = 4; +//! +//! struct Tile(u8); +//! +//! struct TileMap { +//! storage: Vec<Tile>, +//! } +//! +//! // `tilemap[x][y]` should give us `tilemap.storage[y * MAP_WIDTH + x]`. +//! ``` +//! +//! The signature of the [`Index`] trait in Rust is such that the output is +//! forced to be borrowed from the type being indexed. So something like the +//! following is not going to work. +//! +//! [`Index`]: core::ops::Index +//! +//! ``` +//! # const MAP_WIDTH: usize = 4; +//! # +//! # struct Tile(u8); +//! # +//! # struct TileMap { +//! # storage: Vec<Tile>, +//! # } +//! # +//! struct Column<'a> { +//! tilemap: &'a TileMap, +//! x: usize, +//! } +//! +//! # mod index1 { +//! # use super::{TileMap, Column, MAP_WIDTH}; +//! # +//! # trait Index<Idx> { +//! # fn index(&self, idx: Idx) -> Column; +//! # } +//! # +//! // Does not work! The output of Index must be a reference that is +//! // borrowed from self. Here the type Column is not a reference. +//! impl Index<usize> for TileMap { +//! fn index(&self, x: usize) -> Column { +//! assert!(x < MAP_WIDTH); +//! Column { tilemap: self, x } +//! } +//! } +//! # } +//! +//! # mod index2 { +//! # use super::{Column, Tile, MAP_WIDTH}; +//! # use std::ops::Index; +//! # +//! impl<'a> Index<usize> for Column<'a> { +//! # type Output = Tile; +//! fn index(&self, y: usize) -> &Tile { +//! &self.tilemap.storage[y * MAP_WIDTH + self.x] +//! } +//! } +//! # } +//! # +//! # fn main() {} +//! ``` +//! +//! Here is a working approach using `RefCast`. +//! +//! ``` +//! # use ref_cast::RefCast; +//! # use std::ops::Index; +//! # +//! # const MAP_WIDTH: usize = 4; +//! # +//! # struct Tile(u8); +//! # +//! # struct TileMap { +//! # storage: Vec<Tile>, +//! # } +//! # +//! #[derive(RefCast)] +//! #[repr(transparent)] +//! struct Strided([Tile]); +//! +//! // Implement `tilemap[x][y]` as `tilemap[x..][y * MAP_WIDTH]`. +//! impl Index<usize> for TileMap { +//! type Output = Strided; +//! fn index(&self, x: usize) -> &Self::Output { +//! assert!(x < MAP_WIDTH); +//! Strided::ref_cast(&self.storage[x..]) +//! } +//! } +//! +//! impl Index<usize> for Strided { +//! type Output = Tile; +//! fn index(&self, y: usize) -> &Self::Output { +//! &self.0[y * MAP_WIDTH] +//! } +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/ref-cast/1.0.24")] +#![no_std] +#![allow( + clippy::extra_unused_type_parameters, + clippy::let_underscore_untyped, + clippy::manual_assert, + clippy::missing_panics_doc, + clippy::missing_safety_doc, + clippy::module_name_repetitions, + clippy::needless_doctest_main, + clippy::needless_pass_by_value +)] + +mod custom; +mod layout; +mod trivial; + +pub use ref_cast_impl::{ref_cast_custom, RefCast, RefCastCustom}; + +/// Safely cast `&T` to `&U` where the struct `U` contains a single field of +/// type `T`. +/// +/// ``` +/// # use ref_cast::RefCast; +/// # +/// // `&String` can be cast to `&U`. +/// #[derive(RefCast)] +/// #[repr(transparent)] +/// struct U(String); +/// +/// // `&T` can be cast to `&V<T>`. +/// #[derive(RefCast)] +/// #[repr(transparent)] +/// struct V<T> { +/// t: T, +/// } +/// ``` +/// +/// See the [crate-level documentation][crate] for usage examples! +pub trait RefCast { + type From: ?Sized; + fn ref_cast(from: &Self::From) -> &Self; + fn ref_cast_mut(from: &mut Self::From) -> &mut Self; +} + +// Not public API. +#[doc(hidden)] +pub mod __private { + #[doc(hidden)] + pub use crate::custom::{ref_cast_custom, CurrentCrate, RefCastCustom}; + #[doc(hidden)] + pub use crate::layout::{assert_layout, Layout, LayoutUnsized}; + #[doc(hidden)] + pub use crate::trivial::assert_trivial; + #[doc(hidden)] + pub use core::mem::transmute; +} |
