synology_apm_repo.sdk.format.chunkmap module

ChunkMapRecord — the 20-byte record describing one segment of a file’s content within a composition record (FORMAT-SPEC.md: ChunkMapRecord).

This is the core of the entire read path: every byte of every restorable unit is reached by walking an array of these. Decode precisely — traps #4/#5/#7 all live in the ambiguity between the two record kinds this module resolves once, here.

class synology_apm_repo.sdk.format.chunkmap.ChunkMapKind(value)

Bases: Enum

Type (FORMAT-SPEC.md: ChunkMapRecord). Values match the on-disk encoding exactly — do not renumber.

MAPPING = 0
ZERO = 1
class synology_apm_repo.sdk.format.chunkmap.ChunkMapEntry(kind, file_offset, is_inherit, addr, map_num, repeat)

Bases: object

One decoded ChunkMapRecord.

map_num’s meaning depends on kind: for ChunkMapKind.MAPPING it is the address template length in chunks (the template repeats 1 + repeat times); for ChunkMapKind.ZERO it is the literal chunk count covered (repeat is always 0 and meaningless there) — both are decoded from the identical byte offset [16,20), just split differently, which is exactly why a single field name is used for both rather than inventing a separate zero_num.

kind: ChunkMapKind
file_offset: int

fileChunkIdx << 12 — the byte offset within the described file where this record’s coverage begins. Recorded as ChunkMapRecord in FORMAT-SPEC.md.

is_inherit: bool

The INHERIT bit — purely descriptive (“this data was carried over unchanged from a reference composition”). See FORMAT-SPEC.md’s hole-zero-inherit note. The read path never branches on it — every record, inherited or not, is self-sufficient to read.

addr: ChunkAddress | None

The chunk’s base address in Pool. None for ChunkMapKind.ZERO.

map_num: int
repeat: int
property length: int

Byte length this record covers, starting at file_offset.

property end_offset: int
synology_apm_repo.sdk.format.chunkmap.parse_chunk_map_record(data)

Decode one 20-byte ChunkMapRecord from the start of data (data may be longer; only the first 20 bytes are consulted).

A Mapping record’s embedded ChunkAddress is not itself range-checked here — an out-of-range field either surfaces naturally downstream (IndexError/NotFoundError) or is the job of units/verify_reachable.py’s dedicated, verify-only checks; skipping it here matters at scale, since this runs once per real chunk in an export.

Raises:
synology_apm_repo.sdk.format.chunkmap.iter_chunk_map_page(page_bytes, count)

Lazily decode count consecutive ChunkMapRecords starting at the front of page_bytes — the batch form of parse_chunk_map_record a page-at-a-time cache’s caller uses instead of re-deriving the same slice arithmetic itself.