wire

package
v2.14.0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package wire IS the shellcade game ABI as code: the version handshake, the export and host-function names, and the packed little-endian payload encodings, expressed over neutral types with zero dependencies.

This package is the single source of truth both sides compile against: the gamekit guest SDK maps wire types to its authoring types, and the private host adapter maps them to its engine types. Non-Go guests implement the same layouts from ABI.md, which documents exactly what this package encodes.

Index

Constants

View Source
const (
	// DeltaHeaderBytes is the fixed container header length.
	DeltaHeaderBytes = 9
	// RunHeaderBytes is the per-run prefix (u16 startIndex + u16 runLen).
	RunHeaderBytes = 4
	// KeyframeBytes is the keyframe form's exact size and the worst-case bound:
	// 9-byte header (bit0 set) + one run {start=0, len=FrameCells} + the full
	// 46080-byte packed grid = 46093. The SDK budget rule ships the keyframe
	// when an encoded delta would meet or exceed this (inclusive).
	KeyframeBytes = DeltaHeaderBytes + RunHeaderBytes + FrameBytes // 46093

	// FlagKeyframe is header flags bit0: the payload is a self-contained keyframe.
	FlagKeyframe = 0x01
)

The v2 frame-delta container (normative, ABI.md §4.5). Every send/identical carries this variable-length, little-endian, index-addressed run-list:

Header (9 bytes):
  u8  flags    bit0 = keyframe (1 = full-frame keyframe); all other bits MUST be zero
  u32 epoch    the host-issued epoch this delta is computed against (0 on a fresh instance)
  u16 runCount number of runs (keyframe: exactly 1; no-change: 0)
  u8  rows     grid geometry; MUST be 24 in v2
  u8  cols     grid geometry; MUST be 80 in v2
then runCount runs, each:
  u16 startIndex  first cell index (0..FrameCells-1, == row*Cols+col)
  u16 runLen      1..FrameCells, consecutive changed cells
  runLen × CellBytes  packed canonical-zero cells (PutCell output)

These encoders/validators are index-addressed (mirroring PutCell/GetCell), never the appending Buf, so they are allocation-free over caller-owned scratch — the SDK's leaking-GC steady-state requirement.

View Source
const (
	ExpABI   = "shellcade_abi"
	ExpMeta  = "meta"
	ExpStart = "start"
	ExpJoin  = "join"
	ExpLeave = "leave"
	ExpInput = "input"
	ExpWake  = "wake"
	ExpClose = "close"
)

Guest export names.

View Source
const (
	FnSend            = "send"
	FnIdentical       = "identical"
	FnSetInputContext = "set_input_context"
	FnEnd             = "end"
	FnPost            = "post"
	FnLog             = "log"
	FnKVGet           = "kv_get"
	FnKVSet           = "kv_set"
	FnKVDelete        = "kv_delete"
	FnConfigGet       = "config_get"
)

Host function names.

View Source
const (
	Rows       = 24
	Cols       = 80
	CellBytes  = 24
	FrameCells = Rows * Cols            // 1920
	FrameBytes = FrameCells * CellBytes // 46080
	RowBytes   = Cols * CellBytes       // 1920
)

Frame geometry: 80x24 cells, 24 bytes per v2 grapheme cell.

View Source
const (
	KindGuest  uint8 = 0
	KindMember uint8 = 1
)

Player kind codes.

View Source
const (
	ModeQuick   uint8 = 0
	ModePrivate uint8 = 1
	ModeSolo    uint8 = 2
)

Mode codes.

View Source
const (
	StatusFinished uint8 = 0
	StatusDNF      uint8 = 1
	StatusFlagged  uint8 = 2
)

Status codes.

View Source
const (
	InputRune uint8 = 0
	InputKey  uint8 = 1
)

Input kind codes.

View Source
const (
	CtxRosterUnchanged uint16 = 0xFFFF
	CtxRosterFull      uint16 = 0xFFFE
	CtxRosterMaxCount  uint16 = 0xFFFD
)

Ctx member-section sentinels (roster-epoch mode). Real rosters are capped far below these values, so the count u16 disambiguates the three forms: 0..CtxRosterMaxCount = legacy full roster (no epoch), CtxRosterFull = u32 epoch + u16 real count + members, CtxRosterUnchanged = u32 epoch only.

