decoder

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: May 17, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package decoder 把不同编码(yaml/json/...)的字节流解码为统一的 map[string]any 中间表示。该中间表示只在 reload 流水线内部存在, 不会出现在公开 API 上。

解码器通过进程内 registry 注册(见 registry.go)。内置 yaml/yml/json 在 init 时注册;外部 codec(toml/hcl/json5/...)可通过 fastconf.RegisterCodec 在仓库外注入。

Phase 130 (SPEC-130) — typed decoder hooks.

FastConf's default decode path round-trips merged maps through encoding/json. That keeps the canonical byte stream coherent with the SHA-256 hash used for dedupe, but encoding/json refuses common "human-readable string → typed value" conversions: "30s" cannot land in a time.Duration, "10.0.0.1" cannot land in net.IP, etc.

TypedHook is a small, opt-in pre-decode rewrite step. BuildTypedPlan inspects *T once at construction and emits a tree describing which leaves carry hook-eligible types and which map-key candidates they can appear under (json tag, lowercase field name, struct field name). Apply walks both the merged map and the plan tree together so it works regardless of whether the source codec wrote canonical-JSON keys or YAML-flavoured lowercase keys.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnknownCodec = errors.New("decoder: unknown codec")

ErrUnknownCodec 表示不识别的 codec 名。

Functions

func CodecFromExt

func CodecFromExt(ext string) string

CodecFromExt infers a codec name from a file extension (with or without the leading dot). Returns empty string when the extension is unrecognised. Queries only codecs registered via RegisterCodec/RegisterCodecExt.

func DecodeAny

func DecodeAny(codec string, data []byte) (any, error)

DecodeAny decodes data as either an object or an array (used for RFC 6902 patch layers whose top-level node is an array). Returns either map[string]any or []any. Returns nil on empty input.

func Lookup

func Lookup(name string) (contracts.Codec, bool)

Lookup returns the codec for name (case-insensitive) along with an "exists" flag. Used by tests to assert registration ordering.

func LookupExt

func LookupExt(ext string) string

LookupExt returns the codec name for a given extension, or "" if the extension is unknown.

func Register

func Register(name string, c contracts.Codec)

Register installs c under the given name (case-insensitive). It is safe for concurrent use. Registering nil panics; that signals a bug at init time and we prefer to fail loudly rather than silently dropping the codec on first use. Re-registering an existing name overwrites it, which makes test helpers and feature toggles ergonomic.

func RegisterExt

func RegisterExt(ext, codec string)

RegisterExt maps a file extension (with or without leading dot, case insensitive) to a codec name. It does NOT register the codec itself — the caller should also call Register if the codec is custom.

Types

type Decoder

type Decoder = contracts.Codec

Decoder 把字节流解码为通用 map。

Decoder 等价于公共契约 contracts.Codec — 内部包以别名形式持有, 任何实现 contracts.Codec 的类型都可直接喂进 internal/decoder 的注册表。

func For

func For(codec string) (Decoder, error)

For 按 codec 名返回 Decoder。codec 不区分大小写。 不在注册表中时返回 ErrUnknownCodec。

type DurationHook

type DurationHook struct{}

DurationHook: "30s" → int64(30 * time.Second).

func (DurationHook) Convert

func (DurationHook) Convert(raw any) (any, error)

func (DurationHook) Match

func (DurationHook) Match(t reflect.Type) bool

type IPHook

type IPHook struct{}

IPHook: "10.0.0.1" → canonical string accepted by net.IP JSON unmarshal.

func (IPHook) Convert

func (IPHook) Convert(raw any) (any, error)

func (IPHook) Match

func (IPHook) Match(t reflect.Type) bool

type RegexHook

type RegexHook struct{}

RegexHook: validates the pattern then passes through.

func (RegexHook) Convert

func (RegexHook) Convert(raw any) (any, error)

func (RegexHook) Match

func (RegexHook) Match(t reflect.Type) bool

type TypedHook

type TypedHook interface {
	// Match reports whether this hook applies to the given destination
	// field type. The walker calls Match once per leaf, cached by type.
	Match(t reflect.Type) bool
	// Convert turns the raw value (usually string) into a value the
	// JSON decoder can natively assign to the target type. Returning
	// (raw, nil) leaves the value untouched.
	Convert(raw any) (any, error)
}

TypedHook converts a raw value into the typed representation that encoding/json round-trip expects for a specific field type.

func DefaultTypedHooks

func DefaultTypedHooks() []TypedHook

DefaultTypedHooks returns the built-in hook set. By design only hooks whose target type has a native JSON wire form survive the pre-decode rewrite (encoding/json must accept the rewritten value). time.Duration → int64 nanoseconds is the canonical example; *url.URL and *regexp.Regexp have no direct JSON form and are exposed as helpers users can install explicitly via WithTypedHook when their schema uses a string-field surrogate.

type TypedHookPlan

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

TypedHookPlan is a struct-shaped plan: each node mirrors a struct field and records which map-key aliases the merged map might use (json tag, yaml tag, lowercase name, exact field name).

func BuildTypedHookPlan

func BuildTypedHookPlan(t reflect.Type, hooks []TypedHook) *TypedHookPlan

BuildTypedHookPlan inspects t and returns a plan that the walker can apply against any merged map. Pointer/elem unwrapping is automatic.

func (*TypedHookPlan) Apply

func (p *TypedHookPlan) Apply(merged map[string]any) error

Apply rewrites every hook-eligible leaf in merged. Returns the first conversion error encountered.

type URLHook

type URLHook struct{}

URLHook: round-trips a URL string after validating.

func (URLHook) Convert

func (URLHook) Convert(raw any) (any, error)

func (URLHook) Match

func (URLHook) Match(t reflect.Type) bool

Jump to

Keyboard shortcuts

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