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
//! InnoDB page and file structure constants.
//!
//! These values are derived from the MySQL/InnoDB source code headers:
//! - `fil0fil.h` (FIL header/trailer)
//! - `page0page.h` (page header)
//! - `fsp0fsp.h` (FSP header)
// ── Page sizes ──────────────────────────────────────────────────────
/// Default InnoDB page size (16 KiB).
pub const SIZE_PAGE_DEFAULT: u32 = 16384;
/// 4 KiB page size.
pub const SIZE_PAGE_4K: u32 = 4096;
/// 8 KiB page size.
pub const SIZE_PAGE_8K: u32 = 8192;
/// 16 KiB page size.
pub const SIZE_PAGE_16K: u32 = 16384;
/// 32 KiB page size.
pub const SIZE_PAGE_32K: u32 = 32768;
/// 64 KiB page size.
pub const SIZE_PAGE_64K: u32 = 65536;
// ── FIL Header (38 bytes total) ─────────────────────────────────────
/// Size of the FIL header in bytes.
pub const SIZE_FIL_HEAD: usize = 38;
/// Offset of the checksum (or space id in older formats). 4 bytes.
pub const FIL_PAGE_SPACE_OR_CHKSUM: usize = 0;
/// Offset of the page number within the tablespace. 4 bytes.
pub const FIL_PAGE_OFFSET: usize = 4;
/// Offset of the previous page pointer. 4 bytes.
pub const FIL_PAGE_PREV: usize = 8;
/// Offset of the next page pointer. 4 bytes.
pub const FIL_PAGE_NEXT: usize = 12;
/// Offset of the LSN of newest modification. 8 bytes.
pub const FIL_PAGE_LSN: usize = 16;
/// Offset of the page type field. 2 bytes.
pub const FIL_PAGE_TYPE: usize = 24;
/// Offset of the flush LSN (only page 0 of system tablespace). 8 bytes.
pub const FIL_PAGE_FILE_FLUSH_LSN: usize = 26;
/// Offset of the space ID. 4 bytes.
pub const FIL_PAGE_SPACE_ID: usize = 34;
// ── FIL Trailer (8 bytes total) ─────────────────────────────────────
/// Size of the FIL trailer in bytes.
pub const SIZE_FIL_TRAILER: usize = 8;
// Trailer is at: page_size - SIZE_FIL_TRAILER
// old-style checksum: offset 0 within trailer (4 bytes)
// low 32 bits of LSN: offset 4 within trailer (4 bytes)
/// Start of page data (immediately after FIL header).
pub const FIL_PAGE_DATA: usize = 38;
// ── FSP Header (112 bytes, starts at FIL_PAGE_DATA on page 0) ──────
/// Size of the FSP header in bytes.
pub const FSP_HEADER_SIZE: usize = 112;
/// Offset of the space ID within the FSP header. 4 bytes.
pub const FSP_SPACE_ID: usize = 0;
/// Unused field in the FSP header. 4 bytes.
pub const FSP_NOT_USED: usize = 4;
/// Offset of the tablespace size (in pages) within the FSP header. 4 bytes.
pub const FSP_SIZE: usize = 8;
/// Offset of the minimum page not yet initialized. 4 bytes.
pub const FSP_FREE_LIMIT: usize = 12;
/// Offset of the FSP flags field. 4 bytes.
pub const FSP_SPACE_FLAGS: usize = 16;
/// Offset of the used-page count in the FSP_FREE_FRAG list. 4 bytes.
pub const FSP_FRAG_N_USED: usize = 20;
// ── FSP flags bit positions for page size detection ─────────────────
/// Bit position of the page size field within FSP flags.
pub const FSP_FLAGS_POS_PAGE_SSIZE: u32 = 6;
/// Bitmask for the 4-bit page size field within FSP flags.
pub const FSP_FLAGS_MASK_PAGE_SSIZE: u32 = 0xF << FSP_FLAGS_POS_PAGE_SSIZE;
// ── Page Header (INDEX page specific, starts at FIL_PAGE_DATA) ──────
/// Offset of the directory slot count. 2 bytes.
pub const PAGE_N_DIR_SLOTS: usize = 0;
/// Offset of the record heap top pointer. 2 bytes.
pub const PAGE_HEAP_TOP: usize = 2;
/// Offset of the heap record count (bit 15 = compact flag). 2 bytes.
pub const PAGE_N_HEAP: usize = 4;
/// Offset of the free record list pointer. 2 bytes.
pub const PAGE_FREE: usize = 6;
/// Offset of the deleted-record byte count (garbage). 2 bytes.
pub const PAGE_GARBAGE: usize = 8;
/// Offset of the last-inserted record pointer. 2 bytes.
pub const PAGE_LAST_INSERT: usize = 10;
/// Offset of the last insert direction. 2 bytes.
pub const PAGE_DIRECTION: usize = 12;
/// Offset of the consecutive same-direction insert count. 2 bytes.
pub const PAGE_N_DIRECTION: usize = 14;
/// Offset of the user record count. 2 bytes.
pub const PAGE_N_RECS: usize = 16;
/// Offset of the maximum transaction ID (secondary indexes only). 8 bytes.
pub const PAGE_MAX_TRX_ID: usize = 18;
/// Offset of the B+Tree level (0 = leaf). 2 bytes.
pub const PAGE_LEVEL: usize = 26;
/// Offset of the index ID. 8 bytes.
pub const PAGE_INDEX_ID: usize = 28;
/// Offset of the leaf segment FSEG header. 10 bytes.
pub const PAGE_BTR_SEG_LEAF: usize = 36;
/// Offset of the non-leaf segment FSEG header. 10 bytes.
pub const PAGE_BTR_SEG_TOP: usize = 46;
/// Total INDEX page header size (before FSEG headers).
pub const PAGE_HEADER_SIZE: usize = 56;
// ── FSEG Header ─────────────────────────────────────────────────────
/// Size of an FSEG (file segment) header in bytes.
pub const FSEG_HEADER_SIZE: usize = 10;
// ── Record extra bytes ──────────────────────────────────────────────
/// Extra bytes preceding each record in old-style (redundant) format.
pub const REC_N_OLD_EXTRA_BYTES: usize = 6;
/// Extra bytes preceding each record in new-style (compact) format.
pub const REC_N_NEW_EXTRA_BYTES: usize = 5;
// ── System record offsets (compact pages) ───────────────────────────
/// Computed data offset (FIL_PAGE_DATA + PAGE_HEADER + 2 * FSEG_HEADER).
pub const PAGE_DATA: usize = FIL_PAGE_DATA + PAGE_HEADER_SIZE + 2 * FSEG_HEADER_SIZE;
// Note: the MySQL source uses PAGE_DATA = 38 + 36 + 20 = 94
/// Actual system record data offset matching MySQL source.
pub const PAGE_DATA_OFFSET: usize = 94;
/// Offset of the infimum record (compact format).
pub const PAGE_NEW_INFIMUM: usize = PAGE_DATA_OFFSET + REC_N_NEW_EXTRA_BYTES; // 99
/// Offset of the supremum record (compact format).
pub const PAGE_NEW_SUPREMUM: usize = PAGE_DATA_OFFSET + 2 * REC_N_NEW_EXTRA_BYTES + 8; // 112
/// Offset of the infimum record (redundant format).
pub const PAGE_OLD_INFIMUM: usize = PAGE_DATA_OFFSET + 1 + REC_N_OLD_EXTRA_BYTES; // 101
/// Offset of the supremum record (redundant format).
pub const PAGE_OLD_SUPREMUM: usize = PAGE_DATA_OFFSET + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8; // 112
// ── Special values ──────────────────────────────────────────────────
/// Null page reference (0xFFFFFFFF / 4294967295).
pub const FIL_NULL: u32 = 0xFFFFFFFF;
// ── Checksum constants ──────────────────────────────────────────────
/// First random mask used by `ut_fold_ulint_pair` in legacy InnoDB checksums.
pub const UT_HASH_RANDOM_MASK: u32 = 1463735687;
/// Second random mask used by `ut_fold_ulint_pair` in legacy InnoDB checksums.
pub const UT_HASH_RANDOM_MASK2: u32 = 1653893711;
// ── MariaDB FSP flag constants (fsp0types.h) ────────────────────────
/// MariaDB full_crc32 page size mask (bits 0-3). Same ssize encoding as
/// MySQL but at a different bit position.
pub const MARIADB_FSP_FLAGS_FCRC32_PAGE_SSIZE_MASK: u32 = 0x0F;
/// MariaDB full_crc32 marker (bit 4). When set, the tablespace uses
/// MariaDB's simplified full_crc32 format (10.5+).
pub const MARIADB_FSP_FLAGS_FCRC32_MARKER_MASK: u32 = 0x10;
/// MariaDB full_crc32 compression algorithm mask (bits 5-7).
/// 0 = none, 1 = zlib, 2 = lz4, 3 = lzo, 4 = lzma, 5 = bzip2, 6 = snappy.
pub const MARIADB_FSP_FLAGS_FCRC32_COMPRESSED_ALGO_MASK: u32 = 0xE0;
/// MariaDB original-format page compression flag (bit 16).
/// Not used by MySQL; its presence (with MySQL compression bits zero)
/// indicates MariaDB original format.
pub const MARIADB_FSP_FLAGS_PAGE_COMPRESSION: u32 = 1 << 16;
// ── MariaDB page type constants ─────────────────────────────────────
/// MariaDB page-level compression (replaces MySQL hole-punching type 14).
pub const FIL_PAGE_PAGE_COMPRESSED: u16 = 34354;
/// MariaDB page-level compression + encryption.
pub const FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: u16 = 37401;
/// MariaDB instant ALTER TABLE metadata page.
pub const FIL_PAGE_TYPE_INSTANT: u16 = 18;
// ── Encryption constants ──────────────────────────────────────────
/// Size of the encryption magic marker. 3 bytes.
pub const ENCRYPTION_MAGIC_SIZE: usize = 3;
/// Length of the AES-256 key in bytes (32 bytes = 256 bits).
pub const ENCRYPTION_KEY_LEN: usize = 32;
/// Length of the server UUID string. 36 bytes (ASCII).
pub const ENCRYPTION_SERVER_UUID_LEN: usize = 36;
/// Total size of the encryption info structure on page 0.
/// Layout: magic(3) + master_key_id(4) + uuid(36) + encrypted_key_iv(64) + crc32(4) = 111.
pub const ENCRYPTION_INFO_SIZE: usize = 111;
/// Maximum size of the encryption info area including trailing padding.
pub const ENCRYPTION_INFO_MAX_SIZE: usize = 115;
/// Encryption magic bytes for version 1.
pub const ENCRYPTION_MAGIC_V1: & = b"lCA";
/// Encryption magic bytes for version 2.
pub const ENCRYPTION_MAGIC_V2: & = b"lCB";
/// Encryption magic bytes for version 3 (MySQL 8.0.5+).
pub const ENCRYPTION_MAGIC_V3: & = b"lCC";
/// Offset within the FIL header where the original page type is stored
/// when a page has been encrypted. 2 bytes at offset 26.
pub const FIL_PAGE_ORIGINAL_TYPE_V1: usize = 26;
/// Size of a single XDES (extent descriptor) entry. 40 bytes.
pub const XDES_SIZE: usize = 40;
// ── Insert direction values ─────────────────────────────────────────
/// Insert direction: left.
pub const PAGE_LEFT: u16 = 1;
/// Insert direction: right.
pub const PAGE_RIGHT: u16 = 2;
/// Insert direction: same record position.
pub const PAGE_SAME_REC: u16 = 3;
/// Insert direction: same page.
pub const PAGE_SAME_PAGE: u16 = 4;
/// Insert direction: no direction.
pub const PAGE_NO_DIRECTION: u16 = 5;