surge

package module
v1.2.8 Latest Latest
Warning

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

Go to latest
Published: Dec 11, 2021 License: MIT Imports: 7 Imported by: 5

README

🔌 surge

GitHub Coverage Report

Documentation

A library for fast binary (un)marshaling. Designed to be used in Byzantine networks, 🔌 surge never explicitly panics, protects against malicious inputs, allocates minimally, and has very few dependencies (its only dependency is the ginkgo testing framework). It supports the (un)marshaling of:

  • scalars,
  • arrays,
  • slices,
  • maps,
  • structs, and
  • custom implementations (using the Marshaler and Unmarshaler interfaces).

Built-in Types

All built-in types that can be marshaled are supported by surge. And, for the vast majority of use cases, ToBinary and FromBinary are the only functions that you will need to use:

Scalars
// Marshal
x := uint64(42)
data, err := surge.ToBinary(x)
if err != nil {
    panic(err)
}

// Unmarshal
y := uint64(0)
if err := surge.FromBinary(&y, data); err != nil {
    panic(err)
}
Arrays

Arrays are collections of a known, fixed, length. Arrays are not length prefixed, because their length is part of their type. All arrays marshal their elements one-by-one, with the exception of byte arrays (which are marshaled in bulk using copy):

// Marshal
x := [4]uint64{42, 43, 44, 45}
data, err := surge.ToBinary(x)
if err != nil {
    panic(err)
}

// Unmarshal
y := [4]uint64{}
if err := surge.FromBinary(&y, data); err != nil {
    panic(err)
}
Slices

Slices are collections of variable length. Slices are length prefixed, because their length is not known at compile-time. All slices marshal their elements one-by-one, with the exception of byte slices (which are marshaled in bulk using copy):

// Marshal
x := []uint64{42, 43, 44, 45}
data, err := surge.ToBinary(x)
if err != nil {
    panic(err)
}

// Unmarshal
y := []uint64{}
if err := surge.FromBinary(&y, data); err != nil {
    panic(err)
}
Maps

Maps are effectively slices of key/value pairs. Maps are length prefixed, because their length is not known at compile-time. Maps are marshaled as a sorted slice of (key, value) tuples, sorted lexographically by keys (after the key has been marshaled, because not all key types are directly comparable). Sorting is done because it guarantees that the binary output is always the same when the key/value pairs are the same (this is particularly useful when hashing/signing maps for authenticity):

// Marshal
x := map[string]uint64{"foo": 42, "bar": 43, "baz": 44}
data, err := surge.ToBinary(x)
if err != nil {
    panic(err)
}

// Unmarshal
y := map[string]uint64{}
if err := surge.FromBinary(&y, data); err != nil {
    panic(err)
}

User-defined types

The same pattern that we have seen above works for custom structs too. You will not need to make any changes to your struct, as long as all of its fields are marshalable by surge:

type MyStruct struct {
    Foo int64
    Bar float64
    Baz MyInnerStruct
}

type MyInnerStruct struct {
    Inner1 []bool
    Inner2 []string
}

// Marshal
x := MyStruct{
    Foo: int64(43),
    Bar: float64(3.14),
    Baz: MyInnerStruct{
        Inner1: []bool{true, false},
        Inner2: []string{"hello", "world"},
    },
}
data, err := surge.ToBinary(x)
if err != nil {
    panic(err)
}

// Unmarshal
y := MyStruct{}
if err := surge.FromBinary(&y, data); err != nil {
    panic(err)
}
Specialisation

Using the default marshaler built into surge is great for prototyping, and will good enough for many applications. But, sometimes we need to specialise our marshaling. Providing our own implementation will not only be faster, but it will also give us the ability to customise the marshaler (which can be necessary when thinking about backward compatibility, etc.):

type MyStruct struct {
  Foo int64
  Bar float64
  Baz string
}

// SizeHint tells surge how many bytes our
// custom type needs when being represented
// in its binary form.
func (myStruct MyStruct) SizeHint() int {
    return surge.SizeHintI64 +
           surge.SizeHintF64 +
           surge.SizeHintString(myStruct.Baz)
}

