lcs

package module
v0.0.0-...-0fa8432 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 2022 License: Apache-2.0 Imports: 10 Imported by: 8

README

lcs

Build Status codecov Go Report Card Codacy Badge

Go library for Libra canonical serialization (and deserialization). See LCS Spec.

For types defined and used in actual Libra blockchain, please visit go-libra: Libra client library with crypto verifications.

Supported Custom Marshal & Unmarshal.

Installation

$ go get -u github.com/coming-chat/lcs

Usage

import "github.com/coming-chat/lcs"

See example_test.go for complete examples.

Basic types

You can serialize and deserialize the following basic types:

  • bool
  • int8, int16, int32, int64, uint8, uint16, uint32, uint64
  • string
  • slice, map
bytes, _ := lcs.Marshal("hello")

fmt.Printf("%x\n", bytes)
// Output: 050000068656c6c6f
myInt := int16(0)
lcs.Unmarshal([]byte{0x05, 0x00}, &myInt) // <- be careful to pass a pointer

fmt.Printf("%d\n", myInt)
// Output: 5
Struct types

Simple struct can be serialized or deserialized directly. You can use struct field tags to change lcs behaviors.

type MyStruct struct {
    Boolean    bool
    Bytes      []byte
    Label      string `lcs:"-"` // "-" tagged field is ignored
    unexported uint32           // unexported field is ignored
}

// Serialize:
bytes, err := lcs.Marshal(&MyStruct{})

// Deserialize:
out := &MyStruct{}
err = lcs.Unmarshal(bytes, out)
Struct with optional fields

Optional fields should be pointers, slices or maps with "optional" tag.

type MyStruct struct {
    Label  *string          `lcs:"optional"`
    Nested *MyStruct        `lcs:"optional"`
    Slice  []byte           `lcs:"optional"`
    Map    map[uint8]uint8  `lcs:"optional"`
}
Fixed length lists

Arrays are treated as fixed length lists.

You can also specify fixed length for struct members with len tag. Slices and strings are supported.

type MyStruct struct {
	Str           string `lcs:"len=2"`
	Bytes         []byte `lcs:"len=4"`
	OptionalBytes []byte `lcs:"len=4,optional"`
}
Enum types

Enum types are golang interfaces.

(The old enum API is deprecated.)

// Enum1 is an enum type.
type Enum1 interface {
//	isEnum1()	// optional: member functions
}

// *Enum1Opt0, Enum1Opt1, Enum1Opt2 are variants of Enum1
type Enum1Opt0 struct {
	Data uint32
}
type Enum1Opt1 struct{} // Use empty struct for a variant without contents.
type Enum1Opt2 []Enum1	// self reference is OK

// Register Enum1 with LCS. Will be available globaly.
var _ = lcs.RegisterEnum(
	// nil pointer to the enum interface type:
	(*Enum1)(nil),
	// zero-values of each variants
	(*Enum1Opt0)(nil), 	// Use pointer for non-empty struct.
	Enum1Opt1{},
	Enum1Opt2(nil),
)

// Usage: Marshal the enum alone, must use pointer
e1 := Enum1(Enum1Opt1{})
bytes, err := lcs.Marshal(&e1)

// Use Enum1 within other structs
type Wrapper struct {
	Enum Enum1
}
bytes, err := lcs.Marshal(&Wrapper{
	Enum: Enum1Opt0{10},
})

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(v interface{}) ([]byte, error)
Example (Libra_program)
package main

import (
	"fmt"

	"github.com/coming-chat/lcs"
)

type TransactionArgument interface{}

type Program struct {
	Code    []byte
	Args    []TransactionArgument
	Modules [][]byte
}

func main() {
	prog := &Program{
		Code: []byte("move"),
		Args: []TransactionArgument{
			"CAFE D00D",
			"cafe d00d",
		},
		Modules: [][]byte{{0xca}, {0xfe, 0xd0}, {0x0d}},
	}

	bytes, err := lcs.Marshal(prog)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%X\n", bytes)
}
Output:

046D6F766502020943414645204430304402096361666520643030640301CA02FED0010D
Example (Struct)
package main

import (
	"fmt"

	"github.com/coming-chat/lcs"
)

