packed

package
v0.2.1-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package packed ships a folder of embedded text compressed, and unpacks it on the first read.

A folder handed to go:embed lands in the binary verbatim, and prose is the most compressible thing codeaf ships: the v3 chat manual alone is a megabyte of Markdown that is a megabyte of binary. A folder handed to Pack lands as one gzip stream, about a third of that, and the text a caller reads back is identical byte for byte. The raw folder stays in the repository as the source of truth; the archive beside it is generated from the folder by go:generate, regenerated by `make build`, and asserted against it by Verify in the test beside every packed corpus. Nothing is hand-edited.

THE WHOLE FOLDER UNPACKS AT ONCE, ON THE FIRST READ, AND NEVER AGAIN. One stream over every file compresses far better than one stream per file — the pages of a corpus are written in one vocabulary, and gzip's window can only trade on that when they are adjacent — and these corpora are read whole anyway: a manual is indexed entire, a roster is parsed entire. Declaring a folder reads nothing, so a run that never asks it a question never pays for it; `codeaf --version` decompresses none of this.

A Folder is deliberately not an io/fs.FS. An archive has no directories, and a type that half-answers fs.WalkDir is worse than one that never claimed to walk. A caller asks for a name, for a pattern, or for the whole list.

The archive is a gzip stream of entries, each one

uvarint(len(name)) name uvarint(len(data)) data

in Folder.Names order, which is sorted. Pack writes it and Folder reads it; it is not a format anything else is entitled to produce.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pack

func Pack(root string) ([]byte, error)

Pack walks a folder and returns the archive New reads. Entry names keep the folder's own base name in front — Pack("chat") names "chat/keys.md" — so the packed names are the names go:embed gave.

It skips what go:embed skips: a name beginning with "." or "_", and anything that is not a regular file. The result is a pure function of the folder's bytes — sorted names, fixed level, no timestamps — so regenerating an unchanged folder rewrites an identical archive and leaves the tree clean. That is what lets `make build` regenerate unconditionally instead of trusting a freshness check.

func Unpacks

func Unpacks() int64

Unpacks is how many packed folders this process has decompressed since it started, across every corpus in the binary.

IT EXISTS SO THAT "THE LAUNCH READS NONE OF THIS" CAN BE A TEST. The package doc above states that law in prose — declaring a folder reads nothing, and `codeaf --version` decompresses none of it — and prose is what a change quietly breaks: one manual lookup moved onto the launch path costs a megabyte of gunzip before the first frame, and nothing would say so. A caller takes the reading either side of the construction it is holding to the law and asserts the difference is zero; counting rather than timing is what makes that assertion the same assertion on every machine.

func Verify

func Verify(archive []byte, root string) error

Verify reports whether an archive still holds exactly what a folder holds, name for name and byte for byte. It is what the test beside each packed corpus asserts, so a page edited without regenerating fails the build rather than shipping yesterday's text.

Types

type Folder

type Folder struct {
	// contains filtered or unexported fields
}

Folder is one packed folder, still compressed until something reads it.

func New

func New(archive []byte) *Folder

New names an archive. Nothing is decompressed here, so a package-level folder costs a pointer at startup and nothing else.

func (*Folder) Glob

func (f *Folder) Glob(pattern string) ([]string, error)

Glob returns the packed names matching pattern, in Folder.Names order. The syntax and the ErrBadPattern are io/fs.Glob's, because that is what the callers of a folder were written against.

func (*Folder) Names

func (f *Folder) Names() []string

Names lists every packed file, sorted, which is the order the folder was walked in.

func (*Folder) ReadFile

func (f *Folder) ReadFile(name string) ([]byte, error)

ReadFile returns one file's bytes. The name is the one the file had under go:embed — "chat/keys.md", not "keys.md" — so no caller's paths move when a folder becomes packed. The returned slice belongs to the caller.

Directories

Path Synopsis
cmd
pack command
Command pack writes the archive a packed corpus ships as.
Command pack writes the archive a packed corpus ships as.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL