Skip to content

Latest commit

 

History

History
179 lines (132 loc) · 6.81 KB

README.md

File metadata and controls

179 lines (132 loc) · 6.81 KB

skyencoder

Code-generation based encoder for Skycoin

Build Status GoDoc

Introduction

skyencoder generates a file with encode and decode methods for an encodable struct, using the Skycoin binary encoding format.

For encodable non-struct types, you can wrap the non-struct type in a struct for the same result. A struct definition adds no overhead and does not change the encoding.

Skycoin's package encoder has a reflect-based encoder that can be used at runtime, and supports any encodable type.

Installation

go get github.com/skycoin/skyencoder/cmd/skyencoder

This installs skyencoder to $GOPATH/bin. Make sure $GOPATH/bin is in your shell environment's $PATH variable in order to invoke it in the shell.

go:generate

To use go generate to generate the code, add a directive like this in the file where the struct is defined:

// go:generate skyencoder -struct Foo

Then, use go:generate to generate it:

go generate github.com/foo/foo

CLI Usage

» go run cmd/skyencoder/skyencoder.go --help
Usage of skyencoder:
	skyencoder [flags] -struct T [go import path e.g. github.com/skycoin/skycoin/src/coin]
	skyencoder [flags] -struct T files... # Must be a single package
Flags:
  -no-test
    	disable generating the _test.go file (test files require github.com/google/go-cmp/cmp and github.com/skycoin/encodertest)
  -output-file string
    	output file name; default <struct_name>_skyencoder.go
  -output-path string
    	output path; defaults to the package's path, or the file's containing folder
  -package string
    	package name for the output; if not provided, defaults to the struct's package
  -silent
    	disable all non-error log output
  -struct string
    	struct name, must be set
  -tags string
    	comma-separated list of build tags to apply
  -unexported
    	don't export generated methods (always true if the struct is not an exported type)

skyencoder generates a file with encode and decode methods for a struct, using the Skycoin encoding format.

By default, the generated file is written to the same package as the source struct type.

If you wish to have the file written to a different location, use -package to control the name of the destination package, -output-path to control the destination path, and -output-file to control the destination filename.

Build tags can be applied to the loaded package with -tags.

CLI Examples

Generate code for struct coin.SignedBlock in github.com/skycoin/skycoin/src/coin:

go run cmd/skyencoder/skyencoder.go -struct SignedBlock github.com/skycoin/skycoin/src/coin

Generate code for struct Foo in /tmp/foo/foo.go:

go run cmd/skyencoder/skyencoder.go -struct Foo /tmp/foo/foo.go

Note: absolute paths can only point to a Go file. If there are multiple Go files in that same path, all of them must be included.

Generate code for struct coin.SignedBlock in github.com/skycoin/skycoin/src/coin, but sent to an external package:

go run cmd/skyencoder/skyencoder.go -struct SignedBlock -package foo -output-path /tmp/foo github.com/skycoin/skycoin/src/coin

Note: do not use -package if the generated file is going to be in the same package as the struct

Generate encoder for non-struct types

skyencoder only generates code for struct types, but the reflect-based skycoin encoder package can handle any encodable type as an argument. Since structs add no overhead, you can wrap your non-struct type in a struct to generate an encoder for it with skyencoder.

For example, to generate an encoder for []int64, wrap it:

import (
	"bytes"

	"github.com/skycoin/skycoin/src/cipher/encoder"
)

//go:generate skyencoder -struct int64SliceWrapper
type int64SliceWrapper struct {
	Int64Slice []int64
}

func assertEncoderEqualsSkyencoder(x []int64) {
	buf, err := encoder.Serialize(x)
	if err != nil {
		return panic(err)
	}

	buf2, err := encodeInt64SliceWrapper(int64SliceWrapper{
		Int64Slice: x,
	})
	if err != nil {
		panic(err)
	}

	if !bytes.Equal(buf, buf2) {
		panic("encoder.Serialize does not match encodeInt64SliceWrapper")
	}
}

Generated tests

A file with tests is generated by default and can be disabled with -no-test. This test file requires github.com/google/go-cmp/cmp and github.com/google/go-cmp/cmp/cmpopts.

Autogenerated tests will check that encoding and decoding succeeds and that the output matches the reflect-based github.com/skycoin/skycoin/src/cipher/encoder.

Notes:

  • Autogenerated tests do not cover maxlen exceeded errors

Benchmark results

Benchmarks compare the reflect-based github.com/skycoin/skycoin/src/cipher/encoder to the generated encoder. Benchmarks performed on a Mid-2015 base model 15" Macbook Pro.

Comparison of skyencoder to other encoders is available at:

» make bench
go test -benchmem -bench '.*' ./benchmark
goos: darwin
goarch: amd64
pkg: github.com/skycoin/skyencoder/benchmark
BenchmarkEncodeSize-8                    	200000000	         6.33 ns/op	       0 B/op	       0 allocs/op
BenchmarkCipherEncodeSize-8              	 1000000	      1488 ns/op	     128 B/op	      16 allocs/op
BenchmarkEncodeToBuffer-8                	10000000	       133 ns/op	       0 B/op	       0 allocs/op
BenchmarkEncode-8                        	10000000	       189 ns/op	     112 B/op	       1 allocs/op
BenchmarkCipherEncode-8                  	  500000	      3103 ns/op	     400 B/op	      34 allocs/op
BenchmarkDecode-8                        	 5000000	       375 ns/op	     120 B/op	      10 allocs/op
BenchmarkCipherDecode-8                  	  500000	      2425 ns/op	     472 B/op	      29 allocs/op
BenchmarkEncodeSizeSignedBlock-8         	50000000	        25.0 ns/op	       0 B/op	       0 allocs/op
BenchmarkCipherEncodeSizeSignedBlock-8   	  200000	      8125 ns/op	     600 B/op	      75 allocs/op
BenchmarkEncodeSignedBlockToBuffer-8     	 3000000	       418 ns/op	       0 B/op	       0 allocs/op
BenchmarkEncodeSignedBlock-8             	 2000000	       721 ns/op	    1792 B/op	       1 allocs/op
BenchmarkCipherEncodeSignedBlock-8       	  100000	     19673 ns/op	    4080 B/op	     185 allocs/op
BenchmarkDecodeSignedBlock-8             	 1000000	      1002 ns/op	    1648 B/op	      10 allocs/op
BenchmarkCipherDecodeSignedBlock-8       	  100000	     13919 ns/op	    5448 B/op	     130 allocs/op
PASS
ok  	github.com/skycoin/skyencoder/benchmark	24.198s