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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
//! # Key Encoding Helpers for Storage Backends
//!
//! This module provides functions that construct byte-level keys for every
//! higher-level store (offset, log, deduplication, snapshot). All keys use a
//! two-level namespace of the form `<topic_name>\x00<sub_key>`, where `\x00`
//! is the [`SEP`] separator byte.
//!
//! ## Why a Separator Byte?
//!
//! The null byte (`\x00`) acts as an unambiguous boundary between the topic
//! name and the sub-key. This prevents prefix collisions: scanning entries for
//! `"room/5"` will never accidentally match entries for `"room/50"` because
//! the prefix scanned is `room/5\x00`, not the raw string `room/5`.
//!
//! ## Key Formats
//!
//! | Store | Key format | Produced by |
//! |-------|-----------|-------------|
//! | Offset | `<topic>\x00head` | [`offset_key`] |
//! | Log | `<topic>\x00<offset:020>` | [`log_key`] |
//! | Dedupe | `<topic>\x00<message_id>\x00` | [`dedupe_key`] |
//! | Snapshot | `<topic>\x00<snapshot_id>` | [`snapshot_key`] |
//!
//! Each store also has a corresponding `*_prefix` function that returns the
//! topic portion of the key (everything up to and including the separator),
//! suitable for use with [`StorageEngine::scan_prefix`](crate::storage::StorageEngine::scan_prefix).
//!
//! ## Lexicographic Ordering
//!
//! Log offsets are zero-padded to 20 digits so that lexicographic byte
//! ordering matches numeric ordering. This allows efficient range scans
//! over sorted key-value backends (e.g. sled) without a secondary index.
/// Separator byte placed between the topic name and the sub-key in every
/// encoded key. Using `\x00` (NUL) ensures that topic prefixes never collide
/// with each other regardless of their content.
pub const SEP: u8 = 0x00;
// ── Offset keys ──────────────────────────────────────────────
/// Build the key for a topic's current head offset.
///
/// The head offset is the highest offset that has been allocated for the
/// topic. The resulting key has the format `<topic>\x00head`.
///
/// # Parameters
///
/// - `topic` -- the topic name.
///
/// # Returns
///
/// A `Vec<u8>` containing the encoded key.
/// Build a prefix that matches all entries belonging to `topic` in the
/// offset namespace.
///
/// This prefix is passed to
/// [`StorageEngine::scan_prefix`](crate::storage::StorageEngine::scan_prefix)
/// to retrieve every offset-related entry for the given topic.
///
/// # Parameters
///
/// - `topic` -- the topic name.
// ── Log keys ─────────────────────────────────────────────────
/// Build the key for a single log entry at the given `offset`.
///
/// The offset is zero-padded to 20 decimal digits so that lexicographic
/// byte ordering matches numeric ordering. The resulting key has the format
/// `<topic>\x00<offset:020>`.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// - `offset` -- the numeric offset of the log entry.
///
/// # Returns
///
/// A `Vec<u8>` containing the encoded key, ready for point lookups or
/// range scans.
/// Build a prefix that matches all log entries belonging to `topic`.
///
/// Pass this to
/// [`StorageEngine::scan_prefix`](crate::storage::StorageEngine::scan_prefix)
/// to retrieve every log entry for the given topic.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// Build the **inclusive** start key for a log range scan beginning at
/// `from`.
///
/// This is equivalent to calling [`log_key`] with the `from` offset. It is
/// the lower bound of a `[from, to]` range query.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// - `from` -- the first offset to include in the range.
/// Build the **exclusive** end key for a log range scan ending at `to`.
///
/// The returned key is one byte past the key for offset `to`, so that a
/// prefix scan up to (but not including) this key will include `to` but
/// exclude `to + 1`. This is achieved by appending a `0xFF` byte to the
/// standard log key.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// - `to` -- the last offset to include in the range.
// ── Dedupe keys ──────────────────────────────────────────────
/// Build the key for a single deduplication entry.
///
/// The resulting key has the format `<topic>\x00<message_id>\x00`. The
/// trailing separator ensures that entries for different message IDs under
/// the same topic are cleanly separated.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// - `message_id` -- the deduplication key (typically a unique message ID).
/// Build a prefix that matches all deduplication entries belonging to
/// `topic`.
///
/// Pass this to
/// [`StorageEngine::scan_prefix`](crate::storage::StorageEngine::scan_prefix)
/// to iterate over every deduplication entry for the given topic (e.g. for
/// sweeping expired entries).
///
/// # Parameters
///
/// - `topic` -- the topic name.
// ── Snapshot keys ────────────────────────────────────────────
/// Build the key for a single snapshot entry.
///
/// The resulting key has the format `<topic>\x00<snapshot_id>`. Each topic
/// stores at most one snapshot at a time; capturing a new snapshot replaces
/// the previous one.
///
/// # Parameters
///
/// - `topic` -- the topic name.
/// - `snapshot_id` -- the unique identifier for the snapshot.
/// Build a prefix that matches all snapshot entries belonging to `topic`.
///
/// Pass this to
/// [`StorageEngine::scan_prefix`](crate::storage::StorageEngine::scan_prefix)
/// to list or delete all snapshots for the given topic.
///
/// # Parameters
///
/// - `topic` -- the topic name.