libjson

package
v1.75.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: BSD-3-Clause Imports: 22 Imported by: 1

Documentation

Index

Examples

Constants

View Source
const (
	DefaultTypedMaxDepth  = 1024
	DefaultTypedMaxBytes  = 16 << 20
	DefaultTypedMaxValues = 1 << 20
)

Default limits of DumpTyped, LoadTyped and Canonize. They bound the work and memory of one call on hostile or accidental input; each can be changed with an option for typed encoding/decoding; Canonize only lowers these limits.

View Source
const DefaultPackageName = "json"

DefaultPackageName is the package name used by LoadPackage.

View Source
const DurableFormatVersion = 1

DurableFormatVersion is the format version every durable document starts with. It is frozen: LoadDurable rejects any other version.

Variables

View Source
var ErrTypedLimit = errors.New("typed json: limit exceeded")

ErrTypedLimit is wrapped by every error that reports a configured limit.

Functions

func Builtins

func Builtins(s *Serializer) []*libutil.Builtin

Builtins takes the default serializer for a lisp environment and returns a set of package builtin functions that use it.

The string-numbers and exact-integers modes the builtins set are stored as bindings in the runtime's DefaultPackageName ("json") package, whichever package the builtins are registered in, so template-forked VMs each keep their own copy (#678). Register them through LoadPackage. An environment that has no "json" package falls back to the serializer's fields, which every VM sharing s also shares; do not publish such an environment as a template.

func Canonize added in v1.74.0

func Canonize(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)

Canonize returns a fresh plain JSON image of v, using exact integer types. It walks values directly, without encoding and decoding a document. For every successful result c, Dump(c, false) == Dump(v, false) == DumpTyped(c); LoadWith(..., LoadOpts{ExactIntegers:true}) and LoadTyped return exactly c, and Canonize(c) equals c. Limits and incremental step charging use the same TypedOptions as DumpTyped. Options may lower the default limits; raising them cannot admit values beyond the default typed limits, since such results would violate the invariant.

Leading tilde strings, invalid UTF-8, integers beyond +/-2^53, nonfinite floats, negative zero, whole-number floats outside the exact/platform int range, int map keys, collisions and changed member order are errors. Opaque native encodings and native numbers are refused: their JSON spelling or treatment of StringNumbers cannot be preserved by a direct value walk. CanonizeBuiltin exposes these data rejections as json:canonize-error, with (message, case keyword, path) data for Lisp handlers.

func CanonizeBuiltin added in v1.74.0

func CanonizeBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

CanonizeBuiltin implements json:canonize and propagates runtime budget conditions unchanged, while charging each started KiB during the walk.

func Dump

func Dump(v *lisp.LVal, stringNums bool) ([]byte, error)

Dump serializes the structure of v as a JSON formatted byte slice.

Dump has no runtime, so unlike the json:dump-* builtins it is bounded by neither Runtime.MaxAlloc nor an evaluation context. An embedder serializing values a lisp program controls should call a json:dump-* builtin instead (see docs/lang.md, "Allocation Limits").

func DumpDurable added in v1.75.0

func DumpDurable(env *lisp.LEnv, v *lisp.LVal, reg *DurableRegistry, opts ...TypedOption) ([]byte, error)

DumpDurable writes v as a durable typed JSON document: ["~#durable",[1,VALUE]]. VALUE is v's typed JSON with extension tags. An object (a nonempty list, a vector or array, a sorted map, a tagged value, bytes, an error or a native) that is reached more than once is written once as ["~#obj",[ID,X]] and then as ["~#ref",ID], so LoadDurable restores the sharing and any cycle. An object reached once is written exactly as DumpTyped writes it. The same value graph always gives the same bytes.

env resolves function names and is passed to the native codecs. A native value is written through the codec reg holds for its Go type; reg may be nil when v holds no natives. A registered builtin is written as ["~#builtin",["PKG","NAME"]], the package and name env's registry registered it under (lisp.PackageRegistry.RegisteredBuiltinName), whatever its names bind. A Lisp function, or a builtin no registration names, that a global binds is written as ["~#fn","PKG:NAME"]: PKG is its defining package and NAME the first name, in sorted order, under which PKG binds it.

