llsd

package module
v0.0.0-...-bbf5ef4 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2022 License: MIT Imports: 17 Imported by: 0

README

go-llsd

LLSD encoder/decoder for Go.

Example use

go-llsd exposes an interface similar to Go's json/xml stdlib. Annotate struct fields with a llsd tag to customize property names.

Basic unmarshaling:

type data struct {
    FieldA string `llsd:"field_a"`
}

const xml = `<?xml version="1.0" encoding="UTF-8"?>
<llsd>
    <map>
      <key>field_a</key><string>Hello, world</string>
    </map>
</llsd>`

var d data
if err := llsd.UnmarshalXML(&d); err != nil {
    panic(err)
}
println(data.FieldA)

Basic marshaling:

type data struct {
    FieldA string `llsd:"field_a"`
}
d := data{FieldA: "Hello, world"}

xml, err := llsd.MarshalXML(&d)
if err != nil {
    panic(err)
}
println(string(xml))

Full example:

package main

import (
    "fmt"

    "github.com/bennettgoble/go-llsd"
)

type StatsResponse struct {
    RegionID llsd.UUID `llsd:"region_id"`
    Scale    string    `llsd:"scale"`
    Stats    struct {
        TimeDilation float64 `llsd:"time dilation"`
        SimFPS       float64 `llsd:"sim fps"`
        PhysicsFPS   float64 `llsd:"physics fps"`
    } `llsd:"simulator statistics"`
}

func main() {
    const xml = `<?xml version="1.0" encoding="UTF-8"?>
    <llsd>
    <map>
        <key>region_id</key><uuid>67153d5b-3659-afb4-8510-adda2c034649</uuid>
        <key>scale</key><string>one minute</string>
        <key>simulator statistics</key>
        <map>
          <key>time dilation</key><real>0.9878624</real>
          <key>sim fps</key><real>44.9000000</real>
          <key>physics fps</key><real>45.0000000</real>
        </map>
    </map>
    </llsd>`

    var res StatsResponse
    if err := llsd.UnmarshalXML([]byte(xml), &res); err != nil {
        panic(err)
    }
    println(fmt.Sprintf("Sim FPS: %f", res.Stats.SimFPS))
}
Field tags

Examples of llsd struct field tags and their meanings:

// Field appears in LLSD with key "my_name"
Field int `llsd:"my_name"`

// Field appears in LLSD with key "my_name" and is omitted
// from the object if it has zero-value
Field int `llsd:"my_name,omitempty"`

// Field is omitted from object if it has zero-value
Field int `llsd:",omitempty"`

// Field is ignored
Field int `llsd:"-"`

// Field appears in LLSD with key "-"
Field int `llsd:"-,"`

// Field appears in LLSD with key "my_name" and uses
// base64 text representation 
Field []byte `llsd:"my_name,base64"`

// Field uses base64 text representation 
Field []byte `llsd:",base64"`

// Field uses base85 text representation (Don't do this, it's gross)
Field []byte `llsd:",base85"`

As a convenience, go-llsd will attempt to use json tags if llsd is not specified.

Custom marshaling/unmarshaling

You may define custom marshaling/unmarshaling behavior for scalar types by implementing the appropriate Unmarshaler/Marshaler interface.

// TextUnmarshaler is the interface implemented by types that want to
// customize how text (xml, notation) LLSD values are unmarshaled into
// themselves.
type TextUnmarshaler interface {
	UnmarshalTextLLSD([]byte) error
}

// TextMarshaler is the interface implemented by types that want to
// customize how text (xml, notation) LLSD values are marshaled into
// text.
type TextMarshaler interface {
	MarshalTextLLSD() (llsd.ScalarType, string, error)
}

For example, to define a type that parses CSV values from LLSD string:

type csv []string

func (c *csv) UnmarshalTextLLSD(b []byte) error {
	v := strings.Split(string(b), ",")
	*c = append(*c, v...)
	return nil
}

func (c *csv) MarshalTextLLSD() (llsd.ScalarType, string, error) {
    return llsd.String, strings.Join(*c, ","), nil
}
Binary support

Binary LLSD can be parsed using methods similar to XML:

var dst MyType

err := llsd.UnmarshalBinary(data, &dst)
if err != nil {
    panic(err)
}
Notes on behavior
  • Using fixed-length arrays causes extra values to be ignored
  • nullptr is serialized as undef

Documentation

Index

Constants

View Source
const (
	Base16 = "base16"
	Base64 = "base64"
	Base85 = "base85"
)
View Source
const BinaryHeader = "<?llsd/binary?>\n"

Variables

This section is empty.

Functions

func MarshalXML

func MarshalXML(v any) ([]byte, error)

func MarshalXMLIndent

func MarshalXMLIndent(v any, indent string) ([]byte, error)

func UnmarshalBinary

func UnmarshalBinary(data []byte, v any) error

