ref_cast/
lib.rs

1//! [![github]](https://github.com/dtolnay/ref-cast) [![crates-io]](https://crates.io/crates/ref-cast) [![docs-rs]](https://docs.rs/ref-cast)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! This crate provides a derive macro for generating safe conversions from `&T`
10//! to `&U` where the struct `U` contains a single field of type `T`.
11//!
12//! # Basic example
13//!
14//! ```
15//! use ref_cast::RefCast;
16//!
17//! #[derive(RefCast)]
18//! #[repr(transparent)]
19//! struct U(String);
20//!
21//! fn main() {
22//!     let s = String::new();
23//!
24//!     // Safely cast from `&String` to `&U`.
25//!     let u = U::ref_cast(&s);
26//! }
27//! ```
28//!
29//! Note that `#[repr(transparent)]` is required in order for the conversion to
30//! be sound. The derive macro will refuse to compile if that is not present.
31//!
32//! # Realistic example
33//!
34//! Suppose we have a multidimensional array represented in a flat buffer in
35//! row-major order for performance reasons, but we want to expose an indexing
36//! operation that works in column-major order because it is more intuitive in
37//! the context of our application.
38//!
39//! ```
40//! const MAP_WIDTH: usize = 4;
41//!
42//! struct Tile(u8);
43//!
44//! struct TileMap {
45//!     storage: Vec<Tile>,
46//! }
47//!
48//! // `tilemap[x][y]` should give us `tilemap.storage[y * MAP_WIDTH + x]`.
49//! ```
50//!
51//! The signature of the [`Index`] trait in Rust is such that the output is
52//! forced to be borrowed from the type being indexed. So something like the
53//! following is not going to work.
54//!
55//! [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html
56//!
57//! ```
58//! # const MAP_WIDTH: usize = 4;
59//! #
60//! # struct Tile(u8);
61//! #
62//! # struct TileMap {
63//! #     storage: Vec<Tile>,
64//! # }
65//! #
66//! struct Column<'a> {
67//!     tilemap: &'a TileMap,
68//!     x: usize,
69//! }
70//!
71//! # mod index1 {
72//! #     use super::{TileMap, Column, MAP_WIDTH};
73//! #
74//! #     trait Index<Idx> {
75//! #         fn index(&self, idx: Idx) -> Column;
76//! #     }
77//! #
78//! // Does not work! The output of Index must be a reference that is
79//! // borrowed from self. Here the type Column is not a reference.
80//! impl Index<usize> for TileMap {
81//!     fn index(&self, x: usize) -> Column {
82//!         assert!(x < MAP_WIDTH);
83//!         Column { tilemap: self, x }
84//!     }
85//! }
86//! # }
87//!
88//! # mod index2 {
89//! #     use super::{Column, Tile, MAP_WIDTH};
90//! #     use std::ops::Index;
91//! #
92//! impl<'a> Index<usize> for Column<'a> {
93//!     # type Output = Tile;
94//!     fn index(&self, y: usize) -> &Tile {
95//!         &self.tilemap.storage[y * MAP_WIDTH + self.x]
96//!     }
97//! }
98//! # }
99//! #
100//! # fn main() {}
101//! ```
102//!
103//! Here is a working approach using `RefCast`.
104//!
105//! ```
106//! # use ref_cast::RefCast;
107//! # use std::ops::Index;
108//! #
109//! # const MAP_WIDTH: usize = 4;
110//! #
111//! # struct Tile(u8);
112//! #
113//! # struct TileMap {
114//! #     storage: Vec<Tile>,
115//! # }
116//! #
117//! #[derive(RefCast)]
118//! #[repr(transparent)]
119//! struct Strided([Tile]);
120//!
121//! // Implement `tilemap[x][y]` as `tilemap[x..][y * MAP_WIDTH]`.
122//! impl Index<usize> for TileMap {
123//!     type Output = Strided;
124//!     fn index(&self, x: usize) -> &Self::Output {
125//!         assert!(x < MAP_WIDTH);
126//!         Strided::ref_cast(&self.storage[x..])
127//!     }
128//! }
129//!
130//! impl Index<usize> for Strided {
131//!     type Output = Tile;
132//!     fn index(&self, y: usize) -> &Self::Output {
133//!         &self.0[y * MAP_WIDTH]
134//!     }
135//! }
136//! ```
137
138#![doc(html_root_url = "https://docs.rs/ref-cast/1.0.23")]
139#![no_std]
140#![allow(
141    clippy::extra_unused_type_parameters,
142    clippy::let_underscore_untyped,
143    clippy::manual_assert,
144    clippy::missing_panics_doc,
145    clippy::missing_safety_doc,
146    clippy::module_name_repetitions,
147    clippy::needless_doctest_main,
148    clippy::needless_pass_by_value
149)]
150
151mod custom;
152mod layout;
153mod trivial;
154
155pub use ref_cast_impl::{ref_cast_custom, RefCast, RefCastCustom};
156
157/// Safely cast `&T` to `&U` where the struct `U` contains a single field of
158/// type `T`.
159///
160/// ```
161/// # use ref_cast::RefCast;
162/// #
163/// // `&String` can be cast to `&U`.
164/// #[derive(RefCast)]
165/// #[repr(transparent)]
166/// struct U(String);
167///
168/// // `&T` can be cast to `&V<T>`.
169/// #[derive(RefCast)]
170/// #[repr(transparent)]
171/// struct V<T> {
172///     t: T,
173/// }
174/// ```
175///
176/// See the [crate-level documentation][crate] for usage examples!
177pub trait RefCast {
178    type From: ?Sized;
179    fn ref_cast(from: &Self::From) -> &Self;
180    fn ref_cast_mut(from: &mut Self::From) -> &mut Self;
181}
182
183// Not public API.
184#[doc(hidden)]
185pub mod __private {
186    #[doc(hidden)]
187    pub use crate::custom::{ref_cast_custom, CurrentCrate, RefCastCustom};
188    #[doc(hidden)]
189    pub use crate::layout::{assert_layout, Layout, LayoutUnsized};
190    #[doc(hidden)]
191    pub use crate::trivial::assert_trivial;
192    #[doc(hidden)]
193    pub use core::mem::transmute;
194}