Lists and arrays whose cells share storage (a list and its tail, a slice of a vector, arrays over one data list) keep that sharing: the storage is written once and each value as a view of it (see durable_views.go). A program literal (a sealed list) is written as ["~#lit",X] and restores as a literal that the mutators refuse.

An error value is written as ["~#error",["CONDITION",[DATA...]]] and restores as an error with the same condition and data, without its call stack or source location (see durable_errors.go).

A lambda no global binds (a closure) is written with its code and the frames it captured (see durable_closures.go).

Refused with an error: internal panics, errors whose condition is empty or not UTF-8, builtins no global binds, macros and special operators (also when a closure captured one), natives with no codec, a native whose payload reaches the native or an object that encloses it (directly or through finished objects), a shared value in the payload of a codec registered without WithSharedPayload, and every value DumpTyped refuses for a reason other than sharing.

opts are typed JSON's limits and charge; see docs/internals/durable-json.md for what each one counts. The byte and value limits never exceed env's per-operation allocation cap. reg must be frozen.

Example
package main

import (
	"fmt"

	"github.com/luthersystems/elps/lisp"
	"github.com/luthersystems/elps/lisp/lisplib/libjson"
)

func main() {
	env := lisp.NewEnv(nil)
	lisp.InitializeUserEnv(env)
	m := lisp.SortedMap()
	m.MapSetLVal(lisp.String("self"), m)
	b, err := libjson.DumpDurable(env, lisp.QExpr([]*lisp.LVal{m, m}), nil)
	fmt.Println(string(b), err)
	back, _ := libjson.LoadDurable(env, b, nil)
	fmt.Println(back.Cells[0] == back.Cells[1])
}
Output:
["~#durable",[1,["~#list",[["~#obj",[0,{"self":["~#ref",0]}]],["~#ref",0]]]]] <nil>
true

func DumpDurableRoots added in v1.75.0

func DumpDurableRoots(env *lisp.LEnv, roots []DurableRoot, reg *DurableRegistry, opts ...TypedOption) ([]byte, error)

DumpDurableRoots writes named values as one durable document, so values shared between roots stay shared. The roots are written in the order of the slice, and that order decides the object ids, so a caller that wants one encoding per set of names passes them in a fixed order (sorted, for example). The value is the list of alternating names and values, ("name1" value1 "name2" value2 ...), or () for no roots. Names must be nonempty, valid UTF-8 and distinct. See DumpDurable for the rest.

func DumpTyped added in v1.74.0

func DumpTyped(v *lisp.LVal, opts ...TypedOption) ([]byte, error)

DumpTyped writes v as typed JSON: exactly the bytes of Dump(Tag(v), false), without building Tag(v).

Supported: ints, floats (NaN and the infinities included), strings (which, like symbol, keyword, map key and tagged type names, must be valid UTF-8), bytes, symbols, keywords, lists (quoted or not: the quote flag is not data), arrays of any rank, sorted maps and tagged values. Functions, native values, errors, nested quotes and values that contain themselves are rejected with an error, so a caller that uses the bytes as a key (a memo key, a SHA-256 content hash) can fall back when a value has no encoding.

The encoding is type-faithful and so finer than equal?: 1 and 1.0 encode differently ("1" and "\"~d1\""), and so do a string and a symbol of one spelling. Values of the same types and structure always give the same bytes, whatever order a map was built in and whichever cells are shared; shared structure is written in full at each occurrence, so a small value whose tree expansion passes the value or byte limit is rejected.

func DumpTypedBuiltin added in v1.74.0

func DumpTypedBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

DumpTypedBuiltin is the runtime adapter for typed dumping across the JSON family.

func DumpWith added in v1.74.0

func DumpWith(v *lisp.LVal, opts DumpOpts) ([]byte, error)

DumpWith encodes v under opts without changing the existing Dump API.

func Load

func Load(b []byte, stringNums bool) *lisp.LVal

Load parses b as JSON and returns an equivalent LVal.

func LoadDurable added in v1.75.0

func LoadDurable(env *lisp.LEnv, b []byte, reg *DurableRegistry, opts ...TypedOption) (*lisp.LVal, error)