// Marshal tells surge exactly how to marshal
// our custom type. As you can see, most implementations
// will be very straight forward, and mostly exist
// for performance reasons. In the future, surge might
// adopt some kind of generator to automatically
// generate these implementations.
func (myStruct MyStruct) Marshal(buf []byte, rem int) ([]byte, int, error) {
    var err error
    if buf, rem, err = surge.MarshalI64(myStruct.Foo, buf, rem); err != nil {
        return buf, rem, err
    }
    if buf, rem, err = surge.MarshalF64(myStruct.Bar, buf, rem); err != nil {
        return buf, rem, err
    }
    if buf, rem, err = surge.MarshalString(myStruct.Baz, buf, rem); err != nil {
        return buf, rem, err
    }
    return buf, rem, err
}

// Unmarshal is the opposite of Marshal, and requires
// a pointer receiver.
func (myStruct *MyStruct) Unmarshal(buf []byte, rem int) ([]byte, int, error) {
    var err error
    if buf, rem, err = surge.UnmarshalI64(&myStruct.Foo, buf, rem); err != nil {
        return buf, rem, err
    }
    if buf, rem, err = surge.UnmarshalF64(&myStruct.Bar, buf, rem); err != nil {
        return buf, rem, err
    }
    if buf, rem, err = surge.UnmarshalString(&myStruct.Baz, buf, rem); err != nil {
        return buf, rem, err
    }
    return buf, rem, err
}
Testing

Testing custom marshaling implementations is incredibly important, but it can also be very tedious, and so it is rarely done as extensively as it should be. Luckily, surge helps us get this done quickly. By using the surgeutil package, we can write comprehensive tests very quickly:

func TestMyStruct(t *testing.T) {
    // Reflect on our custom type
    t := reflect.TypeOf(MyStruct{})
    
    // Fuzz and expect that it does not panic.
    surgeutil.Fuzz(t)
    
    // Marshal, then unmarshal, then check for
    // equality, and expect there to be no
    // errors.
    if err := surgeutil.MarshalUnmarshalCheck(t); err != nil {
        t.Fatalf("bad marshal/unmarshal/check: %v", err)
    }
    
    // Marshal when the buffer is too small
    // and check that it does not work.
    if err := surgeutil.MarshalBufTooSmall(t); err != nil {
        t.Fatalf("bad marshal with insufficient buffer: %v", err)
    }
    
    // Marshal when the remaining memory quota
    // is too small and check that it does not
    // work.
    if err := surgeutil.MarshalRemTooSmall(t); err != nil {
        t.Fatalf("bad marshal with insufficient rem quota: %v", err)
    }
    
    // Unmarshal when the buffer is too small
    // and check that it does not work.
    if err := surgeutil.UnmarshalBufTooSmall(t); err != nil {
        t.Fatalf("bad marshal with insufficient buffer: %v", err)
    }
    
    // Unmarshal when the remaining memory quota
    // is too small and check that it does not
    // work.
    if err := surgeutil.UnmarshalRemTooSmall(t); err != nil {
        t.Fatalf("bad marshal with insufficient rem quota: %v", err)
    }
}

Internally, surgeutil makes use of the quick standard library. So, for surgeutil to work, your type needs to be compatible with quick. This is usually automatic, and most of the time you will not need to think about quick at all. For the more exotic types, that do need custom support, all you need to do is implement the quick.Generator interface. For more examples of surgeutil in use, checkout any of the *_test.go files. All of the testing in surge is done using the surgeutil package.

Benchmarks

When using specialised implementations, surge is about as fast as you can get; it does not really do much under-the-hood. When using the default implementations, the need to use reflect introduces some slow-down, but performance is still faster than most alternatives:

