go-binenc-gen

command module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Dec 28, 2022 License: BSD-3-Clause-Open-MPI Imports: 13 Imported by: 0

Documentation

Overview

go-binenc-gen is a tool to automate the creation of binary serialization methods. Given the name of a Go source file containing structs definitions, go-binenc-gen will create a new self-contained Go source file implementing

func (s *T) WriteTo(w io.Writer) (n int, err error)
func (s *T) ReadFrom(r io.Reader) (err error)

The file is created in the same package and directory as the package that defines T. It has helpful defaults designed for use with go generate.

The goal of the tool is to generate extremely fast binary serialization code by forfeiting the convenience of runtime reflection enabled libraries, such as binary or gob.

For example, given this snippet,

package example

type Header struct {
	Name string
	Value string
}

type Request struct {
	Headers []Header
	ResponseTime uin64
}

running this command

go-binenc-gen example.go

in the same directory will create the file example_encoding.go, in package example, containing definitions of

func (s *Header) WriteTo(w io.Writer) (n int, err error)
func (s *Header) ReadFrom(r io.Reader) (err error)
func (s *Request) WriteTo(w io.Writer) (n int, err error)
func (s *Request) ReadFrom(r io.Reader) (err error)

These methods will serialize Header and Request objects, using a single allocation per WriteTo. For Reads, there will be as many allocations as pointers and slices in the struct:

func (s *Request) WriteTo(w io.Writer) (n int, err error) {
        size := 10
        for _, v := range s.Headers {
                size += 4
                size += len(v.Name) + len(v.Value)
        }
        buf := make([]byte, size)
        offset := 0
        // Headers
        buf[offset] = byte(len(s.Headers))
        buf[offset+1] = byte(len(s.Headers) >> 8)
        offset += 2
        for _, v := range s.Headers {
                buf[offset] = byte(len(v.Name))
                buf[offset+1] = byte(len(v.Name) >> 8)
                offset += 2
                copy(buf[offset:], v.Name)
                offset += len(v.Name)
                buf[offset] = byte(len(v.Value))
                buf[offset+1] = byte(len(v.Value) >> 8)
                offset += 2
                copy(buf[offset:], v.Value)
                offset += len(v.Value)
        }
        // ResponseTime
        buf[offset] = byte(s.ResponseTime)
        buf[offset+1] = byte(s.ResponseTime >> 8)
        buf[offset+2] = byte(s.ResponseTime >> 16)
        buf[offset+3] = byte(s.ResponseTime >> 24)
        buf[offset+4] = byte(s.ResponseTime >> 32)
        buf[offset+5] = byte(s.ResponseTime >> 40)
        buf[offset+6] = byte(s.ResponseTime >> 48)
        buf[offset+7] = byte(s.ResponseTime >> 56)
        offset += 8
        return w.Write(buf)
}

func (s *Request) Read(r io.Reader) error {
        buf := make([]byte, 8)
        var size uint16
        // Headers
        r.Read(buf[:2])
        size = uint16(buf[0]) | (uint16(buf[1]) << 8)
        s.Headers = make([]Header, size)
        si := int(size)
        for i := 0; i < si; i++ {
                r.Read(buf[:2])
                size = uint16(buf[0]) | (uint16(buf[1]) << 8)
                strBuf_0 := make([]byte, size)
                r.Read(strBuf_0)
                s.Headers[i].Name = *(*string)(unsafe.Pointer(&strBuf_0))
                r.Read(buf[:2])
                size = uint16(buf[0]) | (uint16(buf[1]) << 8)
                strBuf_1 := make([]byte, size)
                r.Read(strBuf_1)
                s.Headers[i].Value = *(*string)(unsafe.Pointer(&strBuf_1))
        }
        // ResponseTime
        r.Read(buf[:8])
        s.ResponseTime = uint64(buf[0]) | (uint64(buf[1]) << 8) | (uint64(buf[2]) << 16) | (uint64(buf[3]) << 24) | (uint64(buf[4]) << 32) | (uint64(buf[5]) << 40) | (uint64(buf[6]) << 48) | (uint64(buf[7]) << 56)
        return nil
}

Note that the serialization of Header objects during the serialization of a Request is inlined. For that reason, recursive definitions are not yet supported.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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