LoadDurable decodes a document DumpDurable wrote and rebuilds its value graph: each ["~#obj",[ID,X]] is one value, and every ["~#ref",ID] is that same value, so sharing and cycles come back as they were saved. Natives are rebuilt by the codecs reg holds (reg may be nil when the document holds none), ["~#builtin",["PKG","NAME"]] is the builtin env's registry registered as PKG:NAME (lisp.PackageRegistry.RegisteredBuiltin), whatever that name holds now, and ["~#fn","PKG:NAME"] is the function env's registry binds to that global now, which must be a regular function of package PKG. An ["~#error",...] is an error value with its condition and data, and no call stack or source location; the result itself may be one. A ["~#closure",...] is rebuilt with LEnv.RestoreLambda over frames chained to env's root, and nothing is evaluated.

LoadDurable accepts only what DumpDurable writes. It rejects every input LoadTyped rejects inside the value, a missing header or another format version, an object id out of sequence, an object no reference uses, a reference to an object not yet defined or to the object being defined, a native payload that reaches an unfinished object (directly or through finished ones), sharing inside the payload of a codec registered without WithSharedPayload, an unknown native name or version, a builtin that is not registered as a regular function under its package and name, a function name that does not resolve to a regular function of its package, and an error whose condition is empty or internal-panic. A function may be named by any of its package's names for it, and a ~#fn global may hold a registered builtin (one an upgrade moved to Go), so such a document can re-encode to other bytes. It never panics on malformed input; a native codec is called only with a fully restored payload.

Values are freshly allocated, except builtins, which are the registered values, named functions, which are the current global bindings, and natives, which are whatever their codecs return. Memory is bounded by the input, as for LoadTyped. The byte and value limits never exceed env's per-operation allocation cap. Unlike LoadTyped, LoadDurable calls the charge function: ceil(n/1024) units for n input bytes before it decodes, and each codec's declared charge before each LoadNative call. reg must be frozen.

func LoadPackage

func LoadPackage(env *lisp.LEnv) *lisp.LVal

LoadPackage adds the json package to env

func LoadTyped added in v1.74.0

func LoadTyped(b []byte, opts ...TypedOption) (*lisp.LVal, error)

LoadTyped decodes typed JSON: the same value as Untag of a Strict, ExactIntegers plain load of b, in one pass. Anything DumpTyped could not have produced is rejected with an error: whitespace, a member out of UTF-8 byte order or duplicated, number text other than the canonical text of its value (1.50, 1E5, -0, 01, an int written as a float or past 2^53 as a number), an escape outside the plain encoder's set or a missing mandatory escape, an unknown or misused tag, a tagged empty list, non-canonical base64, trailing bytes, and input over any configured limit. It never panics on malformed input.

Every value it returns is freshly allocated and shares no storage with b or with any other value, so the caller owns it outright. Plain JSON arrays come back as vectors, null as nil, and tagged lists as data lists, as list builds them. A tagged value comes back with its type name and data, and is not checked against any type defined with deftype.

Memory is bounded by the input: every value costs at least one byte of it, and nothing is reserved from a count the input declares.

func LoadTypedBuiltin added in v1.74.0

func LoadTypedBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

LoadTypedBuiltin is the runtime adapter for typed loading across the JSON family.

func LoadWith added in v1.50.0

func LoadWith(b []byte, opts LoadOpts) *lisp.LVal

LoadWith parses b as JSON under opts and returns an equivalent LVal.

func RegisterNative added in v1.75.0

func RegisterNative[T any](r *DurableRegistry, name string, version int, c NativeCodec, opts ...NativeOption) error

RegisterNative registers codec c for native payloads of Go type T. See DurableRegistry.Register.

func Tag added in v1.74.0

func Tag(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)

Tag transforms v into plain JSON values without losing its data types. Whole floats use ~d followed by appendJSONFloat text, including ~d-0. Limits count logical values and containers, without counting tag wrappers.

func TagBuiltin added in v1.74.0

func TagBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

TagBuiltin returns a plain JSON value with type tags.

func Untag added in v1.74.0

func Untag(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)