goos: darwin
goarch: amd64
pkg: github.com/muirglacier/surge
BenchmarkPointMarshalJSON-8              2064483               563 ns/op              80 B/op          1 allocs/op
BenchmarkTriangleMarshalJSON-8            583173              1752 ns/op             239 B/op          1 allocs/op
BenchmarkModelMarshalJSON-8                 7018            163255 ns/op           24588 B/op          1 allocs/op
BenchmarkPointMarshal-8                 11212546               109 ns/op               0 B/op          0 allocs/op
BenchmarkTriangleMarshal-8               3700579               294 ns/op               0 B/op          0 allocs/op
BenchmarkModelMarshal-8                    38652             28270 ns/op              32 B/op          1 allocs/op
BenchmarkFoo-8                          33130609                33 ns/op               0 B/op          0 allocs/op

Contributions

Built with ❤ by Ren.

Documentation

Index

Constants

View Source
const (
	// SizeHintF32 is the number of bytes required to represent a float32 value
	// in binary.
	SizeHintF32 = 4
	// SizeHintF64 is the number of bytes required to represent a float64 value
	// in binary.
	SizeHintF64 = 8
)
View Source
const (
	// SizeHintU8 is the number of bytes required to represent a uint8 value in
	// binary.
	SizeHintU8 = 1
	// SizeHintU16 is the number of bytes required to represent a uint16 value
	// in binary.
	SizeHintU16 = 2
	// SizeHintU32 is the number of bytes required to represent a uint32 value
	// in binary.
	SizeHintU32 = 4
	// SizeHintU64 is the number of bytes required to represent a uint64 value
	// in binary.
	SizeHintU64 = 8
	// SizeHintI8 is the number of bytes required to represent a int8 value in
	// binary.
	SizeHintI8 = 1
	// SizeHintI16 is the number of bytes required to represent a int16 value in
	// binary.
	SizeHintI16 = 2
	// SizeHintI32 is the number of bytes required to represent a int32 value in
	// binary.
	SizeHintI32 = 4
	// SizeHintI64 is the number of bytes required to represent a int64 value in
	// binary.
	SizeHintI64 = 8
)
View Source
const MaxBytes = int(64 * 1024 * 1024)

MaxBytes is set to 64 MB by default.

View Source
const (
	// SizeHintBool is the number of bytes required to represent a boolean value
	// in binary.
	SizeHintBool = 1
)

Variables

View Source
var ErrLengthOverflow = errors.New("max bytes exceeded")

ErrLengthOverflow is returned when the length of an array or slice has overflowed.

View Source
var ErrUnexpectedEndOfBuffer = errors.New("unexpected end of buffer")

ErrUnexpectedEndOfBuffer is used when reading/writing from/to a buffer that has less space than expected.

Functions

func FromBinary

func FromBinary(v interface{}, buf []byte) error

FromBinary unmarshals a byte representation of a value to a pointer to that value. In uses the maximum memory quota to restrict the number of bytes that will be allocated during unmarshaling.

func Marshal

func Marshal(v interface{}, buf []byte, rem int) ([]byte, int, error)

Marshal a value into its binary representation, and store the value in a byte slice. The "remaining memory quota" defines the maximum amount of bytes that can be allocated on the heap when marshaling the value. In this way, the remaining memory quota can be used to avoid allocating too much memory during marshaling. Marshaling supports all scalars, strings, arrays, slices, maps, structs, and custom implementations (for types that implement the Marshaler interface). After marshaling, the unconsumed tail of the byte slice, and the remaining memory quota, are returned. If the byte slice is too small, then an error is returned. Similarly, if the remaining memory quote is too small, then an error is returned. If the type is not supported, then an error is returned. An error does not imply that nothing from the byte slice, or remaining memory quota, was consumed. If the value is a pointer, then the underlying value being pointed to will be marshaled.

x := int64(0)
buf := make([]byte, 8)
tail, rem, err := surge.Marshal(x, buf, 8)
if len(tail) != 0 {
    panic("assertion failed: int64 must consume 8 bytes")
}
if rem != 0 {
    panic("assertion failed: int64 must consume 8 bytes of the memory quota")
}
if err != nil {
    panic(fmt.Errorf("assertion failed: %v", err))
}

