ref_cast/
lib.rs

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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`]: https://doc.rust-lang.org/std/ops/trait.Index.html
//!
//! ```
//! # 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.23")]
#![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;
}