Untag restores the data types represented by Tag. Unknown tags and malformed forms return an error. Input must contain plain JSON values.

func UntagBuiltin added in v1.74.0

func UntagBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

UntagBuiltin restores the types of a plain JSON value with type tags.

Types

type DumpOpts added in v1.74.0

type DumpOpts struct {
	StringNumbers bool
	Canonize      bool
	Typed         bool
}

DumpOpts opts into canonical or typed output. The zero value preserves existing plain output. Canonical and typed modes ignore package defaults; StringNumbers is explicit and cannot be combined with Typed.

type DurableRegistry added in v1.75.0

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

DurableRegistry maps native Go types to their codecs and stable names. The zero value is not usable; call NewDurableRegistry. Register every codec when the environment is built, then call Freeze. DumpDurable and LoadDurable refuse a registry that is not frozen, and a frozen registry refuses Register, so the codecs cannot change while documents are written or read. A frozen registry is safe for concurrent use. Registration order never changes a document's bytes.

func NewDurableRegistry added in v1.75.0

func NewDurableRegistry() *DurableRegistry

NewDurableRegistry returns an empty registry.

func (*DurableRegistry) Fingerprint added in v1.75.0

func (r *DurableRegistry) Fingerprint() string

Fingerprint describes the registered codecs as JSON: an array of {"name","type","shape","version","charge","shared"} objects sorted by name. type is the package-qualified Go type name. shape is its structure (see typeShape), because two types declared inside functions of one Go package can share a name. A named component contributes only its qualified name, so two function-scope types still collide when they, or the named components they contain, share qualified names and differ only inside those components (C struct{ V Leaf } with a local Leaf int in one function and Leaf string in another). Declare codec types, and the types they contain, at package level. Peers compare the fingerprint to check that they hold the same registry.

func (*DurableRegistry) Freeze added in v1.75.0

func (r *DurableRegistry) Freeze()

Freeze ends registration. Call it once every codec is registered.

func (*DurableRegistry) Frozen added in v1.75.0

func (r *DurableRegistry) Frozen() bool

Frozen reports whether Freeze was called.

func (*DurableRegistry) Register added in v1.75.0

func (r *DurableRegistry) Register(typ reflect.Type, name string, version int, c NativeCodec, opts ...NativeOption) error

Register adds codec c for native values whose payload (LVal.Native) has Go type typ. name is written into every document and must never change for that type; qualify it, for example "substrate:bptree". version is the payload version DumpDurable writes, starting at 1. Register returns an error for an empty or invalid name, a version below 1, a nil type or codec, and a type or name that is already registered.

type DurableRoot added in v1.75.0

type DurableRoot struct {
	Value *lisp.LVal
	Name  string
}

DurableRoot is one named value of a durable document of roots.

func LoadDurableRoots added in v1.75.0

func LoadDurableRoots(env *lisp.LEnv, b []byte, reg *DurableRegistry, opts ...TypedOption) ([]DurableRoot, error)

LoadDurableRoots decodes a document DumpDurableRoots wrote and returns its roots in the order they were written. It rejects a document whose value is not a list of distinct names and values, and one whose root list is not a plain list (shared, a literal or a view): DumpDurableRoots builds that list fresh. See LoadDurable for the rest.

type LoadOpts added in v1.50.0