func MarshalBool

func MarshalBool(x bool, buf []byte, rem int) ([]byte, int, error)

MarshalBool into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalBytes

func MarshalBytes(v []byte, buf []byte, rem int) ([]byte, int, error)

MarshalBytes into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalF32

func MarshalF32(x float32, buf []byte, rem int) ([]byte, int, error)

MarshalF32 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalF64

func MarshalF64(x float64, buf []byte, rem int) ([]byte, int, error)

MarshalF64 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalI16

func MarshalI16(x int16, buf []byte, rem int) ([]byte, int, error)

MarshalI16 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalI32

func MarshalI32(x int32, buf []byte, rem int) ([]byte, int, error)

MarshalI32 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalI64

func MarshalI64(x int64, buf []byte, rem int) ([]byte, int, error)

MarshalI64 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalI8

func MarshalI8(x int8, buf []byte, rem int) ([]byte, int, error)

MarshalI8 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalLen

func MarshalLen(l uint32, buf []byte, rem int) ([]byte, int, error)

MarshalLen marshals the given slice length.

func MarshalString

func MarshalString(v string, buf []byte, rem int) ([]byte, int, error)

MarshalString into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalU16

func MarshalU16(x uint16, buf []byte, rem int) ([]byte, int, error)

MarshalU16 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalU32

func MarshalU32(x uint32, buf []byte, rem int) ([]byte, int, error)

MarshalU32 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalU64

func MarshalU64(x uint64, buf []byte, rem int) ([]byte, int, error)

MarshalU64 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func MarshalU8

func MarshalU8(x uint8, buf []byte, rem int) ([]byte, int, error)