UnmarshalBinary attempts to deserialize given LLSD binary data into a given value.

func UnmarshalXML

func UnmarshalXML(data []byte, v any) error

UnmarshalXML attempts to deserialize given LLSD XML data into a given value.

Types

type ArrayEnd

type ArrayEnd struct{}

type ArrayStart

type ArrayStart struct{}

type BinaryMarshaler

type BinaryMarshaler interface {
	MarshalBinaryLLSD() (ScalarType, []byte, error)
}

TextMarshaler is the interface implemented by types that want to customize how text (xml, notation) LLSD values are marshaled into text.

type BinaryScanner

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

func NewBinaryScanner

func NewBinaryScanner(r io.Reader) *BinaryScanner

func (*BinaryScanner) Offset

func (s *BinaryScanner) Offset() int64

func (*BinaryScanner) Token

func (s *BinaryScanner) Token() (Token, error)

type BinaryUnmarshaler

type BinaryUnmarshaler interface {
	UnmarshalBinaryLLSD([]byte) error
}

BinaryUnmarshaler is the interface implemented by types that want to customize how binary LLSD values are unmarshaled into themselves.

type InvalidLLSDError

type InvalidLLSDError struct {
	Problem string
	Offset  int64
}

InvalidLLSDError represents a problem with input LLSD.

func (*InvalidLLSDError) Error

func (e *InvalidLLSDError) Error() string

type Key

type Key string

type MapEnd

type MapEnd struct{}

type MapStart

type MapStart struct{}

type MarshalTypeError

type MarshalTypeError struct {
	Type reflect.Type
}

MarshalTypeError represents an error in the marshaling process.

func (*MarshalTypeError) Error

func (e *MarshalTypeError) Error() string

type Scalar

type Scalar struct {
	Type ScalarType
	Data []byte
	Attr map[string]string
}

type ScalarType

type ScalarType int
const (
	Undefined ScalarType = iota
	Boolean
	Integer
	Real
	UUIDType
	String
	Binary
	Date
	URI
)

func (ScalarType) String

func (t ScalarType) String() string

type TextMarshaler

type TextMarshaler interface {
	MarshalTextLLSD() (ScalarType, string, error)
}

TextMarshaler is the interface implemented by types that want to customize how text (xml, notation) LLSD values are marshaled into text.

type TextUnmarshaler

type TextUnmarshaler interface {
	UnmarshalTextLLSD([]byte) error
}

TextUnmarshaler is the interface implemented by types that want to customize how text (xml, notation) LLSD values are unmarshaled into themselves.

type Token

type Token any

type TokenReader

type TokenReader interface {
	Token() (Token, error) // Get next LLSD token
	Offset() int64         // Input stream offset
}

type URL

type URL string

type UUID

type UUID [16]byte

func (UUID) String

func (u UUID) String() string

type UnmarshalTypeError

type UnmarshalTypeError struct {
	Value  string       // Description of LLSD value - "real", "map", "string"
	Type   reflect.Type // Type of Go value that could not be assigned to
	Offset int64        // Input stream byte offset where error occurred
}

UnmarshalTypeError represents an error in the unmarshaling process.

func (*UnmarshalTypeError) Error

func (e *UnmarshalTypeError) Error() string

type Unmarshaler

type Unmarshaler struct {
	DisallowUnknownFields bool
	// contains filtered or unexported fields
}

Decoder is a generic LLSD unmarshaler that can work with any TokenReader.

func NewBinaryDecoder

func NewBinaryDecoder(r io.Reader) *Unmarshaler

NewBinaryDecoder creates a new instance of an Unmarshaler configured to read binary LLSD.

func NewXMLDecoder

func NewXMLDecoder(r io.Reader) *Unmarshaler

NewXMLDecoder creates a new instance of an Unmarshaler configured to read LLSD XML.

func (*Unmarshaler) Unmarshal

func (u *Unmarshaler) Unmarshal(v any) error

Unmarshal decodes LLSD into a given value.

type XMLEncoder

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

func NewXMLEncoder

func NewXMLEncoder(w io.Writer) *XMLEncoder

func (*XMLEncoder) Encode

func (e *XMLEncoder) Encode(v any) error

func (*XMLEncoder) Flush

func (e *XMLEncoder) Flush()

Flush flushes any buffered XML to the underlying writer

func (*XMLEncoder) SetIndent

func (e *XMLEncoder) SetIndent(indent string)

type XMLScanner

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

func NewXMLScanner

func NewXMLScanner(r io.Reader) *XMLScanner

func (*XMLScanner) Offset

func (s *XMLScanner) Offset() int64

InputOffset returns the input stream byte offset of the current decoder position.

func (*XMLScanner) Skip

func (s *XMLScanner) Skip() error

Skip element, useful for jumping over large maps and arrays.

func (*XMLScanner) Token

func (s *XMLScanner) Token() (Token, error)

Jump to

Keyboard shortcuts

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