type LoadOpts struct {
	// MaxAlloc bounds the number of elements in any single array or object in
	// the document.  Zero means unbounded.
	MaxAlloc int

	// StringNumbers decodes every JSON number as a lisp string holding the
	// number's literal text.  It takes precedence over ExactIntegers: a
	// caller that sets both gets strings, exactly as it does today.
	StringNumbers bool

	// ExactIntegers decodes a JSON integer literal as a lisp int rather than
	// a lisp float.
	//
	// encoding/json decodes every JSON number into a float64, and a float64
	// carries 53 bits of integer precision.  So with ExactIntegers false --
	// the default, and the only behaviour that existed before this option --
	// an integer larger than 2^53 is rounded to the nearest float64 on the
	// way in, and NOTHING reports it: the rounded value still compares = to
	// the integer it was meant to be, so a program can read a corrupted
	// identifier, check it against the value it expected, match, and carry
	// on.  That is issue #350.
	//
	// With ExactIntegers true a JSON number whose literal text is written as
	// an integer -- no '.', no exponent -- decodes to a lisp int holding its
	// exact value, and one that does not fit in a lisp int is an ERROR
	// (condition json:integer-range-error) rather than a rounded float.
	// Numbers written with a fraction or an exponent are untouched and still
	// decode as floats.
	//
	// The rule is SYNTACTIC on purpose.  "1e2" denotes an integer but is not
	// written as one, and it keeps decoding to a float; so does "-0", which
	// parses to the integer 0 and would therefore re-encode as "0" rather
	// than the "-0" it produces today.  A rule that depends only on the bytes
	// of the document, and never on the value they denote, is reproducible on
	// every node that reads the same bytes -- which is the property that
	// matters where this package decodes replicated state.
	ExactIntegers bool

	// Typed selects the strict typed decoder, independent of package defaults.
	// StringNumbers is incompatible; ExactIntegers is allowed and redundant.
	Typed bool
	// Strict accepts only the plain encoder's key order, escapes and number text.
	Strict bool
}

LoadOpts controls how a JSON document is decoded into lisp values.

The zero value reproduces Load(b, false) exactly -- the behaviour every caller of this package has had since 2018. Every field is an opt-in.

type NativeCodec added in v1.75.0

type NativeCodec interface {
	// SaveNative returns the payload for v, a native value of the
	// registered Go type.  The payload is any value DumpDurable can write,
	// natives and named functions included.  DumpDurable calls SaveNative
	// once per native object in one dump.
	SaveNative(env *lisp.LEnv, v *lisp.LVal) (*lisp.LVal, error)
	// LoadNative rebuilds a native value from a payload that SaveNative
	// returned at version (1 to the registered version).  The result must
	// be a native value of the registered Go type.  The payload is fully
	// restored: it holds no object that is still being loaded.
	LoadNative(env *lisp.LEnv, version int, payload *lisp.LVal) (*lisp.LVal, error)
}

NativeCodec saves and restores the native values of one Go type in durable typed JSON. Register it with RegisterNative or DurableRegistry.Register.

A codec must follow this contract, because peers that save or restore one value must agree byte for byte:

  • Deterministic: the result depends only on the arguments. No clock, random source, Go map iteration order or pointer value.
  • No transaction context: no ledger read or write, no logging that a result depends on, and no context value that the arguments do not carry. Everything a codec needs is in the native or the payload.
  • No caching that changes a result: LoadNative returns a new native on every call. A zero-size pointer payload can share an address with another, so give a pointer type a field.
  • Graph identity: a codec keeps the identity of its payload or refuses sharing. By default elps refuses a payload that holds a shared object; a codec whose SaveNative returns the exact payload values LoadNative received registers with WithSharedPayload.
  • Charged: the declared charge (WithNativeCharge) is taken before each call. Work that grows with the input beyond it is charged by the codec through env.ChargeSteps, and a failed charge is returned as the error.
  • Versioned: LoadNative reads every version from 1 to the registered one. Change the payload shape only with a new version.

type NativeFuncs added in v1.75.0

type NativeFuncs struct {
	Save func(env *lisp.LEnv, v *lisp.LVal) (*lisp.LVal, error)
	Load func(env *lisp.LEnv, version int, payload *lisp.LVal) (*lisp.LVal, error)
}

NativeFuncs is a NativeCodec built from two functions.

func (NativeFuncs) LoadNative added in v1.75.0

func (f NativeFuncs) LoadNative(env *lisp.LEnv, version int, payload *lisp.LVal) (*lisp.LVal, error)

LoadNative calls f.Load.

func (NativeFuncs) SaveNative added in v1.75.0

func (f NativeFuncs) SaveNative(env *lisp.LEnv, v *lisp.LVal) (*lisp.LVal, error)

SaveNative calls f.Save.

type NativeOption added in v1.75.0

type NativeOption func(*nativeEntry)

NativeOption configures one registration.

func WithNativeCharge added in v1.75.0

func WithNativeCharge(units int) NativeOption

