Documentation
¶
Index ¶
- Constants
- Variables
- func Builtins(s *Serializer) []*libutil.Builtin
- func Canonize(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)
- func CanonizeBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func Dump(v *lisp.LVal, stringNums bool) ([]byte, error)
- func DumpDurable(env *lisp.LEnv, v *lisp.LVal, reg *DurableRegistry, opts ...TypedOption) ([]byte, error)
- func DumpDurableRoots(env *lisp.LEnv, roots []DurableRoot, reg *DurableRegistry, opts ...TypedOption) ([]byte, error)
- func DumpTyped(v *lisp.LVal, opts ...TypedOption) ([]byte, error)
- func DumpTypedBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func DumpWith(v *lisp.LVal, opts DumpOpts) ([]byte, error)
- func Load(b []byte, stringNums bool) *lisp.LVal
- func LoadDurable(env *lisp.LEnv, b []byte, reg *DurableRegistry, opts ...TypedOption) (*lisp.LVal, error)
- func LoadPackage(env *lisp.LEnv) *lisp.LVal
- func LoadTyped(b []byte, opts ...TypedOption) (*lisp.LVal, error)
- func LoadTypedBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func LoadWith(b []byte, opts LoadOpts) *lisp.LVal
- func RegisterNative[T any](r *DurableRegistry, name string, version int, c NativeCodec, ...) error
- func Tag(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)
- func TagBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func Untag(v *lisp.LVal, opts ...TypedOption) (*lisp.LVal, error)
- func UntagBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- type DumpOpts
- type DurableRegistry
- type DurableRoot
- type LoadOpts
- type NativeCodec
- type NativeFuncs
- type NativeOption
- type Serializer
- func (s *Serializer) Dump(v *lisp.LVal, stringNums bool) ([]byte, error)
- func (s *Serializer) DumpBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) DumpMessageBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) DumpStringBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) DumpWith(v *lisp.LVal, opts DumpOpts) ([]byte, error)
- func (s *Serializer) GoError(v *lisp.LVal) errordeprecated
- func (s *Serializer) GoFloat64(v *lisp.LVal) (float64, bool)deprecated
- func (s *Serializer) GoInt(v *lisp.LVal) (int, bool)deprecated
- func (s *Serializer) GoMap(v *lisp.LVal, stringNums bool) (map[string]any, bool)deprecated
- func (s *Serializer) GoSlice(v *lisp.LVal, stringNums bool) ([]any, bool)deprecated
- func (s *Serializer) GoString(v *lisp.LVal) (string, bool)deprecated
- func (s *Serializer) GoValue(v *lisp.LVal, stringNums bool) anydeprecated
- func (s *Serializer) Load(b []byte, stringNums bool) *lisp.LVal
- func (s *Serializer) LoadBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) LoadMax(b []byte, stringNums bool, maxAlloc int) *lisp.LVal
- func (s *Serializer) LoadMessageBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) LoadStringBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) LoadWith(b []byte, opts LoadOpts) *lisp.LVal
- func (s *Serializer) MessageBytesBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) StringNumbersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) SymbolName(v *lisp.LVal) (string, bool)deprecated
- func (s *Serializer) UseExactIntegersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- func (s *Serializer) UseStringNumbersBuiltin(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal
- type TypedOption
Examples ¶
Constants ¶
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.
const DefaultPackageName = "json"
DefaultPackageName is the package name used by LoadPackage.
const DurableFormatVersion = 1
DurableFormatVersion is the format version every durable document starts with. It is frozen: LoadDurable rejects any other version.
Variables ¶
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
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
CanonizeBuiltin implements json:canonize and propagates runtime budget conditions unchanged, while charging each started KiB during the walk.
func Dump ¶
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
DumpTypedBuiltin is the runtime adapter for typed dumping across the JSON family.
func DumpWith ¶ added in v1.74.0
DumpWith encodes v under opts without changing the existing Dump API.
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 ¶
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
LoadTypedBuiltin is the runtime adapter for typed loading across the JSON family.
func LoadWith ¶ added in v1.50.0
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
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
TagBuiltin returns a plain JSON value with type tags.
Types ¶
type DumpOpts ¶ added in v1.74.0
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
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
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) DumpBytesBuiltin ¶
func (*Serializer) DumpMessageBuiltin ¶
func (*Serializer) DumpStringBuiltin ¶
func (*Serializer) DumpWith ¶ added in v1.74.0
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
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 (*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 (*Serializer) LoadMax ¶ added in v1.20.0
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 (*Serializer) LoadStringBuiltin ¶
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 (*Serializer) StringNumbersBuiltin ¶ added in v1.63.0
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 (*Serializer) UseStringNumbersBuiltin ¶
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).