pagelens

    Read-only SQLite database and WAL file analyzer written in MoonBit

    sqlite
    wal
    database
    forensics
    parser
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    8

    Dependencies

    #PageLens

    PageLens is a read-only SQLite database file and write-ahead log (WAL) analyzer written primarily in MoonBit.

    It parses bytes directly. It does not execute SQL and never modifies the database or WAL supplied by the user.

    #Why PageLens

    SQLite is often embedded behind an application, so a failed migration, a truncated copy, or an unexpected WAL can be hard to reason about without opening the database in a full SQL engine. PageLens exposes the on-disk structures themselves: headers, pages, B-trees, records, overflow chains, freelists, WAL transactions, and committed page overlays.

    The project is useful for file-format learning, database fault diagnosis, consistency triage, recovery teaching, and deterministic local inspection. Its boundary is deliberately narrow: offline, read-only structural analysis.

    #Features

    • Bounds-checked binary reader with big/little-endian integers, signed conversions, slicing, offset management, truncation errors, and SQLite varints.
    • Strict parsing of the 100-byte SQLite database header and all requested metadata fields.
    • Page addressing, all four B-tree page types, cell pointer arrays, freeblocks, fragmented bytes, payload layout, and child-page traversal.
    • SQLite record headers and serial types: NULL, signed integers, IEEE-754 floats, UTF-8/UTF-16 text, blobs, and the special integer constants.
    • Overflow payload sizing and guarded chain traversal with range, cycle, duplicate, and premature-end checks.
    • Freelist trunk/leaf traversal with count, loop, duplicate-reference, and header-consistency diagnostics.
    • WAL headers, both checksum byte orders, frame salts, rolling checksums, commit boundaries, transaction grouping, truncated tails, and uncommitted frames.
    • Immutable database/WAL snapshots at the newest valid commit, latest-frame page lookup, and byte-range change summaries.
    • INFO, WARNING, and ERROR consistency findings across database, B-tree, record, overflow, freelist, ownership, and WAL structures.
    • Human-readable and machine-readable JSON output.
    • Reproducible SQLite fixtures and CI smoke tests for every CLI command.

    #Installation

    Prerequisites:

    • A current stable MoonBit toolchain providing moon, moonc, and moonrun.
    • A native C toolchain when using the native CLI target.
    • Python 3 only when regenerating the example SQLite fixtures.

    Clone and resolve the one declared dependency:

    git clone https://github.com/geniuszby/pagelens.git cd pagelens moon update

    After the first mooncakes.io release, the library can be added to another MoonBit module with:

    moon add geniuszby/pagelens@0.1.0

    #Quick Start

    Generate the project-owned example databases, then inspect one:

    python3 scripts/generate_fixtures.py moon run --target native cmd/pagelens -- inspect fixtures/generated/sample.db

    On Windows, use python instead of python3 when that is the installed command. Fixture generation is optional when analyzing your own files.

    #Usage

    pagelens inspect <database> [--json] pagelens wal <wal-file> [--json] pagelens snapshot <database> [--wal <wal-file>] [--json] pagelens check <database> [--wal <wal-file>] [--json]

    During development, replace pagelens with:

    moon run --target native cmd/pagelens --

    The snapshot and check commands look for database-path-wal by default. Pass --wal to select another file. Check succeeds without a WAL when the default file does not exist; snapshot requires a WAL.

    #CLI

    #Inspect a database

    moon run --target native cmd/pagelens -- inspect app.db moon run --target native cmd/pagelens -- inspect app.db --json

    The report includes every database-header field, physical page count, page 1 layout, schema B-tree reachability, freelist totals, and diagnostics.

    #Inspect a WAL

    moon run --target native cmd/pagelens -- wal app.db-wal

    Each frame reports its page number, commit database size, salt validity, and rolling-checksum validity. Frames are grouped into committed transactions or an uncommitted tail.

    #Build a committed snapshot

    moon run --target native cmd/pagelens -- snapshot app.db moon run --target native cmd/pagelens -- snapshot app.db --wal saved.wal --json

    Only valid frames at or before the newest valid commit boundary are overlaid. The command reports changed pages and byte ranges; it does not write a merged database.

    #Check consistency

    moon run --target native cmd/pagelens -- check app.db moon run --target native cmd/pagelens -- check app.db --wal app.db-wal --json

    Exit status is 0 when no ERROR diagnostic exists, 1 for a completed check with errors, and 2 for invalid command usage or an input that cannot be parsed.

    #Examples

    The generator creates four license-clean cases under fixtures/generated:

    • sample.db: tables, index records, deleted space, UTF-8 text, blobs, and an overflow payload.
    • snapshot.db plus snapshot.db-wal: a committed five-frame WAL pair.
    • invalid-magic.db: a database with a damaged magic header.
    • truncated.db: a deliberately shortened database.

    The current generated WAL produces five valid frames, two transactions, and three changed pages in the committed snapshot. See examples/README.md for copyable commands and expected facts. CI regenerates these files and runs all four commands.

    #Architecture

    file bytes -> BinaryReader -> database header / page layout -> B-tree cells / records / overflow / freelist -> WAL frames and commit boundaries -> immutable SnapshotView -> IntegrityReport -> text or JSON CLI reports

    The core library accepts immutable Bytes values and has no filesystem write API. Filesystem access exists only in cmd/pagelens. Major source files map directly to responsibilities:

    • binary.mbt and error.mbt: safe primitives and typed errors.
    • header.mbt and page.mbt: database and page metadata.
    • btree.mbt, record.mbt, overflow.mbt, freelist.mbt: storage structures.
    • wal.mbt and snapshot.mbt: WAL validation and committed overlays.
    • checker.mbt and report.mbt: aggregate analysis and presentation.
    • cmd/pagelens: argument parsing and read-only file loading.

    More detail is available in docs/architecture.md and docs/sqlite-format.md.

    #Testing

    Run the same checks used by CI:

    moon fmt --check moon check --deny-warn moon build moon test --deny-warn python3 scripts/generate_fixtures.py moon run --target native cmd/pagelens -- check fixtures/generated/sample.db

    The suite covers valid and damaged headers, empty/truncated/non-SQLite inputs, varint boundaries, all B-tree page classes, records and serial types, overflow chains, freelists, WAL checksums and commit boundaries, snapshots, error aggregation, and report rendering. See docs/testing.md.

    #Build

    Portable library build:

    moon build --deny-warn

    Native command-line build:

    moon build --target native --deny-warn

    Packaging preview:

    moon package --list moon publish --dry-run

    #Limitations

    • PageLens is not a SQL parser or execution engine.
    • It never writes, repairs, checkpoints, or recovers a database.
    • Rollback journals and the transient WAL-index/shm format are not parsed.
    • Pointer-map and lock-byte pages are reported as unclassified rather than decoded.
    • Encrypted or application-transformed SQLite pages are not decrypted.
    • Text decoding is loss-tolerant; the checker focuses on structural bounds and serial-type validity rather than proving semantic text correctness.
    • The first release provides structural recovery evidence, not a complete forensic or automated data-recovery product.

    #Roadmap

    • Detailed pointer-map reports for auto-vacuum databases.
    • Schema-object listing and optional row-oriented exploration.
    • User-selectable historical committed WAL boundaries.
    • Streaming access for files too large to hold in one immutable byte buffer.
    • Stable library API documentation generated for mooncakes.io.

    #Contributing

    Open an issue before changing the supported file-format boundary. Contributions should include focused tests, preserve read-only behavior, pass formatting, check, build, and test, and document any new dependency and its license. Do not commit private databases or files containing personal information.

    #License

    PageLens is licensed under the Apache License 2.0. See LICENSE. The only runtime dependency is moonbitlang/x, also Apache-2.0. The parser is an original implementation based on SQLite's public file-format specification; it does not contain SQLite or third-party parser source. Full attribution and dependency notes are in docs/third-party-notices.md.

    ParseError

    pub(all) suberror ParseError {
    UnexpectedEnd(Int, Int, Int, String)
    InvalidRange(Int, Int, Int, String)
    InvalidMagic(String, String)
    InvalidValue(Int, String, String)
    InvalidPageNumber(UInt64, UInt64)
    IntegerOverflow(String)
    Unsupported(String)
    } derive(Eq,
    Debug
    )

    Errors raised by byte-level and SQLite format parsers.

    ParseError::message

    fn ParseError::message(self : ParseError) -> String

    BinaryReader

    pub(all) struct BinaryReader {
    data : Bytes
    start : Int
    limit : Int
    position : Int
    context : String
    }

    A bounded cursor over immutable bytes.

    Every read checks the active range before indexing the input. A reader can be forked into a smaller range, which lets page and cell parsers enforce their own boundaries even when the underlying database buffer is larger.

    BinaryReader::absolute_position

    fn BinaryReader::absolute_position(self : BinaryReader) -> Int

    BinaryReader::fork

    fn BinaryReader::fork(self : BinaryReader, count : Int, context : String) -> BinaryReader raise ParseError

    BinaryReader::is_empty

    fn BinaryReader::is_empty(self : BinaryReader) -> Bool

    BinaryReader::length

    fn BinaryReader::length(self : BinaryReader) -> Int

    BinaryReader::named

    fn BinaryReader::named(data : Bytes, context : String) -> BinaryReader

    BinaryReader::new

    fn BinaryReader::new(data : Bytes) -> BinaryReader

    BinaryReader::peek_u8

    fn BinaryReader::peek_u8(self : BinaryReader) -> Byte raise ParseError

    BinaryReader::peek_varint

    fn BinaryReader::peek_varint(self : BinaryReader) -> Varint raise ParseError

    Decode a varint without changing the reader's position.

    BinaryReader::range

    fn BinaryReader::range(data : Bytes, offset : Int, length : Int, context : String) -> BinaryReader raise ParseError

    BinaryReader::read_ascii

    fn BinaryReader::read_ascii(self : BinaryReader, count : Int) -> String raise ParseError

    BinaryReader::read_bytes

    fn BinaryReader::read_bytes(self : BinaryReader, count : Int) -> Bytes raise ParseError

    BinaryReader::read_f64_be

    fn BinaryReader::read_f64_be(self : BinaryReader) -> Double raise ParseError

    BinaryReader::read_i16_be

    fn BinaryReader::read_i16_be(self : BinaryReader) -> Int raise ParseError

    BinaryReader::read_i24_be

    fn BinaryReader::read_i24_be(self : BinaryReader) -> Int raise ParseError

    BinaryReader::read_i32_be

    fn BinaryReader::read_i32_be(self : BinaryReader) -> Int64 raise ParseError

    BinaryReader::read_i64_be

    fn BinaryReader::read_i64_be(self : BinaryReader) -> Int64 raise ParseError

    BinaryReader::read_i8

    fn BinaryReader::read_i8(self : BinaryReader) -> Int raise ParseError

    BinaryReader::read_int_be

    fn BinaryReader::read_int_be(self : BinaryReader, width : Int) -> Int64 raise ParseError

    Read a two's-complement signed big-endian integer using 1..8 bytes.

    BinaryReader::read_u16_be

    fn BinaryReader::read_u16_be(self : BinaryReader) -> Int raise ParseError

    BinaryReader::read_u24_be

    fn BinaryReader::read_u24_be(self : BinaryReader) -> Int raise ParseError

    BinaryReader::read_u32_be

    fn BinaryReader::read_u32_be(self : BinaryReader) -> UInt64 raise ParseError

    BinaryReader::read_u32_le

    fn BinaryReader::read_u32_le(self : BinaryReader) -> UInt64 raise ParseError

    BinaryReader::read_u64_be

    fn BinaryReader::read_u64_be(self : BinaryReader) -> UInt64 raise ParseError

    BinaryReader::read_u8

    fn BinaryReader::read_u8(self : BinaryReader) -> Byte raise ParseError

    BinaryReader::read_uint_be

    fn BinaryReader::read_uint_be(self : BinaryReader, width : Int) -> UInt64 raise ParseError

    Read an unsigned big-endian integer using exactly width bytes.

    BinaryReader::read_varint

    fn BinaryReader::read_varint(self : BinaryReader) -> Varint raise ParseError

    Decode SQLite's one-to-nine-byte unsigned varint representation.

    BinaryReader::relative_position

    fn BinaryReader::relative_position(self : BinaryReader) -> Int

    BinaryReader::remaining

    fn BinaryReader::remaining(self : BinaryReader) -> Int

    BinaryReader::seek_absolute

    fn BinaryReader::seek_absolute(self : BinaryReader, offset : Int) -> Unit raise ParseError

    BinaryReader::seek_relative

    fn BinaryReader::seek_relative(self : BinaryReader, offset : Int) -> Unit raise ParseError

    BinaryReader::skip

    fn BinaryReader::skip(self : BinaryReader, count : Int) -> Unit raise ParseError

    BtreeCell

    pub(all) struct BtreeCell {
    page_number : UInt64
    index : Int
    offset : Int
    page_type : PageType
    left_child_page : UInt64?
    rowid : Int64?
    payload_size : Int
    local_payload : Bytes
    overflow_page : UInt64?
    encoded_size : Int
    } derive(Eq,
    Debug
    )

    A decoded cell from one of SQLite's four B-tree page types.

    BtreeCell::has_overflow

    fn BtreeCell::has_overflow(self : BtreeCell) -> Bool

    BtreeCell::local_payload_size

    fn BtreeCell::local_payload_size(self : BtreeCell) -> Int

    BtreePageHeader

    pub(all) struct BtreePageHeader {
    page_number : UInt64
    page_offset : Int
    header_offset : Int
    page_type : PageType
    first_freeblock : Int
    cell_count : Int
    cell_content_area : Int
    fragmented_free_bytes : Int
    right_most_pointer : UInt64?
    cell_pointers : Array[Int]
    } derive(Eq,
    Debug
    )

    Parsed common header of a B-tree page.

    BtreePageHeader::cell_content_start

    fn BtreePageHeader::cell_content_start(self : BtreePageHeader) -> Int

    BtreePageHeader::header_size

    fn BtreePageHeader::header_size(self : BtreePageHeader) -> Int

    BtreePageHeader::pointer_array_end

    fn BtreePageHeader::pointer_array_end(self : BtreePageHeader) -> Int

    BtreePageHeader::pointer_array_start

    fn BtreePageHeader::pointer_array_start(self : BtreePageHeader) -> Int

    BtreePageHeader::unallocated_bytes

    fn BtreePageHeader::unallocated_bytes(self : BtreePageHeader) -> Int

    BtreeStatistics

    pub(all) struct BtreeStatistics {
    root_page : UInt64
    total_pages : Int
    interior_pages : Int
    leaf_pages : Int
    table_pages : Int
    index_pages : Int
    total_cells : Int
    maximum_depth : Int
    maximum_children : Int
    } derive(Eq,
    Debug
    )

    Aggregate shape of one traversed SQLite B-tree.

    BtreeStatistics::average_cells_per_page

    fn BtreeStatistics::average_cells_per_page(self : BtreeStatistics) -> Double

    BtreeStatistics::is_single_page

    fn BtreeStatistics::is_single_page(self : BtreeStatistics) -> Bool

    BtreeTraversal

    pub(all) struct BtreeTraversal {
    root_page : UInt64
    visits : Array[BtreeVisit]
    diagnostics : Array[Diagnostic]
    } derive(Eq,
    Debug
    )

    BtreeVisit

    pub(all) struct BtreeVisit {
    page_number : UInt64
    depth : Int
    page_type : PageType
    cell_count : Int
    child_pages : Array[UInt64]
    } derive(Eq,
    Debug
    )

    ChangedRange

    pub(all) struct ChangedRange {
    offset : Int
    length : Int
    } derive(Eq,
    Debug
    )

    One contiguous byte range changed by a WAL frame.

    DatabaseHeader

    pub(all) struct DatabaseHeader {
    page_size : Int
    write_version : Int
    read_version : Int
    reserved_bytes : Int
    max_embedded_payload_fraction : Int
    min_embedded_payload_fraction : Int
    leaf_payload_fraction : Int
    file_change_counter : UInt64
    database_size_pages : UInt64
    first_freelist_trunk_page : UInt64
    total_freelist_pages : UInt64
    schema_cookie : UInt64
    schema_format : UInt64
    default_page_cache_size : Int64
    largest_root_btree_page : UInt64
    text_encoding : TextEncoding
    user_version : UInt64
    incremental_vacuum : UInt64
    application_id : UInt64
    version_valid_for : UInt64
    sqlite_version_number : UInt64
    } derive(Eq,
    Debug
    )

    Parsed representation of SQLite's 100-byte database header.

    DatabaseHeader::effective_database_pages

    fn DatabaseHeader::effective_database_pages(self : DatabaseHeader, file_length : Int) -> UInt64

    DatabaseHeader::is_wal_mode

    fn DatabaseHeader::is_wal_mode(self : DatabaseHeader) -> Bool

    DatabaseHeader::usable_page_size

    fn DatabaseHeader::usable_page_size(self : DatabaseHeader) -> Int

    DatabaseImage

    pub(all) struct DatabaseImage {
    data : Bytes
    header : DatabaseHeader
    page_count : UInt64
    }

    Immutable database image backed by the caller-provided bytes.

    DatabaseImage::file_length

    fn DatabaseImage::file_length(self : DatabaseImage) -> Int

    DatabaseImage::open

    fn DatabaseImage::open(data : Bytes) -> DatabaseImage raise ParseError

    DatabaseImage::page_bytes

    fn DatabaseImage::page_bytes(self : DatabaseImage, page_number : UInt64) -> Bytes raise ParseError

    DatabaseImage::page_offset

    fn DatabaseImage::page_offset(self : DatabaseImage, page_number : UInt64) -> Int raise ParseError

    DatabaseImage::page_reader

    fn DatabaseImage::page_reader(self : DatabaseImage, page_number : UInt64, context : String) -> BinaryReader raise ParseError

    DatabaseImage::validate_page_number

    fn DatabaseImage::validate_page_number(self : DatabaseImage, page_number : UInt64) -> Unit raise ParseError

    DatabaseInspection

    pub(all) struct DatabaseInspection {
    header : DatabaseHeader
    physical_page_count : UInt64
    file_length : Int
    page_one : BtreePageHeader
    page_one_layout : PageLayout
    schema_tree : BtreeTraversal
    freelist : FreelistReport
    diagnostics : Array[Diagnostic]
    }

    High-level database facts used by the CLI's text and JSON renderers.

    Diagnostic

    pub(all) struct Diagnostic {
    severity : Severity
    code : String
    message : String
    offset : Int?
    page_number : UInt64?
    } derive(Eq,
    Debug
    )

    A non-fatal parser or validation observation.

    Diagnostic::error

    fn Diagnostic::error(code : String, message : String, offset? : Int, page_number? : UInt64) -> Diagnostic

    Diagnostic::info

    fn Diagnostic::info(code : String, message : String, offset? : Int, page_number? : UInt64) -> Diagnostic

    Diagnostic::warning

    fn Diagnostic::warning(code : String, message : String, offset? : Int, page_number? : UInt64) -> Diagnostic

    Freeblock

    pub(all) struct Freeblock {
    offset : Int
    next : Int
    size : Int
    } derive(Eq,
    Debug
    )

    FreelistReport

    pub(all) struct FreelistReport {
    trunks : Array[FreelistTrunk]
    trunk_pages : Array[UInt64]
    leaf_pages : Array[UInt64]
    diagnostics : Array[Diagnostic]
    declared_page_count : UInt64
    } derive(
    Debug
    )

    A complete walk of the freelist rooted in the database header.

    FreelistReport::observed_page_count

    fn FreelistReport::observed_page_count(self : FreelistReport) -> Int

    FreelistTrunk

    pub(all) struct FreelistTrunk {
    page_number : UInt64
    next_trunk_page : UInt64
    leaf_count : Int
    leaf_pages : Array[UInt64]
    } derive(Eq,
    Debug
    )

    One SQLite freelist trunk page and the leaf page numbers stored on it.

    IntegrityReport

    pub(all) struct IntegrityReport {
    diagnostics : Array[Diagnostic]
    database_opened : Bool
    pages_examined : Int
    btree_pages : Int
    btree_cells : Int
    records_decoded : Int
    overflow_pages : Int
    freelist_pages : Int
    wal_frames : Int
    }

    Aggregate outcome of PageLens's structural consistency pass.

    IntegrityReport::count

    fn IntegrityReport::count(self : IntegrityReport, severity : Severity) -> Int

    IntegrityReport::error_count

    fn IntegrityReport::error_count(self : IntegrityReport) -> Int

    IntegrityReport::info_count

    fn IntegrityReport::info_count(self : IntegrityReport) -> Int

    IntegrityReport::is_ok

    fn IntegrityReport::is_ok(self : IntegrityReport) -> Bool

    IntegrityReport::warning_count

    fn IntegrityReport::warning_count(self : IntegrityReport) -> Int

    OverflowChain

    pub(all) struct OverflowChain {
    first_page : UInt64
    pages : Array[UInt64]
    payload : Bytes
    diagnostics : Array[Diagnostic]
    } derive(Eq,
    Debug
    )

    PageDifference

    pub(all) struct PageDifference {
    page_number : UInt64
    frame_index : Int
    changed_bytes : Int
    first_changed_offset : Int?
    last_changed_offset : Int?
    ranges : Array[ChangedRange]
    } derive(Eq,
    Debug
    )

    PageLayout

    pub(all) struct PageLayout {
    page_number : UInt64
    header_bytes : Int
    pointer_array_bytes : Int
    unallocated_bytes : Int
    cell_content_bytes : Int
    freeblock_bytes : Int
    fragmented_free_bytes : Int
    usable_bytes : Int
    freeblocks : Array[Freeblock]
    } derive(Eq,
    Debug
    )

    PageLayout::total_free_bytes

    fn PageLayout::total_free_bytes(self : PageLayout) -> Int

    PageType

    pub(all) enum PageType {
    IndexInterior
    TableInterior
    IndexLeaf
    TableLeaf
    } derive(Compare, Eq,
    Debug
    )

    The four B-tree page types defined by the SQLite file format.

    PageType::flag

    fn PageType::flag(self : PageType) -> Int

    PageType::from_flag

    fn PageType::from_flag(flag : Int, offset : Int) -> PageType raise ParseError

    PageType::header_size

    fn PageType::header_size(self : PageType) -> Int

    PageType::is_interior

    fn PageType::is_interior(self : PageType) -> Bool

    PageType::is_table

    fn PageType::is_table(self : PageType) -> Bool

    PageType::label

    fn PageType::label(self : PageType) -> String

    RecordColumn

    pub(all) struct RecordColumn {
    index : Int
    serial_type : UInt64
    body_offset : Int
    byte_length : Int
    value : RecordValue
    } derive(Eq,
    Debug
    )

    RecordValue

    pub(all) enum RecordValue {
    Null
    Integer(Int64)
    Real(Double)
    Text(String)
    Blob(Bytes)
    } derive(Eq,
    Debug
    )

    One decoded value in a SQLite record body.

    RecordValue::display

    fn RecordValue::display(self : RecordValue) -> String

    RecordValue::kind

    fn RecordValue::kind(self : RecordValue) -> String

    Severity

    pub(all) enum Severity {
    Info
    Warning
    Error
    } derive(Compare, Eq,
    Debug
    )

    Stable severity levels used by validation and consistency reports.

    Severity::label

    fn Severity::label(self : Severity) -> String

    SnapshotPage

    pub(all) struct SnapshotPage {
    page_number : UInt64
    source : SnapshotPageSource
    bytes : Bytes
    } derive(Eq,
    Debug
    )

    SnapshotPageSource

    pub(all) enum SnapshotPageSource {
    DatabaseFile
    WalFrame(Int)
    } derive(Eq,
    Debug
    )

    SnapshotStatistics

    pub(all) struct SnapshotStatistics {
    commit_frame : Int
    logical_page_count : UInt64
    changed_pages : Int
    changed_bytes : Int
    changed_ranges : Int
    pages_added_by_wal : Int
    largest_page_change : Int
    } derive(Eq,
    Debug
    )

    SnapshotStatistics::average_changed_bytes_per_page

    fn SnapshotStatistics::average_changed_bytes_per_page(self : SnapshotStatistics) -> Double

    SnapshotStatistics::is_unchanged

    fn SnapshotStatistics::is_unchanged(self : SnapshotStatistics) -> Bool

    SnapshotView

    pub(all) struct SnapshotView {
    database : DatabaseImage
    wal : WalFile
    max_frame : Int
    logical_page_count : UInt64
    }

    An immutable database view at one committed WAL boundary.

    SnapshotView::at_commit

    fn SnapshotView::at_commit(database : DatabaseImage, wal : WalFile, frame_index : Int) -> SnapshotView raise ParseError

    SnapshotView::changed_pages

    fn SnapshotView::changed_pages(self : SnapshotView) -> Array[UInt64]

    SnapshotView::difference_for_page

    fn SnapshotView::difference_for_page(self : SnapshotView, page_number : UInt64) -> PageDifference? raise ParseError

    SnapshotView::differences

    fn SnapshotView::differences(self : SnapshotView) -> Array[PageDifference] raise ParseError

    SnapshotView::page_size

    fn SnapshotView::page_size(self : SnapshotView) -> Int

    SnapshotView::read_page

    fn SnapshotView::read_page(self : SnapshotView, page_number : UInt64) -> SnapshotPage raise ParseError

    SnapshotView::uses_wal

    fn SnapshotView::uses_wal(self : SnapshotView) -> Bool

    SqliteRecord

    pub(all) struct SqliteRecord {
    header_size : Int
    body_offset : Int
    columns : Array[RecordColumn]
    trailing_bytes : Int
    } derive(Eq,
    Debug
    )

    SqliteRecord::column_count

    fn SqliteRecord::column_count(self : SqliteRecord) -> Int

    SqliteRecord::value

    fn SqliteRecord::value(self : SqliteRecord, index : Int) -> RecordValue?

    TextEncoding

    pub(all) enum TextEncoding {
    Utf8
    Utf16Le
    Utf16Be
    Unspecified
    } derive(Eq,
    Debug
    )

    Text encodings allowed by the SQLite database header.

    TextEncoding::from_header

    fn TextEncoding::from_header(value : UInt64) -> TextEncoding raise ParseError

    TextEncoding::label

    fn TextEncoding::label(self : TextEncoding) -> String

    Varint

    pub(all) struct Varint {
    value : UInt64
    length : Int
    } derive(Eq,
    Debug
    )

    Result of decoding one SQLite variable-length integer.

    WalChecksum

    pub(all) struct WalChecksum {
    first : UInt64
    second : UInt64
    } derive(Eq,
    Debug
    )

    WalChecksumOrder

    pub(all) enum WalChecksumOrder {
    BigEndian
    LittleEndian
    } derive(Eq,
    Debug
    )

    Magic 0x377f0683 checksums words as big-endian; 0x377f0682 uses little-endian words. All structural fields remain big-endian.

    WalFile

    pub(all) struct WalFile {
    header : WalHeader
    frames : Array[WalFrame]
    transactions : Array[WalTransaction]
    diagnostics : Array[Diagnostic]
    trailing_bytes : Int
    last_commit_frame : Int?
    } derive(
    Debug
    )

    WalFile::committed_transaction_count

    fn WalFile::committed_transaction_count(self : WalFile) -> Int

    WalFile::latest_frame_for_page

    fn WalFile::latest_frame_for_page(self : WalFile, page_number : UInt64, max_frame? : Int) -> WalFrame?

    Return the newest valid occurrence of a page not newer than max_frame. Frame indexes are one-based, matching the CLI and SQLite documentation.

    WalFile::page_histories

    fn WalFile::page_histories(self : WalFile) -> Array[WalPageHistory]

    WalFile::uncommitted_frame_count

    fn WalFile::uncommitted_frame_count(self : WalFile) -> Int

    WalFile::valid_frame_count

    fn WalFile::valid_frame_count(self : WalFile) -> Int

    WalFrame

    pub(all) struct WalFrame {
    index : Int
    offset : Int
    page_number : UInt64
    database_size_after_commit : UInt64
    salt_first : UInt64
    salt_second : UInt64
    checksum : WalChecksum
    computed_checksum : WalChecksum
    page_data : Bytes
    salt_valid : Bool
    checksum_valid : Bool
    } derive(Eq,
    Debug
    )

    WalFrame::is_commit

    fn WalFrame::is_commit(self : WalFrame) -> Bool

    WalFrame::is_valid

    fn WalFrame::is_valid(self : WalFrame) -> Bool

    WalHeader

    pub(all) struct WalHeader {
    magic : UInt64
    format_version : UInt64
    page_size : Int
    checkpoint_sequence : UInt64
    salt_first : UInt64
    salt_second : UInt64
    checksum : WalChecksum
    computed_checksum : WalChecksum
    checksum_order : WalChecksumOrder
    checksum_valid : Bool
    } derive(Eq,
    Debug
    )

    WalPageHistory

    pub(all) struct WalPageHistory {
    page_number : UInt64
    frame_indexes : Array[Int]
    valid_frame_indexes : Array[Int]
    committed_frame : Int?
    uncommitted_frame_indexes : Array[Int]
    } derive(Eq,
    Debug
    )

    Every occurrence of one database page in a WAL, including frames that do not become visible in the newest committed snapshot.

    WalPageHistory::has_uncommitted_change

    fn WalPageHistory::has_uncommitted_change(self : WalPageHistory) -> Bool

    WalPageHistory::latest_valid_frame

    fn WalPageHistory::latest_valid_frame(self : WalPageHistory) -> Int?

    WalPageHistory::occurrence_count

    fn WalPageHistory::occurrence_count(self : WalPageHistory) -> Int

    WalPageHistory::valid_occurrence_count

    fn WalPageHistory::valid_occurrence_count(self : WalPageHistory) -> Int

    WalTransaction

    pub(all) struct WalTransaction {
    ordinal : Int
    first_frame : Int
    last_frame : Int
    frame_count : Int
    committed : Bool
    database_size_after_commit : UInt64?
    } derive(Eq,
    Debug
    )

    analyze_freelist

    fn analyze_freelist(database : DatabaseImage) -> FreelistReport

    Walk every trunk and validate page references, loops, duplicates and the freelist count declared by the 100-byte database header.

    analyze_page_layout

    fn analyze_page_layout(database : DatabaseImage, header : BtreePageHeader) -> PageLayout raise ParseError

    fn banner() -> String

    Return the project banner without performing file I/O.

    bytes_equal

    fn bytes_equal(left : Bytes, right : Bytes) -> Bool

    bytes_hex

    fn bytes_hex(data : Bytes) -> String

    check_database

    fn check_database(data : Bytes, wal_data? : Bytes) -> IntegrityReport

    Run a read-only consistency pass. Parsing failures become ERROR diagnostics instead of escaping, which makes this function suitable for damaged files.

    description

    let description : String

    Short description used by the CLI and package documentation.

    inspect_database

    fn inspect_database(data : Bytes) -> DatabaseInspection raise ParseError

    join_payload

    fn join_payload(local_bytes : Bytes, overflow : Bytes) -> Bytes

    local_payload_size

    fn local_payload_size(page_type : PageType, payload_size : Int, usable_size : Int) -> Int raise ParseError

    Compute the local payload length using SQLite's spill formula.

    materialize_cell_payload

    fn materialize_cell_payload(database : DatabaseImage, cell : BtreeCell) -> Bytes raise ParseError

    open_snapshot

    fn open_snapshot(database : DatabaseImage, wal : WalFile) -> SnapshotView raise ParseError

    Construct the newest fully committed view. Invalid and uncommitted WAL frames never influence the resulting snapshot.

    parse_btree_cell

    fn parse_btree_cell(database : DatabaseImage, header : BtreePageHeader, index : Int) -> BtreeCell raise ParseError

    parse_btree_page_cells

    fn parse_btree_page_cells(database : DatabaseImage, header : BtreePageHeader) -> Array[BtreeCell] raise ParseError

    parse_btree_page_header

    fn parse_btree_page_header(database : DatabaseImage, page_number : UInt64) -> BtreePageHeader raise ParseError

    parse_cell_record

    fn parse_cell_record(database : DatabaseImage, cell : BtreeCell) -> SqliteRecord raise ParseError

    parse_database_header

    fn parse_database_header(data : Bytes) -> DatabaseHeader raise ParseError

    Parse and strictly validate the SQLite database header.

    parse_freeblocks

    fn parse_freeblocks(database : DatabaseImage, header : BtreePageHeader) -> Array[Freeblock] raise ParseError

    parse_freelist_trunk

    fn parse_freelist_trunk(database : DatabaseImage, page_number : UInt64) -> FreelistTrunk raise ParseError

    Decode a single freelist trunk. Leaf pages are references only: their contents are intentionally not read because SQLite assigns them no format.

    parse_record

    fn parse_record(payload : Bytes, encoding : TextEncoding) -> SqliteRecord raise ParseError

    Parse a complete SQLite record payload.

    parse_wal

    fn parse_wal(data : Bytes) -> WalFile raise ParseError

    Parse a complete WAL, retaining invalid frames and attaching diagnostics so an analyst can distinguish structural damage from uncommitted tail data.

    parse_wal_header

    fn parse_wal_header(data : Bytes) -> WalHeader raise ParseError

    read_overflow_chain

    fn read_overflow_chain(database : DatabaseImage, first_page : UInt64, payload_bytes : Int) -> OverflowChain raise ParseError

    Follow an overflow chain and return exactly payload_bytes bytes.

    render_database_json

    fn render_database_json(inspection : DatabaseInspection) -> String

    render_database_text

    fn render_database_text(inspection : DatabaseInspection) -> String

    render_integrity_json

    fn render_integrity_json(report : IntegrityReport) -> String

    render_integrity_text

    fn render_integrity_text(report : IntegrityReport) -> String

    render_snapshot_json

    fn render_snapshot_json(snapshot : SnapshotView) -> String raise ParseError

    render_snapshot_text

    fn render_snapshot_text(snapshot : SnapshotView) -> String raise ParseError

    render_wal_json

    fn render_wal_json(wal : WalFile) -> String

    render_wal_text

    fn render_wal_text(wal : WalFile) -> String

    serial_type_length

    fn serial_type_length(serial_type : UInt64) -> Int raise ParseError

    Return the number of body bytes represented by a serial type.

    summarize_btree

    fn summarize_btree(traversal : BtreeTraversal) -> BtreeStatistics

    summarize_snapshot

    fn summarize_snapshot(snapshot : SnapshotView) -> SnapshotStatistics raise ParseError

    traverse_btree

    fn traverse_btree(database : DatabaseImage, root_page : UInt64, max_depth? : Int) -> BtreeTraversal raise ParseError

    validate_database_header

    fn validate_database_header(header : DatabaseHeader, file_length : Int) -> Array[Diagnostic]

    Return non-fatal relationships that cannot be decided from one field alone.

    validate_page_layout

    fn validate_page_layout(database : DatabaseImage, header : BtreePageHeader) -> Array[Diagnostic]

    Validate page-local layout facts without parsing cell payloads.

    validate_record

    fn validate_record(record : SqliteRecord) -> Array[Diagnostic]

    version

    let version : String

    Semantic version of the PageLens library.

    wal_checksum

    fn wal_checksum(bytes : Bytes, order : WalChecksumOrder, initial_first? : UInt64, initial_second? : UInt64) -> WalChecksum raise ParseError

    Apply SQLite's rolling two-word WAL checksum. Initial values allow frame checksums to continue the state established by the header and prior frames.