WithNativeCharge declares the units charged before each SaveNative and LoadNative call of the codec, through the WithTypedCharge function of the dump or load (default 0). Use it for a codec's fixed cost, such as reopening a B+-tree.

func WithSharedPayload added in v1.75.0

func WithSharedPayload() NativeOption

WithSharedPayload declares that the codec keeps the identity of its payload: SaveNative returns the same payload values LoadNative was given (for example a native that holds its payload and returns it). Only such a codec may have a payload that shares an object with the rest of the graph, or within itself. Without this option, DumpDurable and LoadDurable refuse a payload that holds a shared object, because the codec would drop the sharing on the next save.

type Serializer

type Serializer struct {
	True  *lisp.LVal
	False *lisp.LVal
	Null  *lisp.LVal
	// UseStringNumbers is the initial default for LoadOpts.StringNumbers used
	// by the package builtins when the caller passes no :string-numbers
	// keyword.  json:use-string-numbers does NOT write this field: the Lisp
	// mode lives in the environment's json package (see modeState), so a
	// template-forked VM owns its own copy.  This field is the fallback an
	// environment reads until Lisp code sets the mode.
	UseStringNumbers bool
	// UseExactIntegers is the initial default for LoadOpts.ExactIntegers used by the
	// package builtins when the caller passes no :exact-integers keyword.  It
	// does NOT affect Load or LoadMax, which take their options as arguments.
	UseExactIntegers bool
}

Serializer defines JSON serialization rules for lisp values.

func DefaultSerializer

func DefaultSerializer() *Serializer

func (*Serializer) Dump

func (s *Serializer) Dump(v *lisp.LVal, stringNums bool) ([]byte, error)

Dump serializes v as JSON and returns any error.

func (*Serializer) DumpBytesBuiltin

func (s *Serializer) DumpBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) DumpMessageBuiltin

func (s *Serializer) DumpMessageBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) DumpStringBuiltin

func (s *Serializer) DumpStringBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) DumpWith added in v1.74.0

func (s *Serializer) DumpWith(v *lisp.LVal, opts DumpOpts) ([]byte, error)

DumpWith encodes v under opts, using the serializer's plain rules when neither Canonize nor Typed is set.

func (*Serializer) GoError deprecated

func (s *Serializer) GoError(v *lisp.LVal) error

GoError returns an error that represents v. If v is not LError then nil is returned.

Deprecated: GoError is no longer used internally for serialization and should be avoided.

func (*Serializer) GoFloat64 deprecated

func (s *Serializer) GoFloat64(v *lisp.LVal) (float64, bool)

GoFloat64 converts the numeric value that v represents to a float64 and returns it with the value true. If v does not represent a number GoFloat64 returns a false second argument

Deprecated: GoFloat64 is no longer used internally for serialization and should be avoided.

func (*Serializer) GoInt deprecated

func (s *Serializer) GoInt(v *lisp.LVal) (int, bool)

GoInt converts the numeric value that v represents to and int and returns it with the value true. If v does not represent a number GoInt returns a false second argument

Deprecated: GoInt is no longer used internally for serialization and should be avoided.

func (*Serializer) GoMap deprecated

func (s *Serializer) GoMap(v *lisp.LVal, stringNums bool) (map[string]any, bool)

GoMap converts an LSortMap to its Go equivalent and returns it with a true second argument. If v does not represent a map json serializable map GoMap returns a false second argument. Excessive nesting returns (nil, false).

Deprecated: GoMap is no longer used internally for serialization and should be avoided.

func (*Serializer) GoSlice deprecated

func (s *Serializer) GoSlice(v *lisp.LVal, stringNums bool) ([]any, bool)

GoSlice converts a list to a Go slice. Non-lists or walks exceeding lisp.MaxValueDepth return (nil, false).

Deprecated: GoSlice is no longer used internally for serialization and should be avoided.

func (*Serializer) GoString deprecated

func (s *Serializer) GoString(v *lisp.LVal) (string, bool)

GoString returns the string that v represents and the value true. If v does not represent a string GoString returns a false second argument

Deprecated: GoString is no longer used internally for serialization and should be avoided.

func (*Serializer) GoValue deprecated