View Source
const (
	// CtxFeatRosterEpoch opts the guest into the ctx member-section sentinel
	// forms: full roster only on change (with an epoch), 6-byte unchanged
	// sections otherwise.
	CtxFeatRosterEpoch uint32 = 1 << 0

	// CtxFeatCharacter opts the guest into per-member character sections
	// (ABI.md §4.1): str glyph + ink RGB + bg RGB + ascii fallback, appended
	// after each member's Kind byte in both member-bearing forms.
	CtxFeatCharacter uint32 = 1 << 1

	// KnownCtxFeatures is the mask of bits this wire revision defines.
	KnownCtxFeatures uint32 = CtxFeatRosterEpoch | CtxFeatCharacter
)

CtxFeatures bits a game may declare in its meta trailer. The host ignores bits it does not implement; the SDKs reject bits they do not define.

View Source
const (
	LifecycleResumable uint8 = 0
	LifecycleEphemeral uint8 = 1
	LifecycleResident  uint8 = 2
)

Lifecycle values for the meta trailer.

View Source
const (
	ConfigText   uint8 = 0
	ConfigNumber uint8 = 1
	ConfigBool   uint8 = 2
	ConfigJSON   uint8 = 3
)

Config value type codes (how the admin surface renders/validates a value).

View Source
const (
	KeyCodeEnter     uint8 = 1
	KeyCodeBackspace uint8 = 2
	KeyCodeEsc       uint8 = 3
	KeyCodeTab       uint8 = 4
	KeyCodeUp        uint8 = 5
	KeyCodeDown      uint8 = 6
	KeyCodeLeft      uint8 = 7
	KeyCodeRight     uint8 = 8
	KeyCodeCtrlC     uint8 = 9
)

Named key codes carried in input payloads and ControlDecl (the InputKey value space; match the SDK Key enum).

View Source
const (
	HeartbeatMinMS uint16 = 20
	HeartbeatMaxMS uint16 = 1000
)

