Skip to content
Code-generation based encoder for Skycoin
Go Makefile
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
benchmark
cmd/skyencoder
tests
.gitignore
.travis.yml
Makefile
README.md
builder.go
builder_test.go
format.go

README.md

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
You can’t perform that action at this time.