MarshalU8 into a byte slice. It will not consume more memory than the remaining memory quota (either through writes, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func NewErrUnsupportedMarshalType

func NewErrUnsupportedMarshalType(v interface{}) error

NewErrUnsupportedMarshalType constructs a new unsupported marshal type error for the given type.

func NewErrUnsupportedUnmarshalType

func NewErrUnsupportedUnmarshalType(v interface{}) error

NewErrUnsupportedUnmarshalType constructs a new unsupported unmarshal type error for the given type.

func SizeHint

func SizeHint(v interface{}) int

SizeHint returns the number of bytes required to store a value in its binary representation. This is the number of bytes "on the wire", not the number of bytes that need to be allocated during marshaling/unmarshaling (which can be different, depending on the representation of the value). SizeHint supports all scalars, strings, arrays, slices, maps, structs, and custom implementations (for types that implement the SizeHinter interface). If the type is not supported, then zero is returned. If the value is a pointer, then the size of the underlying value being pointed to will be returned.

x := int64(0)
sizeHint := surge.SizeHint(x)
if sizeHint != 8 {
    panic("assertion failed: size of int64 must be 8 bytes")
}

func SizeHintBytes

func SizeHintBytes(v []byte) int

SizeHintBytes is the number of bytes required to represent the given byte slice in binary.

func SizeHintString

func SizeHintString(v string) int

SizeHintString is the number of bytes required to represent the given string in binary.

func ToBinary

func ToBinary(v interface{}) ([]byte, error)

ToBinary returns the byte representation of a value. In uses the maximum memory quota to restrict the number of bytes that will be allocated during marshaling.

func Unmarshal

func Unmarshal(v interface{}, buf []byte, rem int) ([]byte, int, error)

Unmarshal a value from its binary representation by reading from a byte slice. The "remaining memory quota" defines the maximum amount of bytes that can be allocated on the heap when unmarshaling the value. In this way, the remaining memory quota can be used to avoid allocating too much memory during unmarshaling (this is particularly useful when dealing with potentially malicious input). Unmarshaling supports pointers to all scalars, strings, arrays, slices, maps, structs, and custom implementations (for types that implement the Unmarshaler interface). After unmarshaling, the unconsumed tail of the byte slice, and the remaining memory quota, are returned. If the byte slice is too small, then an error is returned. Similarly, if the remaining memory quote is too small, then an error is returned. If the type is not a pointer to one of the supported types, then an error is returned. An error does not imply that nothing from the byte slice, or remaining memory quota, was consumed. If the value is not a pointer, then an error is returned.

x := int64(0)
buf := make([]byte, 8)
tail, rem, err := surge.Unmarshal(&x, buf, 8)
if len(tail) != 0 {
    panic("assertion failed: int64 must consume 8 bytes")
}
if rem != 0 {
    panic("assertion failed: int64 must consume 8 bytes of the memory quota")
}
if err != nil {
    panic(fmt.Errorf("assertion failed: %v", err))
}

func UnmarshalBool

func UnmarshalBool(x *bool, buf []byte, rem int) ([]byte, int, error)

UnmarshalBool from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalBytes

func UnmarshalBytes(v *[]byte, buf []byte, rem int) ([]byte, int, error)

UnmarshalBytes from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalF32

func UnmarshalF32(x *float32, buf []byte, rem int) ([]byte, int, error)

UnmarshalF32 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalF64

func UnmarshalF64(x *float64, buf []byte, rem int) ([]byte, int, error)

UnmarshalF64 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalI16

func UnmarshalI16(x *int16, buf []byte, rem int) ([]byte, int, error)

UnmarshalI16 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalI32

func UnmarshalI32(x *int32, buf []byte, rem int) ([]byte, int, error)

UnmarshalI32 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalI64

func UnmarshalI64(x *int64, buf []byte, rem int) ([]byte, int, error)

UnmarshalI64 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalI8

func UnmarshalI8(x *int8, buf []byte, rem int) ([]byte, int, error)

UnmarshalI8 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalLen

func UnmarshalLen(dst *uint32, elemSize int, buf []byte, rem int) ([]byte, int, error)

UnmarshalLen unmarshals a slice length, checking that the total space required for the slice will not exceed rem.

func UnmarshalString

func UnmarshalString(v *string, buf []byte, rem int) ([]byte, int, error)

UnmarshalString from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalU16

func UnmarshalU16(x *uint16, buf []byte, rem int) ([]byte, int, error)

UnmarshalU16 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalU32

func UnmarshalU32(x *uint32, buf []byte, rem int) ([]byte, int, error)

UnmarshalU32 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalU64

func UnmarshalU64(x *uint64, buf []byte, rem int) ([]byte, int, error)

UnmarshalU64 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

func UnmarshalU8

func UnmarshalU8(x *uint8, buf []byte, rem int) ([]byte, int, error)

UnmarshalU8 from a byte slice. It will not consume more memory than the remaining memory quota (either through reads, or in-memory allocations). It will return the unconsumed tail of the byte slice, and the remaining memory quota. An error is returned if the byte slice is too small, or if the remainin memory quote is insufficient.

Types

type ErrUnsupportedMarshalType

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

ErrUnsupportedMarshalType is returned when the an unsupported type is encountered during marshaling.

type ErrUnsupportedUnmarshalType

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

ErrUnsupportedUnmarshalType is returned when the an unsupported type is encountered during unmarshaling.

type MarshalUnmarshaler

type MarshalUnmarshaler interface {
	Marshaler
	Unmarshaler
}

A MarshalUnmarshaler is a marshaler and an unmarshaler.

type Marshaler

type Marshaler interface {
	SizeHinter

	// Marshal this value into bytes.
	Marshal(buf []byte, rem int) ([]byte, int, error)
}

A Marshaler can marshal itself into bytes.

type SizeHinter

type SizeHinter interface {
	// SizeHint returns the upper bound for the number of bytes required to
	// represent this value in binary.
	SizeHint() int
}

A SizeHinter can hint at the number of bytes required to represented it in binary.

type Unmarshaler

type Unmarshaler interface {
	// Unmarshal this value from bytes.
	Unmarshal(buf []byte, rem int) ([]byte, int, error)
}

An Unmarshaler can unmarshal itself from bytes.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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