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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//! Unified zero-copy trait family.
//!
//! This module consolidates `Pod`, `FixedLayout`, `Projectable`, `SafeProjectable`,
//! `LayoutContract`, header metadata, and schema export into one
//! coherent trait stack. This module delivers the foundation:
//!
//! - [`ZeroCopy`], the canonical "safe to overlay on raw bytes"
//! marker. Equivalent-in-contract to [`Pod`], using
//! Hopper's owned `Pod` / `Zeroable` proof layer.
//! A blanket implementation covers `Pod` types that also carry Hopper's
//! sealed marker, including layouts emitted by Hopper's macros.
//!
//! - [`WireLayout`], a `ZeroCopy` type whose wire size is
//! `size_of::<Self>()` under the current blanket implementation.
//!
//! - [`AccountLayout`], a `WireLayout` that also carries Hopper's
//! account header identity (disc, version, wire fingerprint, schema
//! epoch, type offset). This is the top-level account-layout
//! trait, with an explicit member list so the contract is
//! frozen-in-place for migrations and client generation.
//!
//! ## Why three traits, not one
//!
//! The layering mirrors a real capability hierarchy. Every account
//! layout is a wire layout; every wire layout is zero-copy; but not
//! every zero-copy type is a full account layout (`WireU64`, `WireBool`,
//! `TypedAddress<T>` are zero-copy but carry no header). Splitting
//! the traits lets generic helpers demand just what they need.
//!
//! ## Relation to `LayoutContract`
//!
//! The existing [`crate::layout::LayoutContract`] trait predates this
//! module. `LayoutContract` and `AccountLayout` intentionally overlap:
//! both describe "a Hopper layout with disc/version/layout_id".
//! `AccountLayout` presents the same identity through a unified trait stack.
//! A blanket implementation covers types that implement both
//! `LayoutContract` and `ZeroCopy`.
use crateLayoutContract;
use cratePod;
// ══════════════════════════════════════════════════════════════════════
// Seal
// ══════════════════════════════════════════════════════════════════════
/// Internal marker every framework-defined zero-copy type stamps itself
/// with. Sealed by convention: it lives in a doc-hidden module so
/// downstream code cannot name it except through the canonical
/// Hopper entry points (`#[hopper::pod]`, `#[hopper::state]`,
/// `hopper_layout!`, and the framework's own primitive wire types).
///
/// A user bypassing the macro system with a hand-rolled
/// `unsafe impl Pod for Foo {}` cannot accidentally pick up
/// [`ZeroCopy`] for free. The `ZeroCopy` blanket below additionally
/// requires `HopperZeroCopySealed`, which only framework-defined
/// surfaces implement.
///
/// Users who legitimately need to extend `ZeroCopy` for a custom
/// primitive can declare `unsafe impl ::hopper_runtime::__sealed::HopperZeroCopySealed for MyType {}`
/// manually, but the path-through-doc-hidden-module signals clearly
/// that they are opting out of the macro's field-level proof.
// ══════════════════════════════════════════════════════════════════════
// ZeroCopy
// ══════════════════════════════════════════════════════════════════════
/// Canonical marker for types that may be overlaid on raw bytes.
///
/// # Safety
///
/// The contract is the same four-point obligation as [`Pod`]:
///
/// 1. Every `[u8; size_of::<T>()]` bit pattern decodes to a valid `T`.
/// 2. `align_of::<T>() == 1`.
/// 3. `T` contains no padding.
/// 4. `T` contains no internal pointers or references.
///
/// # Sealing
///
/// `ZeroCopy` is gated behind the doc-hidden
/// [`__sealed::HopperZeroCopySealed`] marker. Types authored through
/// `#[hopper::pod]`, `#[hopper::state]`, `hopper_layout!`, or one of
/// the framework's own primitive wire types (`WireU64`, `WireBool`,
/// `TypedAddress<T>`, etc.) stamp themselves with the seal
/// automatically. A user bypassing the macros with a bare
/// `unsafe impl Pod` does **not** get `ZeroCopy` for free. `ZeroCopy`
/// is implemented only through the framework-owned sealed path.
pub unsafe
// Blanket: any `Pod + 'static` type that also carries the seal gets
// `ZeroCopy`. Every framework-defined surface carries the seal; the
// blanket plus the seal together mean the trait is free for
// framework users and opaque to bypassing code.
unsafe
// ══════════════════════════════════════════════════════════════════════
// WireLayout
// ══════════════════════════════════════════════════════════════════════
/// A `ZeroCopy` type with a compile-time-known wire size.
///
/// The associated constant defaults to `size_of::<Self>()`. The blanket
/// implementation below applies that value to each `ZeroCopy` type.
// Blanket: every `ZeroCopy` type gets `WireLayout` with the default
// `WIRE_SIZE`. Keeps the trait free for user code.
// ══════════════════════════════════════════════════════════════════════
// AccountLayout
// ══════════════════════════════════════════════════════════════════════
/// Hopper account layout identity, the top of the unified trait stack.
///
/// `WIRE_FINGERPRINT` is the first 8 bytes of the canonical SHA-256
/// wire descriptor emitted by the `#[hopper::state]` expansion in the
/// `hopper-derive` package, reinterpreted as a little-endian `u64`, so
/// the runtime can compare against the on-account header byte-for-byte.
///
/// `SCHEMA_EPOCH` defaults to `1`; programs that publish later epochs
/// via their on-chain manifest bump it to signal a version transition.
// Blanket: every `LayoutContract` type automatically is an
// `AccountLayout`. This makes the transition source-compatible -
// `#[hopper::state]` emits `LayoutContract` today; downstream can
// reach for either trait interchangeably.
//
// Fingerprint translation: `LayoutContract::LAYOUT_ID` is already a
// `[u8; 8]` produced by the canonical wire-descriptor hash. We reinterpret
// it as a little-endian `u64` for the `WIRE_FINGERPRINT` slot.