func (s *Serializer) GoValue(v *lisp.LVal, stringNums bool) any

GoValue converts v to its natural representation in Go. Quotes are ignored and all lists are turned into slices. Symbols are converted to strings. The value Nil() is converted to nil. Functions are returned as is.

SHARING. The result MAY share Go containers where v shared them, as lisp.GoValue's may: a list or map reached along several paths of v can come back as one []any or map[string]any appearing at each of those places, rather than one copy per path. That is how a value with nested sharing -- (set! x (list x x)) repeated D times, 2^D paths -- converts in time and memory linear in its distinct containers (see lisp/sharing.go); whether a given shared container is shared in the result depends on how much of the value was converted before it, and on its size. A value without sharing converts to distinct Go containers throughout. Treat a result as read-only, or deep-copy it before writing to it. GoSlice and GoMap follow the same rule.

Deprecated: GoValue is no longer used internally for serialization and should be avoided. Excessive nesting (including cycles) returns an ordinary *lisp.ErrorVal implementing error, using lisp.MaxValueDepth.

func (*Serializer) Load

func (s *Serializer) Load(b []byte, stringNums bool) *lisp.LVal

Load parses b and returns an LVal representing its structure.

func (*Serializer) LoadBytesBuiltin

func (s *Serializer) LoadBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) LoadMax added in v1.20.0

func (s *Serializer) LoadMax(b []byte, stringNums bool, maxAlloc int) *lisp.LVal

LoadMax is like Load but enforces a maximum allocation size for arrays and maps parsed from JSON. When maxAlloc is 0, no limit is enforced.

func (*Serializer) LoadMessageBuiltin

func (s *Serializer) LoadMessageBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) LoadStringBuiltin

func (s *Serializer) LoadStringBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) LoadWith added in v1.50.0

func (s *Serializer) LoadWith(b []byte, opts LoadOpts) *lisp.LVal

LoadWith parses b under opts and returns an LVal representing its structure.

func (*Serializer) MessageBytesBuiltin

func (s *Serializer) MessageBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) StringNumbersBuiltin added in v1.63.0

func (s *Serializer) StringNumbersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

StringNumbersBuiltin reports the serializer's default string-numbers mode.

func (*Serializer) SymbolName deprecated

func (s *Serializer) SymbolName(v *lisp.LVal) (string, bool)

SymbolName returns the name of the symbol that v represents and the value true. If v does not represent a symbol SymbolName returns a false second argument

Deprecated: SymbolName is no longer used internally for serialization and should be avoided.

func (*Serializer) UseExactIntegersBuiltin added in v1.50.0

func (s *Serializer) UseExactIntegersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

func (*Serializer) UseStringNumbersBuiltin

func (s *Serializer) UseStringNumbersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

type TypedOption added in v1.74.0

type TypedOption func(*typedConfig)

TypedOption configures DumpTyped, LoadTyped and Canonize.

func WithTypedCharge added in v1.74.0

func WithTypedCharge(charge func(kib int) error) TypedOption

WithTypedCharge makes DumpTyped call charge as its output grows, with the number of KiB newly started since the last call, so a caller can meter the work (a step budget, a context) while it happens. The units add up to ceil(n/1024) for n output bytes, the same as lisp.ChargeStartedKiB, and depend only on the output. A non-nil error stops the encode and is returned wrapped. LoadTyped ignores it: a decode can charge for its whole input before it starts. Canonize uses the same charge on its counted output size during the value walk, without building JSON bytes.

func WithTypedMaxBytes added in v1.74.0

func WithTypedMaxBytes(n int) TypedOption

WithTypedMaxBytes limits the encoded size: the output of DumpTyped and the input of LoadTyped (default DefaultTypedMaxBytes).

func WithTypedMaxDepth added in v1.74.0

func WithTypedMaxDepth(n int) TypedOption

WithTypedMaxDepth limits container nesting (default DefaultTypedMaxDepth).

func WithTypedMaxValues added in v1.74.0

func WithTypedMaxValues(n int) TypedOption

WithTypedMaxValues limits the number of values written or read, counting every element, map key, array dimension and nested value (default DefaultTypedMaxValues).

Jump to

Keyboard shortcuts

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