///|
pub(all) struct Header {
page_size : Int
usable_size : Int
write_version : Int
read_version : Int
change_counter : UInt
declared_pages : UInt
freelist_trunk : UInt
freelist_pages : UInt
schema_cookie : UInt
schema_format : Int
text_encoding : Int
user_version : UInt
application_id : UInt
version_valid_for : UInt
sqlite_version : UInt
} derive(Debug, Eq)
///|
pub extend Header with @debug.Debug::{to_repr}
///|
pub extend Header with Eq::{equal, not_equal}
///|
pub fn parse_header(data : Bytes) -> Header raise SqliteError {
require_range(data, 0, 100)
if data[0:16].to_owned() != b"SQLite format 3\x00" {
raise Invalid("不是 SQLite 3 数据库:magic 不匹配")
}
let raw_size = read_u16(data, 16)
let page_size = if raw_size == 1 { 65536 } else { raw_size }
if page_size < 512 || page_size > 65536 || (page_size & (page_size - 1)) != 0 {
raise Invalid("无效 page_size:\{page_size}")
}
let usable_size = page_size - data[20].to_int()
if usable_size < 480 {
raise Invalid("页面可用空间不足 480 字节")
}
let write_version = data[18].to_int()
let read_version = data[19].to_int()
if read_version != 1 && read_version != 2 {
raise Unsupported("未知文件读取版本")
}
if write_version < 1 {
raise Invalid("无效文件写入版本")
}
if data[21] != 64 || data[22] != 32 || data[23] != 32 {
raise Invalid("无效 payload fractions")
}
let schema_format = bounded_int(
read_u32(data, 44).to_uint64(),
"schema_format",
)
if schema_format > 4 {
raise Unsupported("未知 schema format")
}
let text_encoding = bounded_int(read_u32(data, 56).to_uint64(), "encoding")
if text_encoding < 0 || text_encoding > 3 {
raise Unsupported("未知文本编码")
}
for i = 72; i < 92; i = i + 1 {
if data[i] != 0 {
raise Invalid("数据库头保留字段必须为零")
}
}
{
page_size,
usable_size,
write_version,
read_version,
change_counter: read_u32(data, 24),
declared_pages: read_u32(data, 28),
freelist_trunk: read_u32(data, 32),
freelist_pages: read_u32(data, 36),
schema_cookie: read_u32(data, 40),
schema_format,
text_encoding,
user_version: read_u32(data, 60),
application_id: read_u32(data, 68),
version_valid_for: read_u32(data, 92),
sqlite_version: read_u32(data, 96),
}
}