Heartbeat declaration envelope (mirrors the host's clamp range).

View Source
const ControlLabelMaxRunes = 16

ControlLabelMaxRunes caps a declared control's display label.

View Source
const HostKeyPrefix = "host."

HostKeyPrefix is the reserved config-key namespace interpreted by the host (e.g. host.heartbeat_ms). Games MUST NOT declare specs under it — the platform declares those knobs itself.

View Source
const HostNamespace = "extism:host/user"

HostNamespace is the wasm import namespace for shellcade host functions.

View Source
const MaxControls = 32

MaxControls caps the declared-controls list: a control surface for the handful of inputs beyond the canonical vocabulary, not a keymap dump.

View Source
const MaxDeltaBytes = KeyframeBytes

MaxDeltaBytes is a scratch-buffer cap big enough for any delta this package emits: the run-list worst case never exceeds the keyframe form (the SDK caps it there), so KeyframeBytes is a sufficient and exact ceiling.

View Source
const Revision uint16 = 6

Revision is the wire revision: a monotonic counter of the wire-visible minor additions within ABI major Version, bumped in the same change that lands each addition (ABI.md §5). SDK encoders stamp it automatically into the meta payload's trailing wireRevision field, giving hosts a per-artifact declaration of the newest wire feature the artifact may assume — the mechanical anchor for the deploy-order rule (a host warns on or refuses artifacts declaring a revision above its own compiled-in Revision).

Ledger (the revision that INTRODUCED each wire-visible minor):

0 — unknown: the meta predates the wireRevision field (kit ≤ v2.7.x)
1 — config-spec meta section (kit v2.3.0)
2 — large-room meta section + ctx roster-epoch sentinels (kit v2.6.0)
3 — lifecycle meta byte (kit v2.7.0)
4 — the wireRevision meta field itself
5 — per-member character section behind CtxFeatCharacter (str glyph ·
    u8 ink RGB · u8 bg RGB · u8 asciiFallback after kind, both
    member-bearing forms)
6 — declared-controls meta section (u16 count of {u8 kind ·
    u32 rune | u8 key · str label} after wireRevision)

Revisions 1–3 predate the field, so artifacts of those eras decode as 0; only 0 or values ≥ 4 are ever observed on the wire. Any future change that adds a wire-visible encoding (a new trailing meta section, a ctx-feature bit, a delta flag bit, a new host function the guest calls, …) MUST append a ledger entry and bump this constant in the same change.

Like RosterCap, this is a protocol constant mirrored by the Rust guest SDK (rust/src/wire.rs WIRE_REVISION, asserted equal to this constant by TestRustWireRevisionMatchesWire in this package) — the two must change in lockstep.

View Source
const RosterCap = 1024

RosterCap is the contract-wide roster ceiling for per-index frame baselines: an SDK sizes its baseline table to RosterCap slots (plus the broadcast slot, conventionally at index RosterCap) and silently drops Send for a roster index >= RosterCap, and the host bounds-checks the send index and sizes its per-slot cache the same way (ABI.md §3, §4.6). 1024 since the large-room scale work (kit v2.5.0 Go / v2.7.0 Rust).

This is a protocol invariant shared by every implementation — the Go guest SDK (internal/game), the Rust guest SDK (rust/src/broadcast.rs ROSTER_CAP, asserted equal to this constant by TestRustRosterCapMatchesWire in this package), and the host adapter — so changing it is ABI-affecting and must land in all of them in lockstep.

View Source
const Version uint32 = 2

Version is the ABI major version.

Variables

This section is empty.

Functions

func ApplyFrameDelta

func ApplyFrameDelta(prev, delta []byte) error

ApplyFrameDelta applies a (validated) delta in place to prev, a FrameBytes baseline buffer: each run's cells are copied into prev at startIndex*24, so a keyframe (one full-cover run) overwrites all 1920 cells. It re-validates structurally (so a caller may apply untrusted bytes safely) and returns errMalformedDelta on any malformation, never panicking, never reading OOB, and never partially mutating prev on a malformed container (it validates fully first). It allocates nothing.

func BuildFrameDelta

func BuildFrameDelta(base, next, dst []byte, epoch uint32) int

BuildFrameDelta is the reference delta encoder: it diffs the packed frames base vs next into the caller-provided scratch dst (sized to at least MaxDeltaBytes) and returns the number of payload bytes. It coalesces changed cells into MAXIMAL runs of consecutive changed cells, greedy left-to-right (gap = 0): a single unchanged cell between two changed spans forces two runs. That determinism is what makes cross-implementation golden vectors byte-identical. epoch is stamped into the header (the slot's host-issued epoch). It allocates nothing.

A runCount==0 result (the 9-byte header alone) is the canonical no-change delta. The keyframe form is NOT produced here — callers apply the budget rule (>= KeyframeBytes ⇒ BuildKeyframe) on the returned length.

func BuildKeyframe

func BuildKeyframe(next, dst []byte, epoch uint32) int

BuildKeyframe writes the keyframe form into dst: a 9-byte header (flags bit0 set), one run {startIndex=0, runLen=FrameCells} and the full packed grid next. Returns KeyframeBytes (46093). It allocates nothing.

func CheckFrame

func CheckFrame(b []byte) error

CheckFrame validates a full-frame payload length (the bare packed grid; used by the host-side baseline buffers, not the wire send path, which carries the delta container instead — see CheckFrameDelta).

func CheckFrameDelta

func CheckFrameDelta(b []byte) error

CheckFrameDelta validates a frame-delta container structurally without ever panicking or reading out of bounds (the drop-not-fatal contract). It checks:

  • len >= 9 (header present)
  • geometry bytes == (Rows, Cols) == (24, 80)
  • no unknown flag bits set (only bit0 is assigned in v2 — rejected, not ignored)
  • runCount consistent with body length: 9 + Σ(4 + runLen*24) == len(b)
  • every run in-bounds: startIndex+runLen <= FrameCells
  • runs strictly ascending and non-overlapping: start[i] >= start[i-1]+len[i-1]

A short read degrades to errMalformedDelta. It does NOT require runs to be minimal, greedy, or true diffs — host acceptance is the envelope, so a hand-rolled guest's structurally valid container passes.

func DeltaEpoch

func DeltaEpoch(b []byte) uint32

DeltaEpoch reads the epoch field from a container header without validating the rest. Callers use it to decide acceptance; it returns 0 on a short read.

func EncodeCtx

func EncodeCtx(w *Buf, c Ctx)

EncodeCtx appends the packed CallContext to w in the LEGACY form (full roster, no epoch) — the only form pre-roster-epoch guests understand, and byte-identical to all prior wire revisions. Character fields on Player are silently ignored. This is a frozen features=0 wrapper around EncodeCtxFeat.

func EncodeCtxEpoch

func EncodeCtxEpoch(w *Buf, c Ctx, epoch uint32, full bool)

EncodeCtxEpoch appends the packed CallContext in roster-epoch mode (only for guests whose meta declares CtxFeatRosterEpoch). full=true emits the CtxRosterFull sentinel (epoch + real count + members); full=false emits the CtxRosterUnchanged sentinel (epoch only — the member section is 6 bytes regardless of roster size, and c.Members is not read). Character fields on Player are silently ignored. This is a frozen features=0 wrapper around EncodeCtxEpochFeat.

func EncodeCtxEpochFeat added in v2.9.0

func EncodeCtxEpochFeat(w *Buf, c Ctx, epoch uint32, full bool, features uint32)

EncodeCtxEpochFeat appends the packed CallContext in roster-epoch mode, encoding per-member character sections after each Kind byte when features&CtxFeatCharacter != 0. For guests that do not declare CtxFeatCharacter pass features=0 (or use EncodeCtxEpoch).

func EncodeCtxFeat added in v2.9.0

func EncodeCtxFeat(w *Buf, c Ctx, features uint32)

EncodeCtxFeat appends the packed CallContext to w in the legacy full-roster form, encoding per-member character sections after each Kind byte when features&CtxFeatCharacter != 0. For guests that do not declare CtxFeatCharacter pass features=0 (or use EncodeCtx).

func EncodeMeta

func EncodeMeta(m Meta) []byte

EncodeMeta packs a Meta.

func EncodeResult

func EncodeResult(res Result) []byte

EncodeResult packs a Result.

func IsKeyframe

func IsKeyframe(b []byte) bool

IsKeyframe reports whether the container's flags carry the keyframe bit. It returns false on a short read.

func PutCell

func PutCell(buf []byte, i int, c Cell)

PutCell writes one cell at index i (0..FrameCells-1) into a FrameBytes buffer using the v2 24-byte anchor layout:

rune@0  cp2@4  cp3@8  fg@12..15  bg@16..19  attr@20  cont@21  pad@22..23

PutCell is the normative CANONICAL-ZERO enforcer: it always writes pad = 0 and writes whatever cp2/cp3 the cell carries (0 = unused), so even a hand-built Cell with garbage left in a slot it should not use serializes canonically — cell equality is then exactly a 24-byte memcmp, which is load-bearing for delta determinism and hibernation byte-identity.

func ValidateConfigSpecs

func ValidateConfigSpecs(specs []ConfigSpec) error

ValidateConfigSpecs enforces the authoring rules for declared config specs, shared by guest SDK encoders and host/CLI decoders: keys non-empty and unique, no reserved host. prefix, a known type code, and Schema only on JSON-typed keys where it must itself parse as JSON. The JSON check is a well-formedness scan (json.Valid) — schema COMPILATION is a host concern, keeping this package dependency-free.

func ValidateControls added in v2.10.0

func ValidateControls(decls []ControlDecl) error

ValidateControls enforces the authoring rules for declared controls, shared by guest SDK encoders and host/CLI decoders (the same fail-fast posture as ValidateConfigSpecs): a known input kind; a printable rune or an assigned named-key code; a non-empty label of at most ControlLabelMaxRunes runes; no duplicate inputs; at most MaxControls declarations.

func ValidateLifecycle

func ValidateLifecycle(lifecycle uint8, minPlayers uint16) error

ValidateLifecycle is the shared authoring rule set for the lifecycle declaration, enforced at meta() encode time by both SDKs: the value must be a defined lifecycle, and resident cannot be combined with minPlayers > 1 (a resident room runs with zero members).

func ValidateMetaTrailer

func ValidateMetaTrailer(ctxFeatures uint32, heartbeatMS uint16) error

ValidateMetaTrailer is the shared authoring rule set for the large-room meta section, enforced at meta() encode time by both SDKs (the same fail-fast posture as ValidateConfigSpecs): no undefined ctx-feature bits; heartbeat 0 (no declaration) or within [HeartbeatMinMS, HeartbeatMaxMS].

Types

type Buf

type Buf struct{ B []byte }

Buf is a little-endian append-only encoder.

func (*Buf) Bool

func (w *Buf) Bool(v bool)

func (*Buf) I64

func (w *Buf) I64(v int64)

func (*Buf) Str

func (w *Buf) Str(s string)

func (*Buf) U8

func (w *Buf) U8(v uint8)

func (*Buf) U16

func (w *Buf) U16(v uint16)

func (*Buf) U32

func (w *Buf) U32(v uint32)

type Cell

type Cell struct {
	Rune          rune
	Cp2           rune
	Cp3           rune
	FGSet         bool
	FGR, FGG, FGB uint8
	BGSet         bool
	BGR, BGG, BGB uint8
	Attr          uint8
	Cont          bool
}

Cell is one drawable cell of a frame. In v2 it carries up to three code points of a grapheme cluster: Rune is the base, Cp2/Cp3 the extra code points (0 = unused). The packed form is exactly 24 bytes (CellBytes), with the canonical-zero rule (unused cp slots and pad are zero) enforced by PutCell so cell equality is a 24-byte memcmp.

func GetCell

func GetCell(buf []byte, i int) Cell

GetCell reads one cell at index i from a FrameBytes buffer (24-byte layout).

type Character added in v2.9.0

type Character struct {
	Glyph    string // single width-1 glyph (unicode)
	InkR     uint8
	InkG     uint8
	InkB     uint8
	BgR      uint8
	BgG      uint8
	BgB      uint8
	Fallback uint8 // ASCII fallback codepoint
}

Character is the per-player resolved character, encoded after the Kind byte in every member-bearing Ctx section iff the guest's meta declares CtxFeatCharacter. The zero value means "not declared / not encoded".

type ConfigSpec

type ConfigSpec struct {
	Key         string // the config_get key the game reads
	Title       string // short admin-facing label
	Description string // one-or-two-sentence admin help
	Type        uint8  // ConfigText..ConfigJSON
	Default     string // value the game uses when unset ("" = not declared)
	Schema      string // JSON Schema document (json type only; "" = none)
}

ConfigSpec is one declared admin-settable config key in the meta payload.

type ControlDecl added in v2.10.0

type ControlDecl struct {
	Kind  uint8  // InputRune or InputKey
	Rune  rune   // the printable rune (Kind == InputRune)
	Key   uint8  // the named key code (Kind == InputKey; KeyCodeEnter..KeyCodeCtrlC)
	Label string // short display label, 1..16 runes
}

ControlDecl is one declared extra control in the meta payload: the exact input it sends — a printable rune or a named key, the same value space as input events — plus a short display label (e.g. "RESIGN").

type Ctx

type Ctx struct {
	NowUnixNanos int64
	Seed         int64
	SeedSet      bool
	Mode         uint8
	Capacity     uint16
	MinPlayers   uint16
	Members      []Player
	Settled      bool

	// Roster-epoch mode (spec minor addition; emitted only to guests whose
	// meta declares CtxFeatRosterEpoch). RosterEpochSet marks a sentinel-form
	// member section: RosterUnchanged means the section carried only the
	// epoch (Members is nil — the guest reuses its cached roster); otherwise
	// Members is the full roster at RosterEpoch.
	RosterEpoch     uint32
	RosterEpochSet  bool
	RosterUnchanged bool
}

Ctx is the CallContext every host→guest callback carries.

func DecodeCtx

func DecodeCtx(r *Rd) Ctx

DecodeCtx reads a CallContext, leaving r positioned at the event extras. It recognises all three member-section forms; on the unchanged sentinel Members is nil and RosterUnchanged is true (the caller supplies its cached roster). Character fields are never populated. This is a frozen features=0 wrapper around DecodeCtxFeat.

func DecodeCtxFeat added in v2.9.0

func DecodeCtxFeat(r *Rd, features uint32) Ctx

DecodeCtxFeat reads a CallContext encoded with the given features bitset, populating per-member Character fields when features&CtxFeatCharacter != 0. For payloads encoded without CtxFeatCharacter pass features=0 (or use DecodeCtx). Passing features=CtxFeatCharacter against a features-0 payload will trigger a short-read and set r.Bad — this is intentional (host-fault contract: features must match the payload). Unlike roster-epoch, whose forms are self-describing via the count u16's spare sentinel space, per-member trailing bytes carry no in-band discriminator — hence the out-of-band features parameter.

type Meta

type Meta struct {
	Slug              string
	Name              string
	ShortDescription  string
	MinPlayers        uint16
	MaxPlayers        uint16
	Tags              []string
	QuickModeLabel    string
	SoloModeLabel     string
	PrivateInviteLine string

	HasLeaderboard bool
	MetricLabel    string
	Direction      uint8
	Aggregation    uint8
	Format         uint8

	// ConfigSpecs is the trailing config-spec section (spec minor addition):
	// the game's declared admin-settable config keys. Encoders always write
	// the section (count 0 when empty); decoders treat a payload ending after
	// the leaderboard block as a valid pre-config meta with no specs.
	ConfigSpecs []ConfigSpec

	// CtxFeatures + HeartbeatMS form the trailing large-room section (spec
	// minor addition) after the config-spec section. CtxFeatures is the
	// negotiated-encoding bitset (CtxFeat*); HeartbeatMS is the game's
	// declared wake cadence (0 = no declaration; host precedence: admin
	// config > declaration > platform default, clamped to the platform
	// envelope). Encoders always write the section; decoders treat a payload
	// ending after the config-spec section as a valid older meta with zero
	// values.
	CtxFeatures uint32
	HeartbeatMS uint16

	// Lifecycle is the room end-of-life declaration (spec minor addition;
	// trailing byte after HeartbeatMS): 0 resumable (hibernate on abandon —
	// today's behavior and the zero-value default), 1 ephemeral (end +
	// dispose on abandon; no snapshot, no Resume entry), 2 resident (one
	// long-lived granted room per slug). Hosts treat values they do not
	// implement as resumable.
	Lifecycle uint8

	// WireRevision is the trailing wire-revision declaration (spec minor
	// addition; u16 after the lifecycle byte): the wire.Revision of the kit
	// the artifact was built against. 0 = unknown — the artifact predates
	// the field. SDK encode paths stamp wire.Revision automatically (it is
	// not author-settable); hosts use it to warn on or refuse artifacts
	// declaring a revision above their own (ABI.md §4.2, §5).
	WireRevision uint16

	// Controls is the trailing declared-controls section (spec minor
	// addition; u16 count after WireRevision): the game's extra controls —
	// inputs beyond the canonical vocabulary, each paired with a short
	// display label so a front end on a device without the corresponding
	// physical key (touch) can surface a tappable affordance that sends
	// exactly the declared input. Presentation metadata only: a declaration
	// changes no input interpretation. Encoders always write the section
	// (count 0 when empty); decoders treat a payload ending after the
	// wire-revision field as a valid older meta with no declarations.
	Controls []ControlDecl
}

Meta is the packed GameMeta.

func DecodeMeta

func DecodeMeta(b []byte) (Meta, error)

DecodeMeta parses a packed Meta.

type Player

type Player struct {
	Handle    string
	AccountID string
	Conn      string
	Kind      uint8
	Character Character
}

Player is one roster entry.

type Ranking

type Ranking struct {
	PlayerIdx uint32 // roster index in the callback's Ctx
	Metric    int64
	Rank      uint16
	Status    uint8
}

Ranking is one player's outcome in an end/post payload.

type Rd

type Rd struct {
	B   []byte
	Off int
	Bad bool
}

Rd is a bounds-checked little-endian decoder.

func (*Rd) Bool

func (r *Rd) Bool() bool

func (*Rd) Err

func (r *Rd) Err() error

Err returns the decode error state.

func (*Rd) I64

func (r *Rd) I64() int64

func (*Rd) SkipStr

func (r *Rd) SkipStr()

SkipStr advances past one length-prefixed string without materializing it — the allocation-free skim used by the SDK's roster cache to find the member section's extent before deciding whether to decode it.

func (*Rd) Str

func (r *Rd) Str() string

func (*Rd) U8

func (r *Rd) U8() uint8

func (*Rd) U16

func (r *Rd) U16() uint16

func (*Rd) U32

func (r *Rd) U32() uint32

type Result

type Result struct {
	Rankings []Ranking
}

Result is the end/post payload.

func DecodeResult

func DecodeResult(b []byte) (Result, error)

DecodeResult parses a packed Result.

Jump to

Keyboard shortcuts

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