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
//! Stage artifact keys (Davinci P5-1a): the content identity every cache of
//! a stage artifact keys on.
//!
//! An [`ArtifactKey`] names one stage artifact of one SFC block — its L0
//! source block, its L1 surface page, its L2 page — by content, in the shape
//! of Doctor's `cache_identity` (domain-separated, versioned, explicit):
//!
//! - **Normalized structure, not presentation.** The hash walks the
//! artifact's canonical page: the Disegno folio `Full` form for L2, the
//! lossless render for L1 (L1's page — a lossless tree's page *is* its
//! token sequence). `Full` is the injective form the folio laws pin, so
//! two artifacts share a key exactly when their pages are equal.
//! - **Span-relative.** Every span enters the hash rebased to the start of
//! its block ([`rebase`], the rustc relative-span import); the block's
//! absolute position is L0 side-table data *outside* the key. An edit
//! above a block therefore changes zero keys of that block, and identical
//! block content keys identically at any offset.
//! - **Versioned.** `schema_version` sits inside every key *and* inside the
//! hashed domain prefix. Changing a page grammar or a key recipe bumps the
//! stage's entry in [`schema`], which changes every key of that stage.
//! - **Platform-stable.** Every value is fed as an explicit little-endian
//! fixed-width encoding into XXH3-128 ([`StableHasher128`]); nothing goes
//! through `core::hash::Hash`, whose `usize` lengths differ by target. The
//! TS-43 goldens pin the exact keys, and the Linux and macOS CI lanes both
//! check them.
//!
//! Ambient inputs — tsconfig content, toolchain and Corsa versions, feature
//! flags, platform — are not artifact content; they fold in through the key
//! manifest (P5-1b), never by widening a page.
//!
//! [`StableHasher128`]: vize_l0::hash::StableHasher128
use fmt;
use Span;
use crateStage;
pub
pub use source_block_key;
pub use ;
pub use KeySink;
/// Key-recipe versions, one per keyed stage artifact.
///
/// A version names both the page grammar the hash walks and the feeding
/// recipe. Bump it in the same change that alters either; the TS-43 goldens
/// fail otherwise, which is the point.
/// A stage artifact with a content key.
///
/// Implementations feed an **injective** encoding of the artifact's
/// canonical page: a folio `Full` print (injective by the folio laws)
/// streamed through [`fmt::Write`], or length-prefixed typed fields. Spans
/// go through [`KeySink::feed_span`] or [`rebase`] against
/// [`KeySink::block_start`], never raw.
/// The content key of one stage artifact of one block.
///
/// Equal keys mean equal canonical pages (up to the 128-bit collision
/// bound) under the same stage and recipe version. Keys are plain data:
/// `Copy`, totally ordered, and printed as `l2.v2:<32 hex digits>`.
/// Rebase a file-absolute `span` to block-relative offsets.
///
/// `None` when the span reaches before `block_start` — an out-of-block span
/// has no relative form, so keyers feed it absolute under a distinct marker
/// instead of letting [`Span::to_block_relative`] saturate two different
/// spans onto one. Well-formed stage artifacts never produce one.
pub const