Skip to content

Commit 038f193

Browse files
authored
Merge pull request #5 from jswrenn/rfc
Safe Transmute RFC
2 parents d01da04 + 3217d4a commit 038f193

7 files changed

+2537
-0
lines changed

rfcs/0000-ext-byte-transmutation.md

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
- Feature Name: byte_transmutations
2+
- Start Date: (fill me in with today's date, YYYY-MM-DD)
3+
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
4+
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
5+
6+
[safer transmutation]: 0000-safe-transmute.md
7+
[zerocopy]: https://crates.io/crates/zerocopy
8+
[bytemuck]: https://crates.io/crates/bytemuck
9+
10+
# Summary
11+
[summary]: #summary
12+
13+
This is a **library extension** to [safer transmutation] (i.e., it does not require additional compiler support) which introduces traits encoding common transmutation-conversions: *byte* transmutations:
14+
- `FromZeros`, implemented if `Self` is initializable from an equivalently-sized array of zeroed bytes.
15+
- `FromBytes`, implemented if `Self` is transmutable into an equivalently-sized array of initialized bytes.
16+
- `IntoBytes`, implemented if `Self` is transmutable from an equivalently-sized array of initialized bytes.
17+
18+
# Motivation
19+
[motivation]: #motivation
20+
Transmutations of types to-and-from equivalently-sized buffers of bytes are perhaps the most common use-case of transmutation; e.g., `FromBytes` and `AsBytes` traits of [zerocopy] form the foundation of Fuchsia's Rust networking stack. These traits can be formulated soundly and completely via [safer transmutation], but the obvious formulations aren't viable; e.g.:
21+
```rust
22+
// `Dst` is `FromBytes` if it can be safely transmuted *from* an
23+
// equivalently sized array of `u8`.
24+
unsafe impl<Dst> FromBytes for Dst
25+
where
26+
Dst: TransmuteFrom<[u8; size_of::<Dst>()]>,
27+
{}
28+
```
29+
At the time of writing, `size_of::<Dst>()` *cannot* appear in this context. Our proposal provides implementation of these traits that do not rely on speculative advancements in const generics.
30+
31+
Together, `IntoBytes` and `FromBytes` can form the basis of a [bytemuck]-like [`PlainOldData` trait](https://docs.rs/bytemuck/1.*/bytemuck/trait.Pod.html):
32+
```rust
33+
/// Implemented by types that are "plain old data":
34+
pub unsafe trait PlainOldData<Neglect=()>
35+
where
36+
Neglect: TransmuteOptions
37+
{}
38+
39+
unsafe impl<T, Neglect> PlainOldData for T
40+
where
41+
T: FromBytes<Neglect> + IntoBytes<Neglect>,
42+
Neglect: TransmuteOptions
43+
{}
44+
```
45+
46+
# Reference-level explanation
47+
[reference-level-explanation]: #reference-level-explanation
48+
49+
The implementations of these traits using [safer transmutation] follows:
50+
51+
## `FromZeros`
52+
Indicates that a type may be transmuted from an appropriately-sized array of zeroed bytes. This trait provide a safe alternative to [`mem::zeroed()`](https://doc.rust-lang.org/core/mem/fn.zeroed.html).
53+
54+
```rust
55+
pub unsafe trait FromZeros<Neglect = ()>
56+
where
57+
Neglect: TransmuteOptions
58+
{
59+
/// Safely initialize `Self` from zeroed bytes.
60+
fn zeroed() -> Self
61+
where
62+
Neglect: SafeTransmuteOptions;
63+
64+
/// Unsafely initialize `Self` from zeroed bytes.
65+
fn unsafe_zeroed() -> Self
66+
where
67+
Neglect: TransmuteOptions;
68+
}
69+
70+
#[derive(Copy, Clone, PromiseTransmutableFrom, PromiseTransmutableInto)]
71+
#[repr(u8)]
72+
enum Zero {
73+
Zero = 0u8
74+
}
75+
76+
unsafe impl<Dst, Neglect> FromZeros<Neglect> for Dst
77+
where
78+
Dst: TransmuteFrom<[Zero; usize::MAX], Neglect>,
79+
Neglect: TransmuteOptions
80+
{
81+
fn zeroed() -> Self
82+
where
83+
Neglect: SafeTransmuteOptions
84+
{
85+
[Zero; size_of::<Self>].transmute_into()
86+
}
87+
88+
unsafe fn unsafe_zeroed() -> Self
89+
where
90+
Neglect: TransmuteOptions
91+
{
92+
[Zero; size_of::<Self>].unsafe_transmute_into()
93+
}
94+
}
95+
```
96+
97+
## `FromBytes`
98+
Indicates that a type may be transmuted from an appropriately-sized array of bytes.
99+
```rust
100+
pub unsafe trait FromBytes<Neglect = ()>
101+
where
102+
Neglect: TransmuteOptions
103+
{}
104+
105+
unsafe impl<Dst, Neglect> FromBytes<Neglect> for Dst
106+
where
107+
Dst: TransmuteFrom<[u8; usize::MAX], Neglect>,
108+
Neglect: TransmuteOptions
109+
{}
110+
```
111+
112+
## `IntoBytes`
113+
Indicates that a type may be transmuted into an appropriately-sized array of bytes.
114+
```rust
115+
#[marker]
116+
pub unsafe trait IntoBytes<Neglect = ()>
117+
where
118+
Neglect: TransmuteOptions
119+
{}
120+
121+
// covers `size_of::<Src>() >= 1`
122+
unsafe impl<Src, Neglect> IntoBytes<Options> for Src
123+
where
124+
[Src: usize::MAX]: TransmuteInto<[u8; usize::MAX], Neglect>,
125+
Neglect: TransmuteOptions
126+
{}
127+
128+
// covers `size_of::<Src>() == 0`
129+
unsafe impl<Src, Neglect> IntoBytes for Src
130+
where
131+
Src: SizeEq<()>,
132+
Neglect: TransmuteOptions
133+
{}
134+
```

0 commit comments

Comments
 (0)