Documentation
¶
Overview ¶
Package transform — range 0.2.5.* (ADR 0014 core/data/transform block), and the stdlib schemes' 0.3.26.* (ADR 0014 service/data/transform block, declared here since ADR 0160).
Package transform — declares the sentinels returned by the Compressor facade, and the three the stdlib schemes in internal/service/data/transform wrap a compress/* failure in (ADR 0160: every code is declared in the core, at the service's path). Each var's name equals its errs.Define Reason in SCREAMING_SNAKE form. CodeUnknownCompressor is also surfaced via panic at boot on a duplicate registration (see registry.go), not only as an *Error sentinel.
Package transform — holds the process-wide Compressor registry. Service-level scheme packages register themselves via package-level var initialisers when imported (no init()), mirroring core/data/codec and core/crypto.
Package transform declares the byte-transform port of the SDK: the Compressor contract and the typed Algorithm string under which a compressor registers. It is the fifth core sibling beside codec, writer, crypto, and logger (ADR 0014 D1) and mirrors codec exactly — the registry resolves an Algorithm to a Compressor the way codec resolves a Format to a Codec.
No algorithm bodies and no vendor types live here; concrete compressors live under internal/service/data/transform/ (stdlib gzip/flate/zlib today) and self-register via a package-level var initialiser when imported — no init().
Index ¶
Constants ¶
const CodeCompressedFrameInvalid errs.Code = 0x00_02_05_04 // 0.2.5.4
CodeCompressedFrameInvalid identifies a malformed compressed frame OR a tripped decompression-bomb guard (max output size / max expansion ratio). It is owned by the pkg/v1/data/codec frame layer (a later commit); declared here so the 0.2.5.* block is allocated in one place per ADR 0014.
const CodeCompressionFailed errs.Code = 0x00_02_05_02 // 0.2.5.2
CodeCompressionFailed identifies a Compress call whose underlying compressor returned an error — typically a writer fault while flushing the stream.
const CodeDecompressedTooLarge errs.Code = 0x00_02_05_06 // 0.2.5.6
CodeDecompressedTooLarge identifies a stream whose plaintext exceeded the ceiling the CALLER supplied to BoundedDecompressor.DecompressBounded. It is distinct from the scheme sentinels (GZIP_FAILED and friends) on purpose: a corrupt body and a body that is merely too big are different facts, and a caller that imposed the ceiling is the only one able to say which of the two its own limit produced. Collapsing them would force that caller to report a malformed stream for one whose only established fault is its size.
const CodeDecompressionFailed errs.Code = 0x00_02_05_03 // 0.2.5.3
CodeDecompressionFailed identifies a Decompress call whose underlying decompressor returned an error — malformed input or a truncated stream.
const CodeDuplicateRegistration errs.Code = 0x00_02_05_05 // 0.2.5.5
CodeDuplicateRegistration identifies a boot-time collision on the Compressor registry: a nil scheme, or a distinct scheme claiming an already-registered Algorithm. It is surfaced via panic at boot (see registry.go). Its reason is DUPLICATE_REGISTRATION so the bracket header "[<code> <REASON>]" stays a valid (code,reason) pairing per ADR 0005 §Semantics — mirroring the codec registry's CodeDuplicateRegistration (0.2.2.1).
const CodeFlateFailed errs.Code = 0x00_03_1A_02 // 0.3.26.2
CodeFlateFailed identifies a failure inside compress/flate during either a Compress (writer) or Decompress (reader) operation.
const CodeGzipFailed errs.Code = 0x00_03_1A_01 // 0.3.26.1
CodeGzipFailed identifies a failure inside compress/gzip during either a Compress (writer) or Decompress (reader) operation; the wrap trail and the COMPRESSION_FAILED / DECOMPRESSION_FAILED sentinels distinguish the direction.
const CodeUnknownCompressor errs.Code = 0x00_02_05_01 // 0.2.5.1
CodeUnknownCompressor identifies a Lookup/Decompress call naming an Algorithm that no imported package has registered. It is also surfaced via panic at boot on a duplicate registration (see registry.go), not only as a sentinel.
const CodeZlibFailed errs.Code = 0x00_03_1A_03 // 0.3.26.3
CodeZlibFailed identifies a failure inside compress/zlib during either a Compress (writer) or Decompress (reader) operation. It is distinct from CodeFlateFailed because the zlib envelope (RFC 1950) is a distinct wire format from the raw DEFLATE stream (RFC 1951): a stream rejected under one scheme is routinely valid under the other, so the two must be told apart at the code.
Variables ¶
var ( // UnknownCompressor is returned when no Compressor is registered under the // requested Algorithm — typically a missing blank-import of the scheme. UnknownCompressor = errs.Static(CodeUnknownCompressor, "UNKNOWN_COMPRESSOR", "No compressor is registered under that algorithm", "core/data/transform.Lookup: algorithm absent from registry; blank-import the scheme's package to register it", 0, 0) // CompressionFailed wraps a failure from a compressor's underlying writer // (e.g. compress/gzip or compress/flate) while encoding the payload. CompressionFailed = errs.Static(CodeCompressionFailed, "COMPRESSION_FAILED", "Compression failed", "core/data/transform.Compress: the underlying compressor returned an error", 0, 65) // DecompressionFailed wraps a failure from a decompressor's underlying // reader while decoding the payload — malformed or truncated input. DecompressionFailed = errs.Static(CodeDecompressionFailed, "DECOMPRESSION_FAILED", "Decompression failed", "core/data/transform.Decompress: the underlying decompressor returned an error", 0, 65) // CompressedFrameInvalid is returned for a malformed compressed frame or a // tripped decompression-bomb guard. The pkg/v1/data/codec frame layer (a later // commit) is its emitter; defined here so the 0.2.5.* block lands in one place. CompressedFrameInvalid = errs.Static(CodeCompressedFrameInvalid, "COMPRESSED_FRAME_INVALID", "Compressed frame is malformed or exceeds the safety bound", "core/data/transform: compressed-frame header is malformed or the decompression-bomb guard tripped", 0, 65) // DecompressedTooLarge reports that a stream's plaintext exceeded the // ceiling its caller passed to DecompressBounded. It establishes exactly // that and nothing more: more than max plaintext bytes were produced. It // does NOT report a well-formed stream — the decode stops at the ceiling, // so the trailer is never reached and the bytes past it are never read. // Claiming well-formedness here would be claiming the result of work this // error exists to avoid doing. DecompressedTooLarge = errs.Static(CodeDecompressedTooLarge, "DECOMPRESSED_TOO_LARGE", "Decompressed payload exceeds the caller's ceiling", "core/data/transform.DecompressBounded: plaintext exceeded the caller-supplied max", 0, 65) // DuplicateRegistration is the boot-time panic sentinel for the Compressor // registry: a nil scheme or a distinct scheme claiming a taken Algorithm. Its // reason matches the bracket-header word so code 0.2.5.5 resolves to // DUPLICATE_REGISTRATION — never the unrelated UNKNOWN_COMPRESSOR (0.2.5.1). DuplicateRegistration = errs.Static(CodeDuplicateRegistration, "DUPLICATE_REGISTRATION", "A compressor is already registered under that algorithm", "core/data/transform.Register: a distinct scheme already claims this algorithm, or a nil scheme was supplied", 0, 0) // GzipFailed wraps a failure from compress/gzip (Compress or Decompress). GzipFailed = errs.Static(CodeGzipFailed, "GZIP_FAILED", "gzip transform failed", "service/data/transform: compress/gzip returned an error", 0, 0) // FlateFailed wraps a failure from compress/flate (Compress or Decompress). FlateFailed = errs.Static(CodeFlateFailed, "FLATE_FAILED", "flate transform failed", "service/data/transform: compress/flate returned an error", 0, 0) // ZlibFailed wraps a failure from compress/zlib (Compress or Decompress), // including a failed Adler-32 check the raw-DEFLATE scheme cannot detect. ZlibFailed = errs.Static(CodeZlibFailed, "ZLIB_FAILED", "zlib transform failed", "service/data/transform: compress/zlib returned an error", 0, 0) )
Functions ¶
This section is empty.
Types ¶
type Algorithm ¶
type Algorithm string
Algorithm is the typed key under which a Compressor registers (e.g. "gzip", "flate", "zlib"). The zero value Algorithm("") is reserved invalid, mirroring codec.Format and crypto.Algorithm. Note that "flate" is the raw DEFLATE stream of RFC 1951 and "zlib" is the RFC 1950 envelope HTTP misnames "deflate" — distinct Algorithms, not aliases.
func Available ¶
func Available() []Algorithm
Available returns the sorted list of registered Algorithms, or nil before any Register.
type BoundedDecompressor ¶
type BoundedDecompressor interface {
Compressor
DecompressBounded(dst, src []byte, max int64) (out []byte, err error)
}
BoundedDecompressor is the optional extension for schemes that can be told how much plaintext they are allowed to materialise. Consumers detect support with a type assertion, exactly as they do for the codec layer's Appender.
It exists because a caller that enforces a TIGHTER ceiling than the scheme's own backstop otherwise has no way to say so, and must instead let the scheme materialise everything and then judge the result. Judging afterwards is a correct verdict reached by doing the attacker's work first: a frame layer capping output at 64 MiB but calling plain Decompress still lets a few hundred kilobytes of crafted input drive the scheme's full 256 MiB backstop before the answer is known.
max is a ceiling, never a promise: a scheme MAY refuse a stream below it for its own reasons, and MUST NOT return more than max bytes. A ceiling of zero is a real ceiling — it admits an empty stream and nothing else — and a negative one is clamped to zero rather than given a third meaning, so the bound is monotone in max. A stream that would exceed max fails with DecompressedTooLarge rather than being silently truncated: a short read that looked like success would turn a bomb into a parsing bug further up.
DecompressedTooLarge and NOT the scheme's own sentinel, because the two answer different questions, and because the implementation cannot honestly give the scheme's: it stops reading at the ceiling, short of the trailer the scheme would need to pronounce on the stream at all.
type Compressor ¶
type Compressor interface {
Algorithm() Algorithm
Compress(dst, src []byte) (out []byte, err error)
Decompress(dst, src []byte) (out []byte, err error)
}
Compressor is the contract every byte-transform scheme satisfies. Instances MUST be safe for concurrent use; scheme-specific options are supplied via the scheme's constructor, not via the Compressor interface. Compress and Decompress follow the append-to-dst convention of the stdlib (dst may be nil) so callers can reuse buffers on the hot path.
src must not overlap dst's spare capacity, dst[len(dst):cap(dst)]: every scheme writes its output there while it is still reading src, so an aliased src is overwritten mid-read and the output is corrupt. Reusing one buffer means passing buf[:0] as dst and a DIFFERENT buffer as src — the same rule as copy-free encoders across the stdlib, stated here because no scheme can check it cheaply.
IFACE-PLUGIN: the registry stores plug-in scheme instances behind this interface — concrete scheme types stay unexported per package.
func Lookup ¶
func Lookup(name Algorithm) (c Compressor, ok bool)
Lookup returns the Compressor registered under name.
IFACE-PLUGIN: the registry stores plug-in scheme instances behind the Compressor interface — concrete types are intentionally unexported per scheme.
func Register ¶
func Register(c Compressor) Compressor
Register inserts c into the registry under c.Algorithm() and returns it so callers can bind the singleton to a typed package-level variable like `var GzipCompressor = transform.Register(gzipCompressor{})`. Panics on a nil scheme or when a distinct scheme already claims the same Algorithm.
IFACE-PLUGIN: the registry hands plug-in Compressor instances back to callers so each scheme keeps its concrete type unexported; the stable contract is the Compressor interface itself.
"Nil" here means UNUSABLE, not only an untyped nil: a typed nil pointer and a plug-in whose type is not comparable both satisfy the port and neither can serve one call (see internal/kernel/plugin).