Documentation
¶
Overview ¶
Package exact is the normalized-exact index: analyzed key -> entry ordinals.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder accumulates postings in a plain map; Finish compacts.
func NewBuilder ¶
func NewBuilder() *Builder
func (*Builder) Add ¶
Add indexes one entry's analyzed keys under its ordinal.
Contract: Add is called at most once per ordinal, with strictly ascending ordinals across calls. That makes duplicate detection allocation-free: a key already holds this entry iff its postings tail equals ord.
func (*Builder) Finish ¶
Finish compacts the builder map into the packed representation and freezes it; the Builder must not be used afterwards. A key held by more than maxRun entries is a data bug, not a programmer error: Finish returns a *KeyOverflowError for it (never a panic — this runs on untrusted list data inside a daemon).
type Index ¶
type Index struct {
// contains filtered or unexported fields
}
Index maps analyzed keys to the ordinals of entries holding them.
Memory layout (built by Finish, immutable after): every key's postings are one contiguous run inside the shared postings slice, and the map value is a packed (offset, length) locator. Compared with the naive map[string][]uint32 this drops the per-key slice header and per-key backing allocation — dominant costs when almost every key has exactly one ordinal. Key bytes likewise share one contiguous arena instead of one heap allocation each.
SAFETY INVARIANT (the package's one use of unsafe): the map's keys are unsafe.String views into arena. The arena is populated exactly once — written inside Finish, or handed to Restore whose caller relinquishes it — before any view escapes, and is never mutated afterwards. That makes the views immutable, satisfying Go's string contract.
func Restore ¶
Restore rebuilds an Index from its serialized sections (see kurn/engine/artifact): arena holds every key's bytes back to back, keyLens and runLens give each key's byte length and postings-run length in the same order, and postings holds the runs concatenated in that order. Restore takes ownership of arena and postings — the caller must never mutate them afterwards (the Index's map keys are views into arena; see the SAFETY INVARIANT on Index).
Validation is structural: section lengths must agree exactly, every key and run must be non-empty, runs must fit the packed encoding, and keys must be distinct. Ordinal VALUES are not range-checked here — NumOrds reports the maximum seen, and the caller validates it against its entry count (a corrupt-but-well-formed payload can still return wrong ordinals, matching the ngram artifact's checksum-less corruption stance).
func (*Index) Lookup ¶
Lookup returns the ordinals of every entry holding the analyzed query as a key (ascending), nil on miss. The returned slice is shared with the index: writing to its elements would silently corrupt the index for every concurrent reader. Appending to it is safe — the full-cap subslice forces append to reallocate rather than clobber the next key's run. Scoring is the caller's business — an exact hit has no per-hit score of its own.
func (*Index) NumOrds ¶
NumOrds returns max ordinal + 1 (0 when empty) — the minimum entry count an ordinal-aligned entries slice must have for every Lookup result to be a valid index into it. Same semantics as ngram.Index.NumOrds.
func (*Index) SortedKeys ¶
SortedKeys returns every analyzed key in sorted order. The strings are views into the index's arena (valid as long as the index is reachable); used to serialize the index deterministically.
type KeyOverflowError ¶
type KeyOverflowError struct {
Key string // the analyzed key
Count int // number of entries holding it
Cap int // the encoding cap (maxRun)
}
KeyOverflowError reports a single analyzed key held by more than maxRun entries: the 20-bit run-length field cannot represent it. This is a data bug (an analyzer collapsing every key to one value, or a genuinely pathological list), surfaced as a typed error so a hostile or broken input is REJECTED — never a panic mid-build, which would poison journals and block daemon startup (see engine store journal replay).
func (*KeyOverflowError) Error ¶
func (e *KeyOverflowError) Error() string