# F1 读取约定

## 公开接口

`read_header(input : Bytes, max_input_bytes? : Int = 64 * 1024 * 1024) -> Int raise ParseError` 只读取输入开头的 9 字节，核对 `REDIS` 和四位 ASCII 十进制版本号，当前只接受格式版本 11。返回成功不表示整个 RDB 文件有效，后续内容即使损坏也不在此 API 的检查范围内。

限制针对整个输入长度，包含头部以后的字节；负数限制返回 `InvalidInputLimit`，超过限制返回 `InputTooLarge`，这两项检查在头部检查之前发生。空输入与短输入返回 `UnexpectedEnd`。API 不进行文件 I/O，输入由调用方持有；这不是分块或恒定内存的文件解析。

`ParseError` 的所有偏移为从输入开头计算的零基字节偏移。`UnexpectedEnd` 记录本次读取开始的位置、所需字节数（UInt64）和剩余字节数。头部的魔数／版本字符错误报告首个错误字节位置，版本不支持时报告版本字段起点 5。可按错误构造器匹配；`to_repr()` 可输出结构化调试信息。

## 内部读取器

`Reader` 不属于公开 API。游标始终满足 `0 <= pos <= input.length()`；读取前比较 `count <= remaining`，比较完成后才把 UInt64 转成 Int 并计算结束位置。对超大长度不会先截断数值，也不会按输入声明的长度分配内存。`read_bytes` 返回原输入的视图。

每个完整读取操作成功后前移游标，失败时不改变本次操作开始位置。复合长度读取使用错误清理恢复游标，错误中的偏移仍指向实际失败的子读取位置。示例：在偏移 1 读到 `0x81` 后缺少 8 字节，错误偏移为 2，游标恢复为 1。

基础数值覆盖：单字节、32 / 64 位无符号小端数、8 / 16 / 32 / 64 位有符号数（多字节采用小端）。32 / 64 位大端读取用于长度字段。浮点数、字符串转换、过期状态及数值业务约束不在 F1 中。

## 长度与字符串标记

参考固定 Redis 提交的 [rdbLoadLenByRef](https://github.com/redis/redis/blob/f60370ce28b946c1146dcea77c9c399d39601aaa/src/rdb.c#L200-L233) 和 [rdbLoadIntegerObject](https://github.com/redis/redis/blob/f60370ce28b946c1146dcea77c9c399d39601aaa/src/rdb.c#L272-L298)，按格式独立实现，未复制或翻译其函数体。

| 首字节 | 解释 |
|---|---|
| `0x00..0x3f` | 低 6 位直接表示长度 |
| `0x40..0x7f` | 低 6 位和下一字节组成 14 位长度 |
| `0x80` | 后跟 4 字节无符号大端长度 |
| `0x81` | 后跟 8 字节无符号大端长度 |
| `0x82..0xbf` | 非法长度标记，明确失败 |
| `0xc0..0xc3` | 分别为整数 8 / 16 / 32 位与 LZF 字符串编码标记 |
| `0xc4..0xff` | 在长度上下文中为未知字符串编码，明确失败 |

普通长度和编码标记使用不同枚举分支；仅允许普通计数的调用会拒绝编码标记，不能把 `0xc3` 当作长度 3。长度解码保留完整 UInt64，包括最大值；这不表示允许按该值分配对象或读取内容。更宽表示中的较小数值与 Redis 加载器一致，允许读取。

以上标记的意义取决于上下文，例如 `0xff` 在文件结构中是 EOF，在长度字段中却是非法字符串编码。F1 没有实现文件操作码调度。解压上限、集合大小上限和对象解码将在对应阶段补充。

## F1 验证边界及 F2 接续

F1 的 20 项测试保留，包含：真实空库文件的头部、头部的全部短前缀、所有非数字版本字节、版本限制、输入大小限制、全部 6 / 14 位长度值、32 / 64 位边界与字节序、全部非法长度／编码标记、数值极值及各宽度的全部短前缀。加入后续文件结构和对象测试后，完整测试命令 `moon test --target native` 当前为 155 项。真实文件读取使用 core 的 async/fs，仅在测试导入中使用。

`read_header` 仍只检查头部。F2 新增的 `parse_empty` 另行验证 AUX、文件结构、EOF 和 CRC64，详见 [empty-snapshot.md](empty-snapshot.md)；对象语义留待后续阶段。