func main() {
	type MyStruct struct {
		Boolean    bool
		Bytes      []byte
		Label      string
		unexported uint32
	}
	type Wrapper struct {
		Inner *MyStruct `lcs:"optional"`
		Name  string
	}

	bytes, err := lcs.Marshal(&Wrapper{
		Name: "test",
		Inner: &MyStruct{
			Bytes: []byte{0x01, 0x02, 0x03, 0x04},
			Label: "hello",
		},
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf("%x", bytes)
}
Output:

010004010203040568656c6c6f0474657374

func RegisterEnum

func RegisterEnum(enumTypePtr interface{}, types ...interface{}) (err error)

RegisterEnum register an enum type with its available variants. If the enum type was registered, it will be overwriten.

This function panics on errors. The returned error is always nil.

func Unmarshal

func Unmarshal(data []byte, v interface{}) error
Example (Libra_program)
package main

import (
	"encoding/hex"
	"fmt"

	"github.com/coming-chat/lcs"
)

type TransactionArgument interface{}

type Program struct {
	Code    []byte
	Args    []TransactionArgument
	Modules [][]byte
}

func main() {
	bytes, _ := hex.DecodeString("046D6F766502020943414645204430304402096361666520643030640301CA02FED0010D")
	out := &Program{}
	err := lcs.Unmarshal(bytes, out)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", out)
}
Output:

&{Code:[109 111 118 101] Args:[CAFE D00D cafe d00d] Modules:[[202] [254 208] [13]]}
Example (Struct)
package main

import (
	"encoding/hex"
	"fmt"

	"github.com/coming-chat/lcs"
)

func main() {
	type MyStruct struct {
		Boolean    bool
		Bytes      []byte
		Label      string
		unexported uint32
	}
	type Wrapper struct {
		Inner *MyStruct `lcs:"optional"`
		Name  string
	}

	bytes, _ := hex.DecodeString("010004010203040568656c6c6f0474657374")
	out := &Wrapper{}
	err := lcs.Unmarshal(bytes, out)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Name: %s, Label: %s\n", out.Name, out.Inner.Label)
}
Output:

Name: test, Label: hello

Types

type Decoder

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

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}) error

func (*Decoder) DecodeBytes

func (d *Decoder) DecodeBytes() ([]byte, error)

func (*Decoder) DecodeFixedBytes

func (d *Decoder) DecodeFixedBytes(length int) ([]byte, error)

func (*Decoder) DecodeUleb128

func (d *Decoder) DecodeUleb128() (uint64, error)

func (*Decoder) EOF

func (d *Decoder) EOF() bool

type Encoder

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

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{}) error

func (*Encoder) EncodeBytes

func (e *Encoder) EncodeBytes(b []byte) error

func (*Encoder) EncodeFixedBytes

func (e *Encoder) EncodeFixedBytes(b []byte) (err error)

@params b must be a byte array of limited length. [N]byte

func (*Encoder) EncodeUleb128

func (e *Encoder) EncodeUleb128(u uint64) error

type EnumKeyType

type EnumKeyType = uint64

type EnumTypeUser

type EnumTypeUser interface {
	// EnumTypes return the ingredients used for all enum types in the struct.
	EnumTypes() []EnumVariant
}

EnumTypeUser is an interface of struct with enum type definition. Struct with enum type should implement this interface.

type EnumVariant

type EnumVariant struct {
	// Name of the enum type. Different variants of a same enum type should have same name.
	// This name should match the name defined in the struct field tag.
	Name string

	// Value is the numeric value of the enum variant. Should be unique within the same enum type.
	Value EnumKeyType

	// Template object for the enum variant. Should be the zero value of the variant type.
	//
	// Example values: (*SomeStruct)(nil), MyUint32(0).
	Template interface{}
}

EnumVariant is a definition of a variant of enum type.

type Marshaler

type Marshaler interface {
	MarshalLCS(e *Encoder) error
}

Marshaler is the interface implemented by types that can marshal themselves into valid LCS.

type Unmarshaler

type Unmarshaler interface {
	UnmarshalLCS(d *Decoder) error
}

Jump to

Keyboard shortcuts

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