vendor: Mega update all dependencies

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4080
This commit is contained in:
Jakob Borg
2017-04-05 14:34:41 +00:00
parent 49c1527724
commit a1bcc15458
1354 changed files with 55066 additions and 797850 deletions

View File

@@ -1,71 +0,0 @@
go-lz4
======
go-lz4 is port of LZ4 lossless compression algorithm to Go. The original C code
is located at:
https://github.com/Cyan4973/lz4
Status
------
[![Build Status](https://secure.travis-ci.org/bkaradzic/go-lz4.png)](http://travis-ci.org/bkaradzic/go-lz4)
[![GoDoc](https://godoc.org/github.com/bkaradzic/go-lz4?status.png)](https://godoc.org/github.com/bkaradzic/go-lz4)
Usage
-----
go get github.com/bkaradzic/go-lz4
import "github.com/bkaradzic/go-lz4"
The package name is `lz4`
Notes
-----
* go-lz4 saves a uint32 with the original uncompressed length at the beginning
of the encoded buffer. They may get in the way of interoperability with
other implementations.
Contributors
------------
Damian Gryski ([@dgryski](https://github.com/dgryski))
Dustin Sallings ([@dustin](https://github.com/dustin))
Contact
-------
[@bkaradzic](https://twitter.com/bkaradzic)
http://www.stuckingeometry.com
Project page
https://github.com/bkaradzic/go-lz4
License
-------
Copyright 2011-2012 Branimir Karadzic. All rights reserved.
Copyright 2013 Damian Gryski. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,63 +0,0 @@
package lz4
import (
"bytes"
"io/ioutil"
"testing"
)
var testfile, _ = ioutil.ReadFile("testdata/pg1661.txt")
func roundtrip(t *testing.T, input []byte) {
dst, err := Encode(nil, input)
if err != nil {
t.Errorf("got error during compression: %s", err)
}
output, err := Decode(nil, dst)
if err != nil {
t.Errorf("got error during decompress: %s", err)
}
if !bytes.Equal(output, input) {
t.Errorf("roundtrip failed")
}
}
func TestEmpty(t *testing.T) {
roundtrip(t, nil)
}
func TestLengths(t *testing.T) {
for i := 0; i < 1024; i++ {
roundtrip(t, testfile[:i])
}
for i := 1024; i < 4096; i += 23 {
roundtrip(t, testfile[:i])
}
}
func TestWords(t *testing.T) {
roundtrip(t, testfile)
}
func BenchmarkLZ4Encode(b *testing.B) {
for i := 0; i < b.N; i++ {
Encode(nil, testfile)
}
}
func BenchmarkLZ4Decode(b *testing.B) {
var compressed, _ = Encode(nil, testfile)
b.ResetTimer()
for i := 0; i < b.N; i++ {
Decode(nil, compressed)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +0,0 @@
package du
import "testing"
func TestDiskUsage(t *testing.T) {
cases := []struct {
path string
ok bool
}{
{"c:\\", true},
{"c:\\windows", true},
{"c:\\aux", false},
{"c:\\does-not-exist-09sadkjhdsa98234bj23hgasd98", false},
}
for _, tc := range cases {
res, err := Get(tc.path)
if tc.ok {
if err != nil {
t.Errorf("Unexpected error Get(%q) => %v", tc.path, err)
} else if res.TotalBytes == 0 || res.AvailBytes == 0 || res.FreeBytes == 0 {
t.Errorf("Suspicious result Get(%q) => %v", tc.path, res)
}
} else if err == nil {
t.Errorf("Unexpected nil error in Get(%q)", tc.path)
}
}
}

View File

@@ -1,59 +0,0 @@
// Copyright (C) 2014 Jakob Borg
package luhn_test
import (
"testing"
"github.com/calmh/luhn"
)
func TestGenerate(t *testing.T) {
// Base 6 Luhn
a := luhn.Alphabet("abcdef")
c, err := a.Generate("abcdef")
if err != nil {
t.Fatal(err)
}
if c != 'e' {
t.Errorf("Incorrect check digit %c != e", c)
}
// Base 10 Luhn
a = luhn.Alphabet("0123456789")
c, err = a.Generate("7992739871")
if err != nil {
t.Fatal(err)
}
if c != '3' {
t.Errorf("Incorrect check digit %c != 3", c)
}
}
func TestInvalidString(t *testing.T) {
a := luhn.Alphabet("ABC")
_, err := a.Generate("7992739871")
t.Log(err)
if err == nil {
t.Error("Unexpected nil error")
}
}
func TestBadAlphabet(t *testing.T) {
a := luhn.Alphabet("01234566789")
_, err := a.Generate("7992739871")
t.Log(err)
if err == nil {
t.Error("Unexpected nil error")
}
}
func TestValidate(t *testing.T) {
a := luhn.Alphabet("abcdef")
if !a.Validate("abcdefe") {
t.Errorf("Incorrect validation response for abcdefe")
}
if a.Validate("abcdefd") {
t.Errorf("Incorrect validation response for abcdefd")
}
}

View File

@@ -1,10 +0,0 @@
xdr
===
[![Build Status](https://img.shields.io/circleci/project/calmh/xdr.svg?style=flat-square)](https://circleci.com/gh/calmh/xdr)
[![Coverage Status](https://img.shields.io/coveralls/calmh/xdr.svg?style=flat)](https://coveralls.io/r/calmh/xdr?branch=master)
[![API Documentation](http://img.shields.io/badge/api-Godoc-blue.svg?style=flat)](http://godoc.org/github.com/calmh/xdr)
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://opensource.org/licenses/MIT)
This is an XDR marshalling/unmarshalling library. It uses code generation and
not reflection.

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
// is governed by an MIT-style license that can be found in the LICENSE file.
package xdr_test
import "testing"
type XDRBenchStruct struct {
I1 uint64
I2 uint32
I3 uint16
I4 uint8
Bs0 []byte // max:128
Bs1 []byte
Is0 []int32
S0 string // max:128
S1 string
}
var res []byte // not to be optimized away
var s = XDRBenchStruct{
I1: 42,
I2: 43,
I3: 44,
I4: 45,
Bs0: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
Bs1: []byte{11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
Is0: []int32{23, 43},
S0: "Hello World! String one.",
S1: "Hello World! String two.",
}
func BenchmarkThisMarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
res, _ = s.MarshalXDR()
}
b.ReportAllocs()
}
func BenchmarkThisUnmarshal(b *testing.B) {
bs := s.MustMarshalXDR()
var t XDRBenchStruct
for i := 0; i < b.N; i++ {
err := t.UnmarshalXDR(bs)
if err != nil {
b.Fatal(err)
}
}
b.ReportAllocs()
}

View File

@@ -1,140 +0,0 @@
// ************************************************************
// This file is automatically generated by genxdr. Do not edit.
// ************************************************************
package xdr_test
import (
"github.com/calmh/xdr"
)
/*
XDRBenchStruct Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ I1 (64 bits) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| I2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 16 zero bits | I3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 24 zero bits | I4 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Bs0 (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Bs1 (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of Is0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
| Is0 (n items) |
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ S0 (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ S1 (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct XDRBenchStruct {
unsigned hyper I1;
unsigned int I2;
unsigned int I3;
unsigned int I4;
opaque Bs0<128>;
opaque Bs1<>;
int Is0<>;
string S0<128>;
string S1<>;
}
*/
func (o XDRBenchStruct) XDRSize() int {
return 8 + 4 + 4 + 4 +
4 + len(o.Bs0) + xdr.Padding(len(o.Bs0)) +
4 + len(o.Bs1) + xdr.Padding(len(o.Bs1)) +
4 + len(o.Is0)*4 +
4 + len(o.S0) + xdr.Padding(len(o.S0)) +
4 + len(o.S1) + xdr.Padding(len(o.S1))
}
func (o XDRBenchStruct) MarshalXDR() ([]byte, error) {
buf := make([]byte, o.XDRSize())
m := &xdr.Marshaller{Data: buf}
return buf, o.MarshalXDRInto(m)
}
func (o XDRBenchStruct) MustMarshalXDR() []byte {
bs, err := o.MarshalXDR()
if err != nil {
panic(err)
}
return bs
}
func (o XDRBenchStruct) MarshalXDRInto(m *xdr.Marshaller) error {
m.MarshalUint64(o.I1)
m.MarshalUint32(o.I2)
m.MarshalUint16(o.I3)
m.MarshalUint8(o.I4)
if l := len(o.Bs0); l > 128 {
return xdr.ElementSizeExceeded("Bs0", l, 128)
}
m.MarshalBytes(o.Bs0)
m.MarshalBytes(o.Bs1)
m.MarshalUint32(uint32(len(o.Is0)))
for i := range o.Is0 {
m.MarshalUint32(uint32(o.Is0[i]))
}
if l := len(o.S0); l > 128 {
return xdr.ElementSizeExceeded("S0", l, 128)
}
m.MarshalString(o.S0)
m.MarshalString(o.S1)
return m.Error
}
func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *XDRBenchStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.I1 = u.UnmarshalUint64()
o.I2 = u.UnmarshalUint32()
o.I3 = u.UnmarshalUint16()
o.I4 = u.UnmarshalUint8()
o.Bs0 = u.UnmarshalBytesMax(128)
o.Bs1 = u.UnmarshalBytes()
_Is0Size := int(u.UnmarshalUint32())
if _Is0Size < 0 {
return xdr.ElementSizeExceeded("Is0", _Is0Size, 0)
} else if _Is0Size == 0 {
o.Is0 = nil
} else {
if _Is0Size <= len(o.Is0) {
o.Is0 = o.Is0[:_Is0Size]
} else {
o.Is0 = make([]int32, _Is0Size)
}
for i := range o.Is0 {
o.Is0[i] = int32(u.UnmarshalUint32())
}
}
o.S0 = u.UnmarshalStringMax(128)
o.S1 = u.UnmarshalString()
return u.Error
}

View File

@@ -1,3 +0,0 @@
dependencies:
post:
- ./generate.sh

View File

@@ -1,241 +0,0 @@
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
// is governed by an MIT-style license that can be found in the LICENSE file.
package xdr_test
import (
"bytes"
"io"
"log"
"math/rand"
"reflect"
"testing"
"testing/quick"
"github.com/calmh/xdr"
)
// Contains all supported types
type TestStruct struct {
B bool
I int
I8 int8
UI8 uint8
I16 int16
UI16 uint16
I32 int32
UI32 uint32
I64 int64
UI64 uint64
BS []byte // max:1024
S string // max:1024
C Opaque
SS []string // max:1024
ES EmptyStruct
OS OtherStruct
OSs []OtherStruct
}
func (s1 TestStruct) TestEquals(s2 TestStruct) bool {
if s1.B != s2.B {
log.Printf("B differ; %v != %v", s1.B, s2.B)
return false
}
if s1.I != s2.I {
log.Printf("I differ; %d != %d", s1.I, s2.I)
return false
}
if s1.I8 != s2.I8 {
log.Printf("I8 differ; %d != %d", s1.I8, s2.I8)
return false
}
if s1.UI8 != s2.UI8 {
log.Printf("UI8 differ; %d != %d", s1.UI8, s2.UI8)
return false
}
if s1.I16 != s2.I16 {
log.Printf("I16 differ; %d != %d", s1.I16, s2.I16)
return false
}
if s1.UI16 != s2.UI16 {
log.Printf("UI16 differ; %d != %d", s1.UI16, s2.UI16)
return false
}
if s1.I32 != s2.I32 {
log.Printf("I32 differ; %d != %d", s1.I32, s2.I32)
return false
}
if s1.UI32 != s2.UI32 {
log.Printf("UI32 differ; %d != %d", s1.UI32, s2.UI32)
return false
}
if s1.I64 != s2.I64 {
log.Printf("I64 differ; %d != %d", s1.I64, s2.I64)
return false
}
if s1.UI64 != s2.UI64 {
log.Printf("UI64 differ; %d != %d", s1.UI64, s2.UI64)
return false
}
if !bytes.Equal(s1.BS, s2.BS) {
log.Println("BS differ")
return false
}
if s1.S != s2.S {
log.Printf("S differ; %q != %q", s1.S, s2.S)
return false
}
if s1.C != s2.C {
log.Printf("C differ; %q != %q", s1.C, s2.C)
return false
}
if len(s1.SS) != len(s2.SS) {
log.Printf("len(SS) differ; %q != %q", len(s1.SS), len(s2.SS))
return false
}
for i := range s1.SS {
if s1.SS[i] != s2.SS[i] {
log.Printf("SS[%d] differ; %q != %q", i, s1.SS[i], s2.SS[i])
return false
}
}
if s1.OS != s2.OS {
log.Printf("OS differ; %q != %q", s1.OS, s2.OS)
return false
}
if len(s1.OSs) != len(s2.OSs) {
log.Printf("len(OSs) differ; %q != %q", len(s1.OSs), len(s2.OSs))
return false
}
for i := range s1.OSs {
if s1.OSs[i] != s2.OSs[i] {
log.Printf("OSs[%d] differ; %q != %q", i, s1.OSs[i], s2.OSs[i])
return false
}
}
return true
}
type EmptyStruct struct {
}
type OtherStruct struct {
F1 uint32
F2 string
}
type Opaque [32]byte
func (u *Opaque) XDRSize() int {
return 32
}
func (u *Opaque) MarshalXDRInto(m *xdr.Marshaller) error {
m.MarshalRaw(u[:])
return m.Error
}
func (o *Opaque) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
copy((*o)[:], u.UnmarshalRaw(32))
return u.Error
}
func (Opaque) Generate(rand *rand.Rand, size int) reflect.Value {
var u Opaque
for i := range u[:] {
u[i] = byte(rand.Int())
}
return reflect.ValueOf(u)
}
func TestEncDec(t *testing.T) {
fn := func(t0 TestStruct) bool {
bs, err := t0.MarshalXDR()
if err != nil {
t.Fatal(err)
}
var t1 TestStruct
err = t1.UnmarshalXDR(bs)
if err != nil {
t.Fatal(err)
}
return t0.TestEquals(t1)
}
if err := quick.Check(fn, nil); err != nil {
t.Error(err)
}
}
func TestMarshalShortBuffer(t *testing.T) {
var s TestStruct
buf := make([]byte, s.XDRSize())
if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf}); err != nil {
t.Fatal("Unexpected error", err)
}
if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf[1:]}); err != io.ErrShortBuffer {
t.Fatal("Expected io.ErrShortBuffer, got", err)
}
}
func TestUnmarshalUnexpectedEOF(t *testing.T) {
var s TestStruct
buf := make([]byte, s.XDRSize())
if err := s.MarshalXDRInto(&xdr.Marshaller{Data: buf}); err != nil {
t.Fatal("Unexpected error", err)
}
if err := s.UnmarshalXDR(buf[:len(buf)-1]); err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u := &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalRaw(4)
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalString()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalBytes()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalBool()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalUint8()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalUint16()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:3]}
u.UnmarshalUint32()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
u = &xdr.Unmarshaller{Data: buf[:7]}
u.UnmarshalUint64()
if err := u.Error; err != io.ErrUnexpectedEOF {
t.Fatal("Expected io.ErrUnexpectedEOF, got", err)
}
}

View File

@@ -1,319 +0,0 @@
// ************************************************************
// This file is automatically generated by genxdr. Do not edit.
// ************************************************************
package xdr_test
import (
"github.com/calmh/xdr"
)
/*
TestStruct Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| B (V=0 or 1) |V|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ int Structure \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 24 zero bits | I8 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 24 zero bits | UI8 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 16 zero bits | I16 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 16 zero bits | UI16 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| I32 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UI32 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ I64 (64 bits) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ UI64 (64 bits) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ BS (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ S (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Opaque Structure \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of SS |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
/ /
\ SS (length + padded data) \
/ /
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ EmptyStruct Structure \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ OtherStruct Structure \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of OSs |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ Zero or more OtherStruct Structures \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct TestStruct {
bool B;
int I;
int I8;
unsigned int UI8;
int I16;
unsigned int UI16;
int I32;
unsigned int UI32;
hyper I64;
unsigned hyper UI64;
opaque BS<1024>;
string S<1024>;
Opaque C;
string SS<1024>;
EmptyStruct ES;
OtherStruct OS;
OtherStruct OSs<>;
}
*/
func (o TestStruct) XDRSize() int {
return 4 + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 8 +
4 + len(o.BS) + xdr.Padding(len(o.BS)) +
4 + len(o.S) + xdr.Padding(len(o.S)) +
o.C.XDRSize() +
4 + xdr.SizeOfSlice(o.SS) +
o.ES.XDRSize() +
o.OS.XDRSize() +
4 + xdr.SizeOfSlice(o.OSs)
}
func (o TestStruct) MarshalXDR() ([]byte, error) {
buf := make([]byte, o.XDRSize())
m := &xdr.Marshaller{Data: buf}
return buf, o.MarshalXDRInto(m)
}
func (o TestStruct) MustMarshalXDR() []byte {
bs, err := o.MarshalXDR()
if err != nil {
panic(err)
}
return bs
}
func (o TestStruct) MarshalXDRInto(m *xdr.Marshaller) error {
m.MarshalBool(o.B)
m.MarshalUint64(uint64(o.I))
m.MarshalUint8(uint8(o.I8))
m.MarshalUint8(o.UI8)
m.MarshalUint16(uint16(o.I16))
m.MarshalUint16(o.UI16)
m.MarshalUint32(uint32(o.I32))
m.MarshalUint32(o.UI32)
m.MarshalUint64(uint64(o.I64))
m.MarshalUint64(o.UI64)
if l := len(o.BS); l > 1024 {
return xdr.ElementSizeExceeded("BS", l, 1024)
}
m.MarshalBytes(o.BS)
if l := len(o.S); l > 1024 {
return xdr.ElementSizeExceeded("S", l, 1024)
}
m.MarshalString(o.S)
if err := o.C.MarshalXDRInto(m); err != nil {
return err
}
if l := len(o.SS); l > 1024 {
return xdr.ElementSizeExceeded("SS", l, 1024)
}
m.MarshalUint32(uint32(len(o.SS)))
for i := range o.SS {
m.MarshalString(o.SS[i])
}
if err := o.ES.MarshalXDRInto(m); err != nil {
return err
}
if err := o.OS.MarshalXDRInto(m); err != nil {
return err
}
m.MarshalUint32(uint32(len(o.OSs)))
for i := range o.OSs {
if err := o.OSs[i].MarshalXDRInto(m); err != nil {
return err
}
}
return m.Error
}
func (o *TestStruct) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *TestStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.B = u.UnmarshalBool()
o.I = int(u.UnmarshalUint64())
o.I8 = int8(u.UnmarshalUint8())
o.UI8 = u.UnmarshalUint8()
o.I16 = int16(u.UnmarshalUint16())
o.UI16 = u.UnmarshalUint16()
o.I32 = int32(u.UnmarshalUint32())
o.UI32 = u.UnmarshalUint32()
o.I64 = int64(u.UnmarshalUint64())
o.UI64 = u.UnmarshalUint64()
o.BS = u.UnmarshalBytesMax(1024)
o.S = u.UnmarshalStringMax(1024)
(&o.C).UnmarshalXDRFrom(u)
_SSSize := int(u.UnmarshalUint32())
if _SSSize < 0 {
return xdr.ElementSizeExceeded("SS", _SSSize, 1024)
} else if _SSSize == 0 {
o.SS = nil
} else {
if _SSSize > 1024 {
return xdr.ElementSizeExceeded("SS", _SSSize, 1024)
}
if _SSSize <= len(o.SS) {
for i := _SSSize; i < len(o.SS); i++ {
o.SS[i] = ""
}
o.SS = o.SS[:_SSSize]
} else {
o.SS = make([]string, _SSSize)
}
for i := range o.SS {
o.SS[i] = u.UnmarshalString()
}
}
(&o.ES).UnmarshalXDRFrom(u)
(&o.OS).UnmarshalXDRFrom(u)
_OSsSize := int(u.UnmarshalUint32())
if _OSsSize < 0 {
return xdr.ElementSizeExceeded("OSs", _OSsSize, 0)
} else if _OSsSize == 0 {
o.OSs = nil
} else {
if _OSsSize <= len(o.OSs) {
o.OSs = o.OSs[:_OSsSize]
} else {
o.OSs = make([]OtherStruct, _OSsSize)
}
for i := range o.OSs {
(&o.OSs[i]).UnmarshalXDRFrom(u)
}
}
return u.Error
}
/*
EmptyStruct Structure:
(contains no fields)
struct EmptyStruct {
}
*/
func (o EmptyStruct) XDRSize() int {
return 0
}
func (o EmptyStruct) MarshalXDR() ([]byte, error) {
return nil, nil
}
func (o EmptyStruct) MustMarshalXDR() []byte {
return nil
}
func (o EmptyStruct) MarshalXDRInto(m *xdr.Marshaller) error {
return nil
}
func (o *EmptyStruct) UnmarshalXDR(bs []byte) error {
return nil
}
func (o *EmptyStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
return nil
}
/*
OtherStruct Structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| F1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ /
\ F2 (length + padded data) \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct OtherStruct {
unsigned int F1;
string F2<>;
}
*/
func (o OtherStruct) XDRSize() int {
return 4 +
4 + len(o.F2) + xdr.Padding(len(o.F2))
}
func (o OtherStruct) MarshalXDR() ([]byte, error) {
buf := make([]byte, o.XDRSize())
m := &xdr.Marshaller{Data: buf}
return buf, o.MarshalXDRInto(m)
}
func (o OtherStruct) MustMarshalXDR() []byte {
bs, err := o.MarshalXDR()
if err != nil {
panic(err)
}
return bs
}
func (o OtherStruct) MarshalXDRInto(m *xdr.Marshaller) error {
m.MarshalUint32(o.F1)
m.MarshalString(o.F2)
return m.Error
}
func (o *OtherStruct) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *OtherStruct) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.F1 = u.UnmarshalUint32()
o.F2 = u.UnmarshalString()
return u.Error
}

View File

@@ -1,4 +0,0 @@
#!/bin/sh
go run cmd/genxdr/main.go -- bench_test.go > bench_xdr_test.go
go run cmd/genxdr/main.go -- encdec_test.go > encdec_xdr_test.go

View File

@@ -1,66 +0,0 @@
go-stun
=======
[![Build Status](https://travis-ci.org/ccding/go-stun.svg?branch=master)]
(https://travis-ci.org/ccding/go-stun)
[![License](https://img.shields.io/badge/License-Apache%202.0-red.svg)]
(https://opensource.org/licenses/Apache-2.0)
[![GoDoc](https://godoc.org/github.com/ccding/go-stun?status.svg)]
(http://godoc.org/github.com/ccding/go-stun/stun)
[![Go Report Card](https://goreportcard.com/badge/github.com/ccding/go-stun)]
(https://goreportcard.com/report/github.com/ccding/go-stun)
go-stun is a STUN (RFC 3489, 5389) client implementation in golang
(a.k.a. UDP hole punching).
[RFC 3489](https://tools.ietf.org/html/rfc3489):
STUN - Simple Traversal of User Datagram Protocol (UDP)
Through Network Address Translators (NATs)
[RFC 5389](https://tools.ietf.org/html/rfc5389):
Session Traversal Utilities for NAT (STUN)
### Use the Command Line Tool
Simply run these commands (if you have installed golang and set `$GOPATH`)
```
go get github.com/ccding/go-stun
go-stun
```
or clone this repo and run these commands
```
go build
./go-stun
```
You will get the output like
```
NAT Type: Full cone NAT
External IP Family: 1
External IP: 166.111.4.100
External Port: 23009
```
You can use `-s` flag to use another STUN server, and use `-v` to work on
verbose mode.
```bash
> ./go-stun --help
Usage of ./go-stun:
-s string
server address (default "stun1.l.google.com:19302")
-v verbose mode
```
### Use the Library
The library `github.com/ccding/go-stun/stun` is extremely easy to use -- just
one line of code.
```go
import "github.com/ccding/go-stun/stun"
func main() {
nat, host, err := stun.NewClient().Discover()
}
```
More details please go to `main.go` and [GoDoc]
(http://godoc.org/github.com/ccding/go-stun/stun)

View File

@@ -1,56 +0,0 @@
// Copyright 2013, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: Cong Ding <dinggnu@gmail.com>
package main
import (
"flag"
"fmt"
"github.com/ccding/go-stun/stun"
)
func main() {
var serverAddr = flag.String("s", stun.DefaultServerAddr, "STUN server address")
var v = flag.Bool("v", false, "verbose mode")
var vv = flag.Bool("vv", false, "double verbose mode (includes -v)")
var vvv = flag.Bool("vvv", false, "triple verbose mode (includes -v and -vv)")
flag.Parse()
// Creates a STUN client. NewClientWithConnection can also be used if
// you want to handle the UDP listener by yourself.
client := stun.NewClient()
// The default addr (stun.DefaultServerAddr) will be used unless we
// call SetServerAddr.
client.SetServerAddr(*serverAddr)
// Non verbose mode will be used by default unless we call
// SetVerbose(true) or SetVVerbose(true).
client.SetVerbose(*v || *vv || *vvv)
client.SetVVerbose(*vv || *vvv)
// Discover the NAT and return the result.
nat, host, err := client.Discover()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("NAT Type:", nat)
if host != nil {
fmt.Println("External IP Family:", host.Family())
fmt.Println("External IP:", host.IP())
fmt.Println("External Port:", host.Port())
}
}

View File

@@ -88,6 +88,11 @@ func (c *Client) discover(conn net.PacketConn, addr *net.UDPAddr) (NATType, *Hos
resp.serverAddr.Port() != uint16(addr.Port) {
return NATError, mappedAddr, errors.New("Server error: response IP/port")
}
// if changedAddr is not available, use otherAddr as changedAddr,
// which is updated in RFC 5780
if changedAddr == nil {
changedAddr = resp.otherAddr
}
// changedAddr shall not be nil
if changedAddr == nil {
return NATError, mappedAddr, errors.New("Server error: no changed address.")

View File

@@ -98,6 +98,10 @@ func (v *packet) getChangedAddr() *Host {
return v.getRawAddr(attributeChangedAddress)
}
func (v *packet) getOtherAddr() *Host {
return v.getRawAddr(attributeOtherAddress)
}
func (v *packet) getRawAddr(attribute uint16) *Host {
for _, a := range v.attributes {
if a.types == attribute {

View File

@@ -1,61 +0,0 @@
// Copyright 2016, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Cong Ding <dinggnu@gmail.com>
package stun
import (
"testing"
)
func TestNewPacketFromBytes(t *testing.T) {
b := make([]byte, 23)
_, err := newPacketFromBytes(b)
if err == nil {
t.Errorf("newPacketFromBytes error")
}
b = make([]byte, 24)
_, err = newPacketFromBytes(b)
if err != nil {
t.Errorf("newPacketFromBytes error")
}
}
func TestNewPacket(t *testing.T) {
_, err := newPacket()
if err != nil {
t.Errorf("newPacket error")
}
}
func TestPacketAll(t *testing.T) {
p, err := newPacket()
if err != nil {
t.Errorf("newPacket error")
}
p.addAttribute(*newChangeReqAttribute(true, true))
p.addAttribute(*newSoftwareAttribute("aaa"))
p.addAttribute(*newFingerprintAttribute(p))
pkt, err := newPacketFromBytes(p.bytes())
if err != nil {
t.Errorf("newPacketFromBytes error")
}
if pkt.types != 0 {
t.Errorf("newPacketFromBytes error")
}
if pkt.length < 24 {
t.Errorf("newPacketFromBytes error")
}
}

View File

@@ -26,11 +26,12 @@ type response struct {
serverAddr *Host // the address received packet
changedAddr *Host // parsed from packet
mappedAddr *Host // parsed from packet, external addr of client NAT
otherAddr *Host // parsed from packet, to replace changedAddr in RFC 5780
identical bool // if mappedAddr is in local addr list
}
func newResponse(pkt *packet, conn net.PacketConn) *response {
resp := &response{pkt, nil, nil, nil, false}
resp := &response{pkt, nil, nil, nil, nil, false}
if pkt == nil {
return resp
}
@@ -52,6 +53,12 @@ func newResponse(pkt *packet, conn net.PacketConn) *response {
changedAddrHost := newHostFromStr(changedAddr.String())
resp.changedAddr = changedAddrHost
}
// compute otherAddr
otherAddr := pkt.getOtherAddr()
if otherAddr != nil {
otherAddrHost := newHostFromStr(otherAddr.String())
resp.otherAddr = otherAddrHost
}
return resp
}
@@ -61,10 +68,11 @@ func (r *response) String() string {
if r == nil {
return "Nil"
}
return fmt.Sprintf("{packet nil: %v, local: %v, remote: %v, changed: %v, identical: %v}",
return fmt.Sprintf("{packet nil: %v, local: %v, remote: %v, changed: %v, other: %v, identical: %v}",
r.packet == nil,
r.mappedAddr,
r.serverAddr,
r.changedAddr,
r.otherAddr,
r.identical)
}

View File

@@ -1,69 +0,0 @@
// Copyright 2015, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Cong Ding <dinggnu@gmail.com>
package stun
import (
"testing"
)
func TestPadding(t *testing.T) {
b := []byte{1, 2}
expected := []byte{1, 2, 0, 0}
result := padding(b)
if len(result) != len(expected) {
t.Errorf("Padding error: result size wrong.\n")
}
for i := range expected {
if expected[i] != result[i] {
t.Errorf("Padding error: data wrong in bit %d.\n", i)
}
}
}
func TestAlign(t *testing.T) {
d := make(map[uint16]uint16)
d[1] = 4
d[4] = 4
d[5] = 8
d[6] = 8
d[7] = 8
d[8] = 8
d[65528] = 65528
d[65529] = 65532
d[65531] = 65532
d[65532] = 65532
for k, v := range d {
if align(k) != v {
t.Errorf("Align error: expected %d, get %d", align(k), v)
}
}
}
func TestIsLocalAddress(t *testing.T) {
if !isLocalAddress(":1234", "127.0.0.1:8888") {
t.Errorf("isLocal error")
}
if !isLocalAddress("192.168.0.1:1234", "192.168.0.1:8888") {
t.Errorf("isLocal error")
}
if !isLocalAddress("8.8.8.8:1234", "8.8.8.8:8888") {
t.Errorf("isLocal error")
}
if isLocalAddress(":1234", "8.8.8.8:8888") {
t.Errorf("isLocal error")
}
}

View File

@@ -10,11 +10,10 @@ import (
)
const (
mod = 65521
Mod = 65521
Size = 4
)
const Size = 4
type digest struct {
a, b uint32
@@ -29,9 +28,9 @@ type digest struct {
// Reset resets the Hash to its initial state.
func (d *digest) Reset() {
d.window = d.window[:0] // Reset the size but don't reallocate
d.a = 1
d.b = 0
d.window = d.window[:0]
d.oldest = 0
}
@@ -40,7 +39,13 @@ func (d *digest) Reset() {
// only used to determine which is the oldest element (leaving the
// window). The calls to Roll() do not recompute the whole checksum.
func New() rollinghash.Hash32 {
return &digest{a: 1, b: 0, window: nil, oldest: 0, vanilla: vanilla.New()}
return &digest{
a: 1,
b: 0,
window: make([]byte, 0),
oldest: 0,
vanilla: vanilla.New(),
}
}
// Size returns the number of bytes Sum will return.
@@ -70,7 +75,7 @@ func (d *digest) Write(p []byte) (int, error) {
d.vanilla.Write(p)
s := d.vanilla.Sum32()
d.a, d.b = s&0xffff, s>>16
d.n = uint32(len(p)) % mod
d.n = uint32(len(p)) % Mod
return len(d.window), nil
}
@@ -101,6 +106,6 @@ func (d *digest) Roll(b byte) {
}
// compute
d.a = (d.a + mod + enter - leave) % mod
d.b = (d.b + (d.n*leave/mod+1)*mod + d.a - (d.n * leave) - 1) % mod
d.a = (d.a + Mod + enter - leave) % Mod
d.b = (d.b + (d.n*leave/Mod+1)*Mod + d.a - (d.n * leave) - 1) % Mod
}

View File

@@ -1,12 +1,12 @@
// Package rollinghash/buzhash implements buzhash as described by
// https://en.wikipedia.org/wiki/Rolling_hash#Cyclic_polynomial
package buzhash
package buzhash32
import rollinghash "github.com/chmduquesne/rollinghash"
// 256 random integers generated with a dummy python script
var bytehash = [256]uint32{
var DefaultHash = [256]uint32{
0xa5659a00, 0x2dbfda02, 0xac29a407, 0xce942c08, 0x48513609,
0x325f158, 0xb54e5e13, 0xa9063618, 0xa5793419, 0x554b081a,
0xe5643dac, 0xfb50e41c, 0x2b31661d, 0x335da61f, 0xe702f7b0,
@@ -74,17 +74,28 @@ type digest struct {
// is indicated by d.oldest
window []byte
oldest int
bytehash [256]uint32
}
// Reset resets the Hash to its initial state.
func (d *digest) Reset() {
d.window = nil
d.window = d.window[:0]
d.oldest = 0
d.sum = 0
}
func New() rollinghash.Hash32 {
return &digest{sum: 0, window: nil, oldest: 0}
return NewFromUint32Array(DefaultHash)
}
// NewFromUint32Array returns a buzhash based on the provided table uint32 values.
func NewFromUint32Array(b [256]uint32) rollinghash.Hash32 {
return &digest{
sum: 0,
window: make([]byte, 0),
oldest: 0,
bytehash: b,
}
}
// Size returns the number of bytes Sum will return.
@@ -99,13 +110,19 @@ func (d *digest) BlockSize() int { return 1 }
// Write (via the embedded io.Writer interface) adds more data to the
// running hash. It never returns an error.
func (d *digest) Write(data []byte) (int, error) {
// Copy the window
// Copy the window, avoiding allocations where possible
if len(d.window) != len(data) {
if cap(d.window) >= len(data) {
d.window = d.window[:len(data)]
} else {
d.window = make([]byte, len(data))
}
}
copy(d.window, data)
for _, c := range d.window {
d.sum = d.sum<<1 | d.sum>>31
d.sum ^= bytehash[int(c)]
d.sum ^= d.bytehash[int(c)]
}
d.nRotate = uint(len(d.window)) % 32
d.nRotateComplement = 32 - d.nRotate
@@ -129,8 +146,8 @@ func (d *digest) Roll(c byte) {
d.window[0] = c
}
// extract the entering/leaving bytes and update the circular buffer.
hn := bytehash[int(c)]
h0 := bytehash[int(d.window[d.oldest])]
hn := d.bytehash[int(c)]
h0 := d.bytehash[int(d.window[d.oldest])]
d.window[d.oldest] = c
l := len(d.window)

View File

@@ -0,0 +1,194 @@
// Package rollinghash/buzhash implements buzhash as described by
// https://en.wikipedia.org/wiki/Rolling_hash#Cyclic_polynomial
package buzhash64
import rollinghash "github.com/chmduquesne/rollinghash"
// 256 random integers generated with a dummy python script
var DefaultHash = [256]uint64{
0xd6923700885676e1, 0x2ef758a165917c6c, 0xcac8db9a800db08f,
0x91dfa96019476e5f, 0x61ad4b5c6ec62e4b, 0xbabfc786038a37cb,
0xb68fe9816c09bb98, 0x6dae71ffcf505baf, 0x8f1d5ac180423f59,
0x2ddcaf458c114dae, 0x2975abd372acbb39, 0x620f80a1e7fb8ca0,
0xf8d9b75b40d1fdda, 0x81bff1a297143fab, 0x81935f4d4c31ae6e,
0xf4e0765a732a3a36, 0x0cded3fd708f0f14, 0xa89cb64087b25da9,
0xa69372234eb0602d, 0x773a079265484e2d, 0x8dbc0985c9c4e1cb,
0x000a09a5bc2c80b0, 0xdcaa87a327cead66, 0xd26eaa01fb42ef69,
0x34411456e2c244d7, 0x1082e6fb20af4bea, 0x1e00897e330f3832,
0x4253bef8099f370d, 0x890ce98ec0e8a69c, 0x89eb60e611308754,
0xb39c22caeb5444f1, 0x3e841276d561b022, 0x45292a4e1aaeb117,
0x1a4b1f1d7aeb46d1, 0x7016fc7d7b3114a6, 0x4fc9ea1dfd505a34,
0x97b6013b3739d65e, 0x7fcc6abfae8eb598, 0xff8ec196383c66f2,
0x87ca90161ecaf261, 0xc27ac70e06c9caa3, 0x42c4d7617c362ede,
0xb38656002f3984f0, 0x0520f83a5be24d68, 0x097cdf0f89aa5ad6,
0xcc2c65d8ab0e1e32, 0x8c8ebfd12b2c4fa9, 0x9e99c42db2e8be1d,
0x7bcef376a9003964, 0xbd9bc65dbfebce71, 0xd47a52cea9f0bc02,
0xeadb465977d2d8ca, 0x43065df5caca1a4b, 0x82f5ae94dd2cc349,
0xc4e362ab8614dd84, 0xc8922bf4a4bebf05, 0xb1719f57f9a1ed23,
0xe93a41737e8094ac, 0x33e611a02d4abc93, 0x1dcdb2d07ea310bc,
0xf7a85d96655b03ef, 0x60aafabd410c3180, 0x18c401b08a67ffeb,
0xc1eed3417948c90f, 0x525bfe6ad095d998, 0x2a97938c7fd244c2,
0xbb75ef8569ba728c, 0x53f47ee01b7d1915, 0x51025252faf2890e,
0xf6bd601ee7ad2608, 0x06a07a64f7afbffa, 0x224f41d09b13aed5,
0x9f80d30ece1bcd5c, 0x6ce1076c6780de0c, 0xfd123415c8262763,
0x0d5a643d04d9f438, 0xb92e476b8a36d170, 0x0f533c6c9f196cce,
0x0071ebbeb03d43af, 0x00dcbdee475f482d, 0x3339362a5b7c099c,
0x2f957910672cf39e, 0xd69554bbea71bb60, 0x635dd0f5801c9d13,
0x9832470506cba5cd, 0x77625064508cebba, 0xf428e6bfb38a5d01,
0x4a086e0cf23ab715, 0xb958fe962ca69576, 0x5d0ab146601ee29f,
0x90f0042e06fcc096, 0xba69eaa94dd5cbcc, 0xa821915b9a5fa628,
0xea4f4c03801babed, 0xbc7d5f845d913103, 0xe3cc105d6e4a11ea,
0x251f29b1422b1af5, 0xd700ffdb510d7634, 0x3002ebfda5cc4592,
0xf5614fc379a46223, 0x02cb3e88a92ab123, 0x4dab9392f9075ca5,
0xc8d8c5b39eb3e593, 0x7d6545c168d526df, 0x3cd78f7794445ee4,
0x24e2a4f47772f09a, 0x43be5ca35c81d4ec, 0x77583ba052e5b605,
0x92e07779ea9ccd7f, 0xb9dc8617c0a14ea8, 0x8a2821cb56440f77,
0x15f29e095f8b279e, 0x75c12968e423728c, 0x98cfdf60152b8d2f,
0x3b5a8db5cf80bd68, 0x2356e64e821e3ac4, 0x320b7aef2daff0d4,
0xbae4290e875658bf, 0x3b569a663e0b2445, 0xc494ce552c404288,
0x37a905ddeb550d88, 0x2333bcdc81c0c5c3, 0x8d2682d13259af0c,
0x5ad34026f7e9b8f4, 0x081970325f7f949d, 0xbcf17bf08e61ef19,
0xb3e5da3782fd7f03, 0x8ed53c8ec27635e1, 0x79fca624a1e73b7c,
0xdc9bdb3be0b69b20, 0xc119a348042544cd, 0x1c2408e49ed2a747,
0xe85f0237669d180d, 0x4508bcebda7465f9, 0x5af245c13d3a8ef7,
0xbb8bb6b61f021ed0, 0x48eaa45234935f75, 0x2f78f8fb1695eb65,
0x5dd1e1c8c20a1b76, 0x2f74a22a3159ec45, 0xc64f9c864dfb98cf,
0xf928618091913d32, 0xec08db6828a11873, 0x029ba990fa5cdba6,
0x94b870390499d9ba, 0x1086685fce933b2c, 0x6065be1f390c003a,
0x0f46e9a9d5197803, 0x42833f7327727669, 0xdda6c27eb0d682b3,
0x5ec3a67f39a77d05, 0x818f5646400a80ec, 0xe45c502c1b655c1b,
0xd56ddb4fddd63c56, 0x7ebc81bd9fd90fd1, 0x4f6c111625fb5c8e,
0x6c0fc5f0487dc6ee, 0xc57a12a7159119ed, 0x526bc3b3aadd9dd6,
0xe89f8367962fe1ea, 0x72bac3c1c99d1845, 0x6f56a75582ae96b9,
0x7d23f484a9a317f1, 0xe876956fd23c9f95, 0xdd6411629a0dab0a,
0x827046f4383dad03, 0x36aa4c0e807f9a6d, 0xcfe6ae3f86224a12,
0x84802ff4baf0e073, 0x19d786fe8a6eecd6, 0x38e9f4a7a4ce611a,
0x5442a62e65063565, 0x6a6780a6d0257b82, 0x39af9a8cf5786bd7,
0xe65d071b8fb1c8ee, 0xa63ebe71ad620e4f, 0xdfaaadf4584a0b68,
0x7bb8f20bd9681981, 0xbfa8bbaae1c5db8b, 0xae3a8b06f286932a,
0xe92a89eebe1f3292, 0xf11e1c10444edbd2, 0xaf8308bd4915c7f3,
0x8a1338317833acdc, 0xcec67d8359c7f0e8, 0x3f66a4906e23838a,
0x9e959f9b1c22fef3, 0x8b5404e71735a246, 0xcbddfc7a87347d03,
0x7a0d9bd544622f25, 0x3a78e12aab2f532f, 0xddf89b2aecd51922,
0x38f7465f6d416db4, 0x4349369edbf8ea2a, 0x5e4d38719ad9d621,
0x0ec281878dddca6a, 0x1c92cae74d6b897a, 0xa0c7c7149a8a76b3,
0xc469dca35bf1cb2a, 0x6a902e29fcf0ecd4, 0x8c455620d8f5df32,
0x0b435e9d1c207663, 0x51299e4c5ccbfbd2, 0x365add776bcad536,
0x957aa2746c2bd41e, 0x414ec15efe36e3a1, 0x6faed19dc4940f61,
0x6766d7072a6e1d87, 0x3c01b82ebdff7a2d, 0xbbbe879684ec244c,
0xa425c502184dc5b4, 0x02d77f005bb369ad, 0xb56546c281f8c88f,
0xb49a866ea16fc9e9, 0x93ee62b3965991ec, 0xf03d0958eb9664a9,
0x7e57cce4c6c8d5ab, 0x6ae6f4180ea9c5b1, 0xc45fdb113dfba663,
0x7892fabea1c2d876, 0x7b39106ce2f6d405, 0x12332253ddcff808,
0x877af9766d5147c4, 0xbbfe3ac2eb6e9d3f, 0xd298d13ac6c3c8c4,
0x142bc26ad3606528, 0xb0665de1231f2938, 0xf68498ac39f406ec,
0xc68379a33b570cfe, 0xb43cfe7fcd5d6688, 0x0e18e07f10ee779c,
0xa021ffa7e745086d, 0xa113db9a2c6bdb43, 0xa00e360382ecd221,
0x192dc98cbd494a06, 0xb0c9f52cf0252d86, 0x3efb668bcba50726,
0x114c30f72555d676, 0x99259c3011e85910, 0x5e6c7d80d32133ec,
0xfa445c39db50cb51, 0x14f1d142aac12947, 0x04dcb1a831c0e97a,
0x3102eda0466cb1d7, 0xc57ea8effb8c20f5, 0xa3641775b56361af,
0xaf9608c03cc46398, 0x023b9055ff80b8dc, 0x91965be76eddb8f0,
0xdcdffd182d67712f, 0xe8bf232ef77feef7, 0x0cc8d45930eb0846,
0xef2d62d35924c29a, 0x8a68c569490911e2, 0xc44a865ef922d723,
0xc942fc5e5c343766,
}
// The size of the checksum.
const Size = 8
// digest represents the partial evaluation of a checksum.
type digest struct {
sum uint64
nRotate uint
nRotateComplement uint // redundant, but pre-computed to spare an operation
// window is treated like a circular buffer, where the oldest element
// is indicated by d.oldest
window []byte
oldest int
bytehash [256]uint64
}
// Reset resets the Hash to its initial state.
func (d *digest) Reset() {
d.window = d.window[:0]
d.oldest = 0
d.sum = 0
}
func New() rollinghash.Hash64 {
return NewFromUint64Array(DefaultHash)
}
// NewFromUint32Array returns a buzhash based on the provided table uint32 values.
func NewFromUint64Array(b [256]uint64) rollinghash.Hash64 {
return &digest{
sum: 0,
window: make([]byte, 0),
oldest: 0,
bytehash: b,
}
}
// Size returns the number of bytes Sum will return.
func (d *digest) Size() int { return Size }
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all
// writes are a multiple of the block size.
func (d *digest) BlockSize() int { return 1 }
// Write (via the embedded io.Writer interface) adds more data to the
// running hash. It never returns an error.
func (d *digest) Write(data []byte) (int, error) {
// Copy the window, avoiding allocations where possible
if len(d.window) != len(data) {
if cap(d.window) >= len(data) {
d.window = d.window[:len(data)]
} else {
d.window = make([]byte, len(data))
}
}
copy(d.window, data)
for _, c := range d.window {
d.sum = d.sum<<1 | d.sum>>63
d.sum ^= d.bytehash[int(c)]
}
d.nRotate = uint(len(d.window)) % 64
d.nRotateComplement = 64 - d.nRotate
return len(d.window), nil
}
func (d *digest) Sum64() uint64 {
return d.sum
}
func (d *digest) Sum(b []byte) []byte {
v := d.Sum64()
return append(b, byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}
// Roll updates the checksum of the window from the leaving byte and the
// entering byte.
func (d *digest) Roll(c byte) {
if len(d.window) == 0 {
d.window = make([]byte, 1)
d.window[0] = c
}
// extract the entering/leaving bytes and update the circular buffer.
hn := d.bytehash[int(c)]
h0 := d.bytehash[int(d.window[d.oldest])]
d.window[d.oldest] = c
l := len(d.window)
d.oldest += 1
if d.oldest >= l {
d.oldest = 0
}
d.sum = (d.sum<<1 | d.sum>>63) ^ (h0<<d.nRotate | h0>>d.nRotateComplement) ^ hn
}

29
vendor/github.com/cznic/b/btree.go generated vendored
View File

@@ -826,13 +826,7 @@ func (e *Enumerator) Next() (k interface{} /*K*/, v interface{} /*V*/, err error
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.next(); err != nil {
return
}
}
f, _ := e.t.Seek(e.k)
*e = *f
f.Close()
}
@@ -849,7 +843,7 @@ func (e *Enumerator) Next() (k interface{} /*K*/, v interface{} /*V*/, err error
i := e.q.d[e.i]
k, v = i.k, i.v
e.k, e.hit = k, false
e.k, e.hit = k, true
e.next()
return
}
@@ -880,13 +874,7 @@ func (e *Enumerator) Prev() (k interface{} /*K*/, v interface{} /*V*/, err error
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.prev(); err != nil {
return
}
}
f, _ := e.t.Seek(e.k)
*e = *f
f.Close()
}
@@ -895,15 +883,22 @@ func (e *Enumerator) Prev() (k interface{} /*K*/, v interface{} /*V*/, err error
return
}
if !e.hit {
// move to previous because Seek overshoots if there's no hit
if err = e.prev(); err != nil {
return
}
}
if e.i >= e.q.c {
if err = e.next(); err != nil {
if err = e.prev(); err != nil {
return
}
}
i := e.q.d[e.i]
k, v = i.k, i.v
e.k, e.hit = k, false
e.k, e.hit = k, true
e.prev()
return
}

391
vendor/github.com/cznic/bufs/bufs.go generated vendored
View File

@@ -1,391 +0,0 @@
// Copyright 2014 The bufs Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bufs implements a simple buffer cache.
//
// The intended use scheme is like:
//
// type Foo struct {
// buffers bufs.Buffers
// ...
// }
//
// // Bar can call Qux, but not the other way around (in this example).
// const maxFooDepth = 2
//
// func NewFoo() *Foo {
// return &Foo{buffers: bufs.New(maxFooDepth), ...}
// }
//
// func (f *Foo) Bar(n int) {
// buf := f.buffers.Alloc(n) // needed locally for computation and/or I/O
// defer f.buffers.Free()
// ...
// f.Qux(whatever)
// }
//
// func (f *Foo) Qux(n int) {
// buf := f.buffers.Alloc(n) // needed locally for computation and/or I/O
// defer f.buffers.Free()
// ...
// }
//
// The whole idea behind 'bufs' is that when calling e.g. Foo.Bar N times, then
// normally, without using 'bufs', there will be 2*N (in this example) []byte
// buffers allocated. While using 'bufs', only 2 buffers (in this example)
// will ever be created. For large N it can be a substantial difference.
//
// It's not a good idea to use Buffers to cache too big buffers. The cost of
// having a cached buffer is that the buffer is naturally not eligible for
// garbage collection. Of course, that holds only while the Foo instance is
// reachable, in the above example.
//
// The buffer count limit is intentionally "hard" (read panicking), although
// configurable in New(). The rationale is to prevent recursive calls, using
// Alloc, to cause excessive, "static" memory consumption. Tune the limit
// carefully or do not use Buffers from within [mutually] recursive functions
// where the nesting depth is not realistically bounded to some rather small
// number.
//
// Buffers cannot guarantee improvements to you program performance. There may
// be a gain in case where they fit well. Firm grasp on what your code is
// actually doing, when and in what order is essential to proper use of
// Buffers. It's _highly_ recommended to first do profiling and memory
// profiling before even thinking about using 'bufs'. The real world example,
// and cause for this package, was a first correct, yet no optimizations done
// version of a program; producing few MB of useful data while allocating 20+GB
// of memory. Of course the garbage collector properly kicked in, yet the
// memory abuse caused ~80+% of run time to be spent memory management. The
// program _was_ expected to be slow in its still development phase, but the
// bottleneck was guessed to be in I/O. Actually the hard disk was waiting for
// the billions bytes being allocated and zeroed. Garbage collect on low
// memory, rinse and repeat.
//
// In the provided tests, TestFoo and TestFooBufs do the same simulated work,
// except the later uses Buffers while the former does not. Suggested test runs
// which show the differences:
//
// $ go test -bench . -benchmem
//
// or
//
// $ go test -c
// $ ./bufs.test -test.v -test.run Foo -test.memprofile mem.out -test.memprofilerate 1
// $ go tool pprof bufs.test mem.out --alloc_space --nodefraction 0.0001 --edgefraction 0 -web
// $ # Note: Foo vs FooBufs allocated memory is in hundreds of MBs vs 8 kB.
//
// or
//
// $ make demo # same as all of the above
//
//
// NOTE: Alloc/Free calls must be properly nested in the same way as in for
// example BeginTransaction/EndTransaction pairs. If your code can panic then
// the pairing should be enforced by deferred calls.
//
// NOTE: Buffers objects do not allocate any space until requested by Alloc,
// the mechanism works on demand only.
//
// FAQ: Why the 'bufs' package name?
//
// Package name 'bufs' was intentionally chosen instead of the perhaps more
// conventional 'buf'. There are already too many 'buf' named things in the
// code out there and that'll be a source of a lot of trouble. It's a bit
// similar situation as in the case of package "strings" (not "string").
package bufs
import (
"errors"
"sort"
"sync"
)
// Buffers type represents a buffer ([]byte) cache.
//
// NOTE: Do not modify Buffers directly, use only its methods. Do not create
// additional values (copies) of Buffers, that'll break its functionality. Use
// a pointer instead to refer to a single instance from different
// places/scopes.
type Buffers [][]byte
// New returns a newly created instance of Buffers with a maximum capacity of n
// buffers.
//
// NOTE: 'bufs.New(n)' is the same as 'make(bufs.Buffers, n)'.
func New(n int) Buffers {
return make(Buffers, n)
}
// Alloc will return a buffer such that len(r) == n. It will firstly try to
// find an existing and unused buffer of big enough size. Only when there is no
// such, then one of the buffer slots is reallocated to a bigger size.
//
// It's okay to use append with buffers returned by Alloc. But it can cause
// allocation in that case and will again be producing load for the garbage
// collector. The best use of Alloc is for I/O buffers where the needed size of
// the buffer is figured out at some point of the code path in a 'final size'
// sense. Another real world example are compression/decompression buffers.
//
// NOTE: The buffer returned by Alloc _is not_ zeroed. That's okay for e.g.
// passing a buffer to io.Reader. If you need a zeroed buffer use Calloc.
//
// NOTE: Buffers returned from Alloc _must not_ be exposed/returned to your
// clients. Those buffers are intended to be used strictly internally, within
// the methods of some "object".
//
// NOTE: Alloc will panic if there are no buffers (buffer slots) left.
func (p *Buffers) Alloc(n int) (r []byte) {
b := *p
if len(b) == 0 {
panic(errors.New("Buffers.Alloc: out of buffers"))
}
biggest, best, biggestI, bestI := -1, -1, -1, -1
for i, v := range b {
//ln := len(v)
// The above was correct, buts it's just confusing. It worked
// because not the buffers, but slices of them are returned in
// the 'if best >= n' code path.
ln := cap(v)
if ln >= biggest {
biggest, biggestI = ln, i
}
if ln >= n && (bestI < 0 || best > ln) {
best, bestI = ln, i
if ln == n {
break
}
}
}
last := len(b) - 1
if best >= n {
r = b[bestI]
b[last], b[bestI] = b[bestI], b[last]
*p = b[:last]
return r[:n]
}
r = make([]byte, n, overCommit(n))
b[biggestI] = r
b[last], b[biggestI] = b[biggestI], b[last]
*p = b[:last]
return
}
// Calloc will acquire a buffer using Alloc and then clears it to zeros. The
// zeroing goes up to n, not cap(r).
func (p *Buffers) Calloc(n int) (r []byte) {
r = p.Alloc(n)
for i := range r {
r[i] = 0
}
return
}
// Free makes the lastly allocated by Alloc buffer free (available) again for
// Alloc.
//
// NOTE: Improper Free invocations, like in the sequence {New, Alloc, Free,
// Free}, will panic.
func (p *Buffers) Free() {
b := *p
b = b[:len(b)+1]
*p = b
}
// Stats reports memory consumed by Buffers, without accounting for some
// (smallish) additional overhead.
func (p *Buffers) Stats() (bytes int) {
b := *p
b = b[:cap(b)]
for _, v := range b {
bytes += cap(v)
}
return
}
// Cache caches buffers ([]byte). A zero value of Cache is ready for use.
//
// NOTE: Do not modify a Cache directly, use only its methods. Do not create
// additional values (copies) of a Cache, that'll break its functionality. Use
// a pointer instead to refer to a single instance from different
// places/scopes.
type Cache [][]byte
// Get returns a buffer ([]byte) of length n. If no such buffer is cached then
// a biggest cached buffer is resized to have length n and returned. If there
// are no cached items at all, Get returns a newly allocated buffer.
//
// In other words the cache policy is:
//
// - If the cache is empty, the buffer must be newly created and returned.
// Cache remains empty.
//
// - If a buffer of sufficient size is found in the cache, remove it from the
// cache and return it.
//
// - Otherwise the cache is non empty, but no cached buffer is big enough.
// Enlarge the biggest cached buffer, remove it from the cache and return it.
// This provide cached buffers size adjustment based on demand.
//
// In short, if the cache is not empty, Get guarantees to make it always one
// item less. This rules prevent uncontrolled cache grow in some scenarios.
// The older policy was not preventing that. Another advantage is better cached
// buffers sizes "auto tuning", although not in every possible use case.
//
// NOTE: The buffer returned by Get _is not guaranteed_ to be zeroed. That's
// okay for e.g. passing a buffer to io.Reader. If you need a zeroed buffer
// use Cget.
func (c *Cache) Get(n int) []byte {
r, _ := c.get(n)
return r
}
func (c *Cache) get(n int) (r []byte, isZeroed bool) {
s := *c
lens := len(s)
if lens == 0 {
r, isZeroed = make([]byte, n, overCommit(n)), true
return
}
i := sort.Search(lens, func(x int) bool { return len(s[x]) >= n })
if i == lens {
i--
s[i] = make([]byte, n, overCommit(n))
}
r = s[i][:n]
copy(s[i:], s[i+1:])
s[lens-1] = nil
s = s[:lens-1]
*c = s
return r, false
}
// Cget will acquire a buffer using Get and then clears it to zeros. The
// zeroing goes up to n, not cap(r).
func (c *Cache) Cget(n int) (r []byte) {
r, ok := c.get(n)
if ok {
return
}
for i := range r {
r[i] = 0
}
return
}
// Put caches b for possible later reuse (via Get). No other references to b's
// backing array may exist. Otherwise a big mess is sooner or later inevitable.
func (c *Cache) Put(b []byte) {
b = b[:cap(b)]
lenb := len(b)
if lenb == 0 {
return
}
s := *c
lens := len(s)
i := sort.Search(lens, func(x int) bool { return len(s[x]) >= lenb })
s = append(s, nil)
copy(s[i+1:], s[i:])
s[i] = b
*c = s
return
}
// Stats reports memory consumed by a Cache, without accounting for some
// (smallish) additional overhead. 'n' is the number of cached buffers, bytes
// is their combined capacity.
func (c Cache) Stats() (n, bytes int) {
n = len(c)
for _, v := range c {
bytes += cap(v)
}
return
}
// CCache is a Cache which is safe for concurrent use by multiple goroutines.
type CCache struct {
c Cache
mu sync.Mutex
}
// Get returns a buffer ([]byte) of length n. If no such buffer is cached then
// a biggest cached buffer is resized to have length n and returned. If there
// are no cached items at all, Get returns a newly allocated buffer.
//
// In other words the cache policy is:
//
// - If the cache is empty, the buffer must be newly created and returned.
// Cache remains empty.
//
// - If a buffer of sufficient size is found in the cache, remove it from the
// cache and return it.
//
// - Otherwise the cache is non empty, but no cached buffer is big enough.
// Enlarge the biggest cached buffer, remove it from the cache and return it.
// This provide cached buffers size adjustment based on demand.
//
// In short, if the cache is not empty, Get guarantees to make it always one
// item less. This rules prevent uncontrolled cache grow in some scenarios.
// The older policy was not preventing that. Another advantage is better cached
// buffers sizes "auto tuning", although not in every possible use case.
//
// NOTE: The buffer returned by Get _is not guaranteed_ to be zeroed. That's
// okay for e.g. passing a buffer to io.Reader. If you need a zeroed buffer
// use Cget.
func (c *CCache) Get(n int) []byte {
c.mu.Lock()
r, _ := c.c.get(n)
c.mu.Unlock()
return r
}
// Cget will acquire a buffer using Get and then clears it to zeros. The
// zeroing goes up to n, not cap(r).
func (c *CCache) Cget(n int) (r []byte) {
c.mu.Lock()
r = c.c.Cget(n)
c.mu.Unlock()
return
}
// Put caches b for possible later reuse (via Get). No other references to b's
// backing array may exist. Otherwise a big mess is sooner or later inevitable.
func (c *CCache) Put(b []byte) {
c.mu.Lock()
c.c.Put(b)
c.mu.Unlock()
}
// Stats reports memory consumed by a Cache, without accounting for some
// (smallish) additional overhead. 'n' is the number of cached buffers, bytes
// is their combined capacity.
func (c *CCache) Stats() (n, bytes int) {
c.mu.Lock()
n, bytes = c.c.Stats()
c.mu.Unlock()
return
}
// GCache is a ready to use global instance of a CCache.
var GCache CCache
func overCommit(n int) int {
switch {
case n < 8:
return 8
case n < 1e5:
return 2 * n
case n < 1e6:
return 3 * n / 2
default:
return n
}
}

View File

@@ -9,6 +9,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Not supported on ARM.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !arm
package fileutil
import (
@@ -9,6 +11,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Not supported on OSX.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -11,6 +11,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Unimplemented on FreeBSD.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -15,6 +15,8 @@ import (
"syscall"
)
const hasPunchHole = true
func n(s []byte) byte {
for i, c := range s {
if c < '0' || c > '9' {

View File

@@ -11,6 +11,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Similar to FreeBSD, this is
// unimplemented.

View File

@@ -9,6 +9,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Similar to FreeBSD, this is
// unimplemented.

View File

@@ -9,6 +9,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Unimplemented on Plan 9.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -11,6 +11,8 @@ import (
"os"
)
const hasPunchHole = false
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Not supported on Solaris.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -12,6 +12,8 @@ import (
"unsafe"
)
const hasPunchHole = true
// PunchHole deallocates space inside a file in the byte range starting at
// offset and continuing for len bytes. Not supported on Windows.
func PunchHole(f *os.File, off, len int64) error {

View File

@@ -34,6 +34,7 @@ package buffer
import (
"github.com/cznic/internal/slice"
"io"
)
// CGet returns a pointer to a byte slice of len size. The pointed to byte
@@ -53,3 +54,93 @@ func Get(size int) *[]byte { return slice.Bytes.Get(size).(*[]byte) }
//
// Put is safe for concurrent use by multiple goroutines.
func Put(p *[]byte) { slice.Bytes.Put(p) }
// Bytes is similar to bytes.Buffer but may generate less garbage when properly
// Closed. Zero value is ready to use.
type Bytes struct {
p *[]byte
}
// Bytes return the content of b. The result is R/O.
func (b *Bytes) Bytes() []byte {
if b.p != nil {
return *b.p
}
return nil
}
// Close will recycle the underlying storage, if any. After Close, b is again
// the zero value.
func (b *Bytes) Close() error {
if b.p != nil {
Put(b.p)
b.p = nil
}
return nil
}
// Len returns the size of content in b.
func (b *Bytes) Len() int {
if b.p != nil {
return len(*b.p)
}
return 0
}
// Reset discard the content of Bytes while keeping the internal storage, if any.
func (b *Bytes) Reset() {
if b.p != nil {
*b.p = (*b.p)[:0]
}
}
// Write writes p into b and returns (len(p), nil).
func (b *Bytes) Write(p []byte) (int, error) {
n := b.Len()
b.grow(n + len(p))
copy((*b.p)[n:], p)
return len(p), nil
}
// WriteByte writes p into b and returns nil.
func (b *Bytes) WriteByte(p byte) error {
n := b.Len()
b.grow(n + 1)
(*b.p)[n] = p
return nil
}
// WriteTo writes b's content to w and returns the number of bytes written to w
// and an error, if any.
func (b *Bytes) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(b.Bytes())
return int64(n), err
}
// WriteString writes s to b and returns (len(s), nil).
func (b *Bytes) WriteString(s string) (int, error) {
n := b.Len()
b.grow(n + len(s))
copy((*b.p)[n:], s)
return len(s), nil
}
func (b *Bytes) grow(n int) {
if b.p != nil {
if n <= cap(*b.p) {
*b.p = (*b.p)[:n]
return
}
np := Get(2 * n)
*np = (*np)[:n]
copy(*np, *b.p)
Put(b.p)
b.p = np
return
}
b.p = Get(n)
}

110
vendor/github.com/cznic/lldb/2pc.go generated vendored
View File

@@ -73,6 +73,7 @@ const (
wpt00Header = iota
wpt00WriteData
wpt00Checkpoint
wpt00Empty
)
const (
@@ -99,10 +100,38 @@ type ACIDFiler0 struct {
bwal *bufio.Writer
data []acidWrite
newEpoch bool
peakBitFilerPages int // track maximum transaction memory
peakWal int64 // tracks WAL maximum used size
testHook bool // keeps WAL untruncated (once)
wal *os.File
walOptions walOptions
}
type walOptions struct {
headroom int64 // Minimum WAL size.
}
// WALOption amends WAL properties.
type WALOption func(*walOptions) error
// MinWAL sets the minimum size a WAL file will have. The "extra" allocated
// file space serves as a headroom. Commits that fit into the headroom should
// not fail due to 'not enough space on the volume' errors.
//
// The min parameter is first rounded-up to a non negative multiple of the size
// of the Allocator atom.
//
// Note: Setting minimum WAL size may render the DB non-recoverable when a
// crash occurs and the DB is opened in an earlier version of LLDB that does
// not support minimum WAL sizes.
func MinWAL(min int64) WALOption {
min = mathutil.MaxInt64(0, min)
if r := min % 16; r != 0 {
min += 16 - r
}
return func(o *walOptions) error {
o.headroom = min
return nil
}
}
// NewACIDFiler0 returns a newly created ACIDFiler0 with WAL in wal.
@@ -111,17 +140,24 @@ type ACIDFiler0 struct {
// granted and no recovery procedure is taken.
//
// If the WAL is of non zero size then it is checked for having a
// commited/fully finished transaction not yet been reflected in db. If such
// committed/fully finished transaction not yet been reflected in db. If such
// transaction exists it's committed to db. If the recovery process finishes
// successfully, the WAL is truncated to zero size and fsync'ed prior to return
// from NewACIDFiler0.
func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) {
// successfully, the WAL is truncated to the minimum WAL size and fsync'ed
// prior to return from NewACIDFiler0.
//
// opts allow to amend WAL properties.
func NewACIDFiler(db Filer, wal *os.File, opts ...WALOption) (r *ACIDFiler0, err error) {
fi, err := wal.Stat()
if err != nil {
return
}
r = &ACIDFiler0{wal: wal}
for _, o := range opts {
if err := o(&r.walOptions); err != nil {
return nil, err
}
}
if fi.Size() != 0 {
if err = r.recoverDb(db); err != nil {
@@ -149,15 +185,23 @@ func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) {
return
}
wfi, err := r.wal.Stat()
if err == nil {
r.peakWal = mathutil.MaxInt64(wfi.Size(), r.peakWal)
var wfi os.FileInfo
if wfi, err = r.wal.Stat(); err != nil {
return
}
r.peakWal = mathutil.MaxInt64(wfi.Size(), r.peakWal)
// Phase 1 commit complete
for _, v := range r.data {
if _, err := db.WriteAt(v.b, v.off); err != nil {
n := len(v.b)
if m := v.off + int64(n); m > sz {
if n -= int(m - sz); n <= 0 {
continue
}
}
if _, err = db.WriteAt(v.b[:n], v.off); err != nil {
return err
}
}
@@ -173,12 +217,8 @@ func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) {
// Phase 2 commit complete
if !r.testHook {
if err = r.wal.Truncate(0); err != nil {
return
}
if _, err = r.wal.Seek(0, 0); err != nil {
return
if err := r.emptyWAL(); err != nil {
return err
}
}
@@ -196,6 +236,33 @@ func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) {
return r, nil
}
func (a *ACIDFiler0) emptyWAL() error {
if err := a.wal.Truncate(a.walOptions.headroom); err != nil {
return err
}
if _, err := a.wal.Seek(0, 0); err != nil {
return err
}
if a.walOptions.headroom != 0 {
a.bwal.Reset(a.wal)
if err := (*acidWriter0)(a).writePacket([]interface{}{wpt00Empty}); err != nil {
return err
}
if err := a.bwal.Flush(); err != nil {
return err
}
if _, err := a.wal.Seek(0, 0); err != nil {
return err
}
}
return nil
}
// PeakWALSize reports the maximum size WAL has ever used.
func (a ACIDFiler0) PeakWALSize() int64 {
return a.peakWal
@@ -235,6 +302,14 @@ func (a *ACIDFiler0) recoverDb(db Filer) (err error) {
return
}
if items[0] == int64(wpt00Empty) {
if len(items) != 1 {
return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("invalid packet items %#v", items)}
}
return nil
}
if len(items) != 3 || items[0] != int64(wpt00Header) || items[1] != int64(walTypeACIDFiler0) {
return &ErrILSEQ{Type: ErrInvalidWAL, Name: a.wal.Name(), More: fmt.Sprintf("invalid packet items %#v", items)}
}
@@ -280,7 +355,8 @@ func (a *ACIDFiler0) recoverDb(db Filer) (err error) {
}
for {
k, v, err := enum.current()
var k, v []byte
k, v, err = enum.current()
if err != nil {
if fileutil.IsEOF(err) {
break
@@ -312,7 +388,7 @@ func (a *ACIDFiler0) recoverDb(db Filer) (err error) {
// Recovery complete
if err = a.wal.Truncate(0); err != nil {
if err := a.emptyWAL(); err != nil {
return err
}

View File

@@ -37,6 +37,10 @@ Packet definitions
This packet must be present only once - as the last packet of
a WAL file.
{wpt00Empty int}
The WAL size is of non-zero size due to configured headroom,
but empty otherwise.
*/
package lldb

View File

@@ -638,7 +638,7 @@ retry:
}
if e.enum.index == e.enum.p.len() && e.enum.serial == e.enum.t.serial {
if err := e.enum.next(); err != nil {
if err = e.enum.next(); err != nil {
e.err = err
return nil, nil, e.err
}
@@ -1037,7 +1037,7 @@ func (p btreeIndexPage) underflow(a btreeStore, root, iroot, parent int64, ph *i
return nil, err
}
if lc := btreeIndexPage(left).len(); lc > kIndex {
if lc := left.len(); lc > kIndex {
ppp := buffer.Get(maxBuf)
defer buffer.Put(ppp)
pp := *ppp
@@ -1049,10 +1049,10 @@ func (p btreeIndexPage) underflow(a btreeStore, root, iroot, parent int64, ph *i
p = p.setLen(pc + 1)
di, si, sz := 1+1*14, 1+0*14, (2*pc+1)*7
copy(p[di:di+sz], p[si:])
p.setChild(0, btreeIndexPage(left).child(lc))
p.setChild(0, left.child(lc))
p.setDataPage(0, btreeIndexPage(pp).dataPage(parentIndex-1))
*index++
btreeIndexPage(pp).setDataPage(parentIndex-1, btreeIndexPage(left).dataPage(lc-1))
btreeIndexPage(pp).setDataPage(parentIndex-1, left.dataPage(lc-1))
left = left.setLen(lc - 1)
if err = a.Realloc(parent, pp); err != nil {
return nil, err
@@ -1479,8 +1479,9 @@ func (p btreeDataPage) split(a btreeStore, root, ph, parent int64, parentIndex,
} else {
nr := newBTreeIndexPage(ph)
nr = nr.insert3(0, rh, rh)
nrh, err := a.Alloc(nr)
if err != nil {
var nrh int64
if nrh, err = a.Alloc(nr); err != nil {
return nil, err
}
@@ -1866,7 +1867,7 @@ func (root btree) String(a btreeStore) string {
}
}
f(int64(iroot), "")
f(iroot, "")
return strings.Join(s, "\n")
}
@@ -2074,8 +2075,9 @@ func (root btree) extract(a btreeStore, dst []byte, c func(a, b []byte) int, key
if ok {
if btreePage(p).isIndex() {
dph := btreeIndexPage(p).dataPage(index)
dp, err := a.Get(dst, dph)
if err != nil {
var dp []byte
if dp, err = a.Get(dst, dph); err != nil {
return nil, err
}
@@ -2088,7 +2090,6 @@ func (root btree) extract(a btreeStore, dst []byte, c func(a, b []byte) int, key
}
if btreeIndexPage(p).len() < kIndex && ph != iroot {
var err error
if p, err = btreeIndexPage(p).underflow(a, int64(root), iroot, parent, &ph, parentIndex, &index); err != nil {
return nil, err
}
@@ -2325,8 +2326,9 @@ func (root btree) clear2(a btreeStore, ph int64) (err error) {
case true:
ip := btreeIndexPage(p)
for i := 0; i <= ip.len(); i++ {
root.clear2(a, ip.child(i))
if err = root.clear2(a, ip.child(i)); err != nil {
return err
}
}
case false:
dp := btreeDataPage(p)

View File

@@ -45,7 +45,7 @@ type ErrPERM struct {
// Error implements the built in error type.
func (e *ErrPERM) Error() string {
return fmt.Sprintf("%s: Operation not permitted", string(e.Src))
return fmt.Sprintf("%s: Operation not permitted", e.Src)
}
// ErrTag represents an ErrILSEQ kind.

View File

@@ -287,16 +287,16 @@ Note: No Allocator method returns io.EOF.
type Allocator struct {
f Filer
flt flt
Compress bool // enables content compression
cache cache
m map[int64]*node
lru lst
mu sync.Mutex
expHit int64
expMiss int64
cacheSz int
hit uint16
miss uint16
mu sync.Mutex
Compress bool // enables content compression
}
// NewAllocator returns a new Allocator. To open an existing file, pass its
@@ -338,7 +338,7 @@ func NewAllocator(f Filer, opts *Options) (a *Allocator, err error) {
}
if _, err = f.WriteAt(b[:], 0); err != nil {
a.f.Rollback()
_ = a.f.Rollback()
return
}
@@ -704,7 +704,7 @@ reloc:
atoms := n2atoms(dlen)
switch atoms {
case 1:
switch tag := first[15]; tag {
switch tag = first[15]; tag {
default:
return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)}
case tagNotCompressed:
@@ -725,7 +725,7 @@ reloc:
return
}
switch tag := cc[0]; tag {
switch tag = cc[0]; tag {
default:
return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)}
case tagNotCompressed:
@@ -760,7 +760,7 @@ reloc:
return
}
switch tag := cc[0]; tag {
switch tag = cc[0]; tag {
default:
return nil, &ErrILSEQ{Type: ErrTailTag, Off: off, Arg: int64(tag)}
case tagNotCompressed:
@@ -866,8 +866,8 @@ retry:
}
fh, fa := handle+needAtoms, atoms-needAtoms
sz, err := a.f.Size()
if err != nil {
var sz int64
if sz, err = a.f.Size(); err != nil {
return err
}
@@ -1147,7 +1147,7 @@ func (a *Allocator) makeUsedBlock(dst []byte, b []byte) (w []byte, rqAtoms int,
n2 := len(dst)
if rqAtoms2 := n2atoms(n2); rqAtoms2 < rqAtoms { // compression saved at least a single atom
w, n, rqAtoms, cc = dst, n2, rqAtoms2, tagCompressed
w, rqAtoms, cc = dst, rqAtoms2, tagCompressed
}
}
return
@@ -1206,7 +1206,7 @@ func (a *Allocator) verifyUnused(h, totalAtoms int64, tag byte, log func(error)
}
if atoms < 2 {
err = &ErrILSEQ{Type: ErrLongFreeBlkTooShort, Off: off, Arg: int64(atoms)}
err = &ErrILSEQ{Type: ErrLongFreeBlkTooShort, Off: off, Arg: atoms}
break
}

View File

@@ -7,15 +7,7 @@
package lldb
import (
"fmt"
"github.com/cznic/mathutil"
)
func doubleTrouble(first, second error) error {
return fmt.Errorf("%q. Additionally, while attempting to recover (rollback): %q", first, second)
}
import "github.com/cznic/mathutil"
// A Filer is a []byte-like model of a file or similar entity. It may
// optionally implement support for structural transaction safety. In contrast

2
vendor/github.com/cznic/lldb/gb.go generated vendored
View File

@@ -182,7 +182,7 @@ func EncodeScalars(scalars ...interface{}) (b []byte, err error) {
n := len(x)
if n <= 17 {
b = append(b, byte(gbBytes00+n))
b = append(b, []byte(x)...)
b = append(b, x...)
break
}

View File

@@ -13,12 +13,6 @@ import (
"github.com/cznic/internal/file"
)
const (
pgBits = 16
pgSize = 1 << pgBits
pgMask = pgSize - 1
)
var _ Filer = &MemFiler{}
// MemFiler is a memory backed Filer. It implements BeginUpdate, EndUpdate and

View File

@@ -336,19 +336,18 @@ func (f *bitFiler) dumpDirty(w io.WriterAt) (nwr int, err error) {
// RollbackFiler is safe for concurrent use by multiple goroutines.
type RollbackFiler struct {
mu sync.RWMutex
inCallback bool
inCallbackMu sync.RWMutex
bitFiler *bitFiler
checkpoint func(int64) error
closed bool
f Filer
parent Filer
tlevel int // transaction nesting level, 0 == not in transaction
writerAt io.WriterAt
// afterRollback, if not nil, is called after performing Rollback
// without errros.
afterRollback func() error
tlevel int // transaction nesting level, 0 == not in transaction
closed bool
inCallback bool
}
// NewRollbackFiler returns a RollbackFiler wrapping f.

View File

@@ -149,7 +149,7 @@ func BitLenUintptr(n uintptr) int {
// PopCountByte returns population count of n (number of bits set in n).
func PopCountByte(n byte) int {
return int(popcnt[byte(n)])
return int(popcnt[n])
}
// PopCountUint16 returns population count of n (number of bits set in n).

View File

@@ -5,7 +5,9 @@
// Package mathutil provides utilities supplementing the standard 'math' and
// 'math/rand' packages.
//
// Compatibility issues
// Release history and compatibility issues
//
// 2016-10-10: New functions QuadPolyDiscriminant and QuadPolyFactors.
//
// 2013-12-13: The following functions have been REMOVED
//
@@ -89,7 +91,7 @@ func GCDUint16(a, b uint16) uint16 {
return a
}
// GCD returns the greatest common divisor of a and b.
// GCDUint32 returns the greatest common divisor of a and b.
func GCDUint32(a, b uint32) uint32 {
for b != 0 {
a, b = b, a%b
@@ -97,7 +99,7 @@ func GCDUint32(a, b uint32) uint32 {
return a
}
// GCD64 returns the greatest common divisor of a and b.
// GCDUint64 returns the greatest common divisor of a and b.
func GCDUint64(a, b uint64) uint64 {
for b != 0 {
a, b = b, a%b
@@ -257,7 +259,7 @@ func ModPowByte(b, e, m byte) byte {
return byte(r)
}
// ModPowByte computes (b^e)%m. It panics for m == 0 || b == e == 0.
// ModPowUint16 computes (b^e)%m. It panics for m == 0 || b == e == 0.
func ModPowUint16(b, e, m uint16) uint16 {
if b == 0 && e == 0 {
panic(0)
@@ -382,7 +384,7 @@ func MulUint128_64(a, b uint64) (hi, lo uint64) {
mid2 := ahi * blo
c1, lo := AddUint128_64(lo, mid1<<w)
c2, lo := AddUint128_64(lo, mid2<<w)
_, hi = AddUint128_64(ahi*bhi, mid1>>w+mid2>>w+uint64(c1+c2))
_, hi = AddUint128_64(ahi*bhi, mid1>>w+mid2>>w+c1+c2)
return
}

View File

@@ -8,14 +8,14 @@ import (
"sort"
)
// Generate the first permutation of data.
// PermutationFirst generates the first permutation of data.
func PermutationFirst(data sort.Interface) {
sort.Sort(data)
}
// Generate the next permutation of data if possible and return true.
// Return false if there is no more permutation left.
// Based on the algorithm described here:
// PermutationNext generates the next permutation of data if possible and
// return true. Return false if there is no more permutation left. Based on
// the algorithm described here:
// http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
func PermutationNext(data sort.Interface) bool {
var k, l int

111
vendor/github.com/cznic/mathutil/poly.go generated vendored Normal file
View File

@@ -0,0 +1,111 @@
// Copyright (c) 2016 The mathutil Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mathutil
import (
"fmt"
)
func abs(n int) uint64 {
if n >= 0 {
return uint64(n)
}
return uint64(-n)
}
// QuadPolyDiscriminant returns the discriminant of a quadratic polynomial in
// one variable of the form a*x^2+b*x+c with integer coefficients a, b, c, or
// an error on overflow.
//
// ds is the square of the discriminant. If |ds| is a square number, d is set
// to sqrt(|ds|), otherwise d is < 0.
func QuadPolyDiscriminant(a, b, c int) (ds, d int, _ error) {
if 2*BitLenUint64(abs(b)) > IntBits-1 ||
2+BitLenUint64(abs(a))+BitLenUint64(abs(c)) > IntBits-1 {
return 0, 0, fmt.Errorf("overflow")
}
ds = b*b - 4*a*c
s := ds
if s < 0 {
s = -s
}
d64 := SqrtUint64(uint64(s))
if d64*d64 != uint64(s) {
return ds, -1, nil
}
return ds, int(d64), nil
}
// PolyFactor describes an irreducible factor of a polynomial in one variable
// with integer coefficients P, Q of the form P*x+Q.
type PolyFactor struct {
P, Q int
}
// QuadPolyFactors returns the content and the irreducible factors of the
// primitive part of a quadratic polynomial in one variable with integer
// coefficients a, b, c of the form a*x^2+b*x+c in integers, or an error on
// overflow.
//
// If the factorization in integers does not exists, the return value is (nil,
// nil).
//
// See also:
// https://en.wikipedia.org/wiki/Factorization_of_polynomials#Primitive_part.E2.80.93content_factorization
func QuadPolyFactors(a, b, c int) (content int, primitivePart []PolyFactor, _ error) {
content = int(GCDUint64(abs(a), GCDUint64(abs(b), abs(c))))
switch {
case content == 0:
content = 1
case content > 0:
if a < 0 || a == 0 && b < 0 {
content = -content
}
}
a /= content
b /= content
c /= content
if a == 0 {
if b == 0 {
return content, []PolyFactor{{0, c}}, nil
}
if b < 0 && c < 0 {
b = -b
c = -c
}
if b < 0 {
b = -b
c = -c
}
return content, []PolyFactor{{b, c}}, nil
}
ds, d, err := QuadPolyDiscriminant(a, b, c)
if err != nil {
return 0, nil, err
}
if ds < 0 || d < 0 {
return 0, nil, nil
}
x1num := -b + d
x1denom := 2 * a
gcd := int(GCDUint64(abs(x1num), abs(x1denom)))
x1num /= gcd
x1denom /= gcd
x2num := -b - d
x2denom := 2 * a
gcd = int(GCDUint64(abs(x2num), abs(x2denom)))
x2num /= gcd
x2denom /= gcd
return content, []PolyFactor{{x1denom, -x1num}, {x2denom, -x2num}}, nil
}

View File

@@ -126,11 +126,11 @@ func builtinAvg(arg []interface{}, ctx map[interface{}]interface{}) (v interface
case complex64:
return complex64(complex128(x) / complex(float64(data.n), 0)), nil
case complex128:
return complex64(complex128(x) / complex(float64(data.n), 0)), nil
return complex64(x / complex(float64(data.n), 0)), nil
case float32:
return float32(float64(x) / float64(data.n)), nil
case float64:
return float64(x) / float64(data.n), nil
return x / float64(data.n), nil
case int8:
return int8(int64(x) / int64(data.n)), nil
case int16:
@@ -138,7 +138,7 @@ func builtinAvg(arg []interface{}, ctx map[interface{}]interface{}) (v interface
case int32:
return int32(int64(x) / int64(data.n)), nil
case int64:
return int64(int64(x) / int64(data.n)), nil
return x / int64(data.n), nil
case uint8:
return uint8(uint64(x) / data.n), nil
case uint16:
@@ -146,7 +146,7 @@ func builtinAvg(arg []interface{}, ctx map[interface{}]interface{}) (v interface
case uint32:
return uint32(uint64(x) / data.n), nil
case uint64:
return uint64(uint64(x) / data.n), nil
return x / data.n, nil
}
}
@@ -216,9 +216,9 @@ func builtinComplex(arg []interface{}, _ map[interface{}]interface{}) (v interfa
case idealUint:
return idealComplex(complex(float64(re), float64(im.(idealUint)))), nil
case float32:
return complex(float32(re), im.(float32)), nil
return complex(re, im.(float32)), nil
case float64:
return complex(float64(re), im.(float64)), nil
return complex(re, im.(float64)), nil
case int8:
return complex(float64(re), float64(im.(int8))), nil
case int16:

26
vendor/github.com/cznic/ql/coerce.go generated vendored
View File

@@ -93,13 +93,13 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
//case idealUint:
//case bool:
case complex64:
return complex64(complex(float32(x), 0))
return complex(float32(x), 0)
case complex128:
return complex128(complex(float64(x), 0))
return complex(float64(x), 0)
case float32:
return float32(float64(x))
case float64:
return float64(float64(x))
return float64(x)
//case int8:
//case int16:
//case int32:
@@ -130,9 +130,9 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
}
//case bool:
case complex64:
return complex64(complex(float32(x), 0))
return complex(float32(x), 0)
case complex128:
return complex128(complex(float64(x), 0))
return complex(float64(x), 0)
case float32:
return float32(int64(x))
case float64:
@@ -150,7 +150,7 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
return int32(int64(x))
}
case int64:
return int64(int64(x))
return int64(x)
//case string:
case uint8:
if x >= 0 && x <= math.MaxUint8 {
@@ -190,9 +190,9 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
return idealUint(int64(x))
//case bool:
case complex64:
return complex64(complex(float32(x), 0))
return complex(float32(x), 0)
case complex128:
return complex128(complex(float64(x), 0))
return complex(float64(x), 0)
case float32:
return float32(int64(x))
case float64:
@@ -204,7 +204,7 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
case int32:
return int32(int64(x))
case int64:
return int64(int64(x))
return int64(x)
//case string:
case uint8:
return uint8(int64(x))
@@ -237,9 +237,9 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
return idealUint(uint64(x))
//case bool:
case complex64:
return complex64(complex(float32(x), 0))
return complex(float32(x), 0)
case complex128:
return complex128(complex(float64(x), 0))
return complex(float64(x), 0)
case float32:
return float32(uint64(x))
case float64:
@@ -258,7 +258,7 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
}
case int64:
if x <= math.MaxInt64 {
return int64(int64(x))
return int64(x)
}
//case string:
case uint8:
@@ -274,7 +274,7 @@ func coerce1(inVal, otherVal interface{}) (coercedInVal interface{}) {
return uint32(int64(x))
}
case uint64:
return uint64(uint64(x))
return uint64(x)
case *big.Int:
return big.NewInt(0).SetUint64(uint64(x))
case *big.Rat:

34
vendor/github.com/cznic/ql/doc.go generated vendored
View File

@@ -14,8 +14,13 @@
//
// Change list
//
// 2017-01-10: Release v1.1.0 fixes some bugs and adds a configurable WAL
// headroom.
//
// https://github.com/cznic/ql/issues/140
//
// 2016-07-29: Release v1.0.6 enables alternatively using = instead of == for
// equality oparation.
// equality operation.
//
// https://github.com/cznic/ql/issues/131
//
@@ -279,18 +284,21 @@
//
// The following keywords are reserved and may not be used as identifiers.
//
// ADD COLUMN false int32 ORDER uint16
// ALTER complex128 float int64 OUTER uint32
// AND complex64 float32 int8 RIGHT uint64
// AS CREATE float64 INTO SELECT uint8
// ASC DEFAULT FROM JOIN SET UNIQUE
// BETWEEN DELETE GROUP LEFT string UPDATE
// bigint DESC IF LIMIT TABLE VALUES
// bigrat DISTINCT IN LIKE time WHERE
// blob DROP INDEX NOT true
// bool duration INSERT NULL OR
// BY EXISTS int OFFSET TRUNCATE
// byte EXPLAIN int16 ON uint
// ADD complex128 FROM LEFT string
// ALTER complex64 FULL LIKE TABLE
// AND CREATE GROUP LIMIT time
// AS DEFAULT IF NOT TRANSACTION
// ASC DELETE IN NULL true
// BEGIN DESC INDEX OFFSET TRUNCATE
// BETWEEN DISTINCT INSERT ON uint
// bigint DROP int OR uint16
// bigrat duration int16 ORDER uint32
// blob EXISTS int32 OUTER uint64
// bool EXPLAIN int64 RIGHT uint8
// BY false int8 ROLLBACK UNIQUE
// byte float INTO rune UPDATE
// COLUMN float32 IS SELECT VALUES
// COMMIT float64 JOIN SET WHERE
//
// Keywords are not case sensitive.
//

50
vendor/github.com/cznic/ql/driver.go generated vendored
View File

@@ -14,8 +14,10 @@ import (
"fmt"
"io"
"math/big"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
@@ -144,23 +146,51 @@ func (d *sqlDriver) lock() func() {
// efficient re-use.
//
// The returned connection is only used by one goroutine at a time.
//
// The name supported URL parameters:
//
// headroom Size of the WAL headroom. See https://github.com/cznic/ql/issues/140.
func (d *sqlDriver) Open(name string) (driver.Conn, error) {
if d != fileDriver && d != memDriver {
switch {
case d == fileDriver:
if !strings.Contains(name, "://") && !strings.HasPrefix(name, "file") {
name = "file://" + name
}
case d == memDriver:
if !strings.Contains(name, "://") && !strings.HasPrefix(name, "memory") {
name = "memory://" + name
}
default:
return nil, fmt.Errorf("open: unexpected/unsupported instance of driver.Driver: %p", d)
}
switch {
case d == fileDriver && strings.HasPrefix(name, "file://"):
name = name[len("file://"):]
case d == fileDriver && strings.HasPrefix(name, "memory://"):
d = memDriver
name = name[len("memory://"):]
name = filepath.ToSlash(name) // Ensure / separated URLs on Windows
uri, err := url.Parse(name)
if err != nil {
return nil, err
}
name = filepath.Clean(name)
if name == "" || name == "." || name == string(os.PathSeparator) {
switch uri.Scheme {
case "file":
// ok
case "memory":
d = memDriver
default:
return nil, fmt.Errorf("open: unexpected/unsupported scheme: %s", uri.Scheme)
}
name = filepath.Clean(filepath.Join(uri.Host, uri.Path))
if d == fileDriver && (name == "" || name == "." || name == string(os.PathSeparator)) {
return nil, fmt.Errorf("invalid DB name %q", name)
}
var headroom int64
if a := uri.Query()["headroom"]; len(a) != 0 {
if headroom, err = strconv.ParseInt(a[0], 10, 64); err != nil {
return nil, err
}
}
defer d.lock()()
db := d.dbs[name]
if db == nil {
@@ -170,7 +200,7 @@ func (d *sqlDriver) Open(name string) (driver.Conn, error) {
case true:
db0, err = OpenMem()
default:
db0, err = OpenFile(name, &Options{CanCreate: true})
db0, err = OpenFile(name, &Options{CanCreate: true, Headroom: headroom})
}
if err != nil {
return nil, err

78
vendor/github.com/cznic/ql/etc.go generated vendored
View File

@@ -145,7 +145,7 @@ func intExpr(x interface{}) (i int64, err error) {
return 0, invNegLO(x)
}
return int64(x), nil
return x, nil
case uint8:
return int64(x), nil
case uint16:
@@ -210,7 +210,7 @@ func limOffExpr(x interface{}) (i uint64, err error) {
case uint32:
return uint64(x), nil
case uint64:
return uint64(x), nil
return x, nil
default:
return 0, fmt.Errorf("non-integer used in LIMIT or OFFSET: %v (value of type %T)", x, x)
}
@@ -318,10 +318,10 @@ func indexExpr(s *string, x interface{}) (i uint64, err error) {
return uint64(x), nil
case uint64:
if s != nil && x >= uint64(len(*s)) {
return 0, invBoundX(*s, uint64(x))
return 0, invBoundX(*s, x)
}
return uint64(x), nil
return x, nil
default:
return 0, fmt.Errorf("non-integer string index %v (value of type %T)", x, x)
}
@@ -429,10 +429,10 @@ func sliceExpr(s *string, x interface{}, mod int) (i uint64, err error) {
return uint64(x), nil
case uint64:
if s != nil && x >= uint64(len(*s)+mod) {
return 0, invSliceBoundX(*s, uint64(x))
return 0, invSliceBoundX(*s, x)
}
return uint64(x), nil
return x, nil
default:
return 0, fmt.Errorf("invalid slice index %s (type %T)", x, x)
}
@@ -529,7 +529,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
//case idealRune:
//case idealUint:
case bool:
return bool(x), nil
return x, nil
//case complex64:
//case complex128:
//case float32:
@@ -561,7 +561,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
return complex(float32(x), 0), nil
//case bool:
case complex64:
return complex64(x), nil
return x, nil
case complex128:
return complex64(x), nil
//case float32:
@@ -595,7 +595,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case complex64:
return complex128(x), nil
case complex128:
return complex128(x), nil
return x, nil
//case float32:
//case float64:
//case int8:
@@ -626,7 +626,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
//case complex64:
//case complex128:
case float32:
return float32(x), nil
return x, nil
case float64:
return float32(x), nil
case int8:
@@ -675,7 +675,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case float32:
return float64(x), nil
case float64:
return float64(x), nil
return x, nil
case int8:
return float64(x), nil
case int16:
@@ -728,7 +728,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case float64:
return int8(x), nil
case int8:
return int8(x), nil
return x, nil
case int16:
return int8(x), nil
case int32:
@@ -777,7 +777,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case int8:
return int16(x), nil
case int16:
return int16(x), nil
return x, nil
case int32:
return int16(x), nil
case int64:
@@ -826,7 +826,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case int16:
return int32(x), nil
case int32:
return int32(x), nil
return x, nil
case int64:
return int32(x), nil
//case string:
@@ -875,7 +875,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case int32:
return int64(x), nil
case int64:
return int64(x), nil
return x, nil
//case string:
case uint8:
return int64(x), nil
@@ -917,7 +917,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case int64:
return string(x), nil
case string:
return string(x), nil
return x, nil
case uint8:
return string(x), nil
case uint16:
@@ -970,7 +970,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
return uint8(x), nil
//case string:
case uint8:
return uint8(x), nil
return x, nil
case uint16:
return uint8(x), nil
case uint32:
@@ -1019,7 +1019,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case uint8:
return uint16(x), nil
case uint16:
return uint16(x), nil
return x, nil
case uint32:
return uint16(x), nil
case uint64:
@@ -1068,7 +1068,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case uint16:
return uint32(x), nil
case uint32:
return uint32(x), nil
return x, nil
case uint64:
return uint32(x), nil
case *big.Int:
@@ -1117,7 +1117,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
case uint32:
return uint64(x), nil
case uint64:
return uint64(x), nil
return x, nil
case *big.Int:
return x.Uint64(), nil
case time.Duration:
@@ -1162,7 +1162,7 @@ func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
ii.Quo(ii, rr.Denom())
return ii, nil
case float64:
rr := big.NewRat(1, 1).SetFloat64(float64(x))
rr := big.NewRat(1, 1).SetFloat64(x)
ii := big.NewInt(0).Set(rr.Num())
ii.Quo(ii, rr.Denom())
return ii, nil
@@ -1365,7 +1365,7 @@ func typeCheck(rec []interface{}, cols []*col) (err error) {
rec[i] = complex64(y)
continue
case qComplex128:
rec[i] = complex128(y)
rec[i] = y
continue
case qFloat32, qFloat64, qInt8, qInt16, qInt32, qInt64, qUint8, qUint16, qUint32, qUint64:
return fmt.Errorf("constant %v truncated to real", y)
@@ -1378,13 +1378,13 @@ func typeCheck(rec []interface{}, cols []*col) (err error) {
rec[i] = complex(float32(y), 0)
continue
case qComplex128:
rec[i] = complex(float64(y), 0)
rec[i] = complex(y, 0)
continue
case qFloat32:
rec[i] = float32(y)
continue
case qFloat64:
rec[i] = float64(y)
rec[i] = y
continue
case qInt8:
if math.Floor(y) != y {
@@ -1532,7 +1532,7 @@ func typeCheck(rec []interface{}, cols []*col) (err error) {
return overflow(y, c.typ)
}
rec[i] = int64(y)
rec[i] = y
continue
case qString:
case qUint8:
@@ -1612,7 +1612,7 @@ func typeCheck(rec []interface{}, cols []*col) (err error) {
return overflow(y, c.typ)
}
rec[i] = int64(y)
rec[i] = y
continue
case qString:
case qUint8:
@@ -1719,7 +1719,7 @@ func typeCheck(rec []interface{}, cols []*col) (err error) {
rec[i] = uint32(y)
continue
case qUint64:
rec[i] = uint64(y)
rec[i] = y
continue
case qBigInt:
rec[i] = big.NewInt(0).SetUint64(y)
@@ -1788,7 +1788,7 @@ func collate1(a, b interface{}) int {
return 1
case complex64:
{
x, y := complex64(x), complex64(y)
x, y := complex64(x), y
if x == y {
return 0
}
@@ -1886,7 +1886,7 @@ func collate1(a, b interface{}) int {
}
case uint64:
{
x, y := uint64(x), uint64(y)
x, y := uint64(x), y
if x < y {
return -1
}
@@ -1968,7 +1968,7 @@ func collate1(a, b interface{}) int {
}
case int64:
{
x, y := int64(x), int64(y)
x, y := int64(x), y
if x < y {
return -1
}
@@ -2050,7 +2050,7 @@ func collate1(a, b interface{}) int {
}
case int64:
{
x, y := int64(x), int64(y)
x, y := int64(x), y
if x < y {
return -1
}
@@ -2106,7 +2106,7 @@ func collate1(a, b interface{}) int {
}
case float64:
{
x, y := float64(x), float64(y)
x, y := float64(x), y
if x < y {
return -1
}
@@ -2144,7 +2144,7 @@ func collate1(a, b interface{}) int {
return 1
case idealComplex:
{
x, y := complex64(x), complex64(y)
x, y := x, complex64(y)
if x == y {
return 0
}
@@ -2190,7 +2190,7 @@ func collate1(a, b interface{}) int {
return 1
case idealComplex:
{
x, y := complex128(x), complex128(y)
x, y := x, complex128(y)
if x == y {
return 0
}
@@ -2228,7 +2228,7 @@ func collate1(a, b interface{}) int {
return 1
case idealFloat:
{
x, y := float32(x), float32(y)
x, y := x, float32(y)
if x < y {
return -1
}
@@ -2258,7 +2258,7 @@ func collate1(a, b interface{}) int {
return 1
case idealFloat:
{
x, y := float64(x), float64(y)
x, y := x, float64(y)
if x < y {
return -1
}
@@ -2378,7 +2378,7 @@ func collate1(a, b interface{}) int {
return 1
case idealInt:
{
x, y := int64(x), int64(y)
x, y := x, int64(y)
if x < y {
return -1
}
@@ -2537,7 +2537,7 @@ func collate1(a, b interface{}) int {
return 1
case idealInt:
{
x, y := uint64(x), uint64(y)
x, y := x, uint64(y)
if x < y {
return -1
}
@@ -2550,7 +2550,7 @@ func collate1(a, b interface{}) int {
}
case idealUint:
{
x, y := uint64(x), uint64(y)
x, y := x, uint64(y)
if x < y {
return -1
}

4
vendor/github.com/cznic/ql/expr.go generated vendored
View File

@@ -1958,7 +1958,7 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
case uint32:
cnt = uint64(y)
case uint64:
cnt = uint64(y)
cnt = y
default:
return invOp2(a, b, op)
}
@@ -2057,7 +2057,7 @@ func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}
case uint32:
cnt = uint64(y)
case uint64:
cnt = uint64(y)
cnt = y
default:
return invOp2(a, b, op)
}

46
vendor/github.com/cznic/ql/file.go generated vendored
View File

@@ -89,7 +89,7 @@ func OpenFile(name string, opt *Options) (db *DB, err error) {
}
}
fi, err := newFileFromOSFile(f) // always ACID
fi, err := newFileFromOSFile(f, opt.Headroom) // always ACID
if err != nil {
return
}
@@ -101,6 +101,8 @@ func OpenFile(name string, opt *Options) (db *DB, err error) {
}
}
fi.removeEmptyWAL = opt.RemoveEmptyWAL
return newDB(fi)
}
@@ -126,10 +128,25 @@ func OpenFile(name string, opt *Options) (db *DB, err error) {
// interface.
//
// If TempFile is nil it defaults to ioutil.TempFile.
//
// Headroom
//
// Headroom selects the minimum size a WAL file will have. The "extra"
// allocated file space serves as a headroom. Commits that fit into the
// headroom should not fail due to 'not enough space on the volume' errors. The
// headroom parameter is first rounded-up to a non negative multiple of the
// size of the lldb.Allocator atom.
//
// RemoveEmptyWAL
//
// RemoveEmptyWAL controls whether empty WAL files should be deleted on
// clean exit.
type Options struct {
CanCreate bool
OSFile lldb.OSFile
TempFile func(dir, prefix string) (f lldb.OSFile, err error)
Headroom int64
RemoveEmptyWAL bool
}
type fileBTreeIterator struct {
@@ -258,7 +275,7 @@ func infer(from []interface{}, to *[]*col) {
case time.Duration:
c.typ = qDuration
case chunk:
vals, err := lldb.DecodeScalars([]byte(x.b))
vals, err := lldb.DecodeScalars(x.b)
if err != nil {
panic(err)
}
@@ -384,9 +401,10 @@ type file struct {
name string
tempFile func(dir, prefix string) (f lldb.OSFile, err error)
wal *os.File
removeEmptyWAL bool // Whether empty WAL files should be removed on close
}
func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
func newFileFromOSFile(f lldb.OSFile, headroom int64) (fi *file, err error) {
nm := lockName(f.Name())
lck, err := lock.Lock(nm)
if err != nil {
@@ -434,9 +452,7 @@ func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
return nil, err
}
if st.Size() != 0 {
return nil, fmt.Errorf("(file-001) non empty WAL file %s exists", wn)
}
closew = st.Size() == 0
}
info, err := f.Stat()
@@ -454,7 +470,7 @@ func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
filer := lldb.Filer(lldb.NewOSFiler(f))
filer = lldb.NewInnerFiler(filer, 16)
if filer, err = lldb.NewACIDFiler(filer, w); err != nil {
if filer, err = lldb.NewACIDFiler(filer, w, lldb.MinWAL(headroom)); err != nil {
return nil, err
}
@@ -508,7 +524,7 @@ func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
filer := lldb.Filer(lldb.NewOSFiler(f))
filer = lldb.NewInnerFiler(filer, 16)
if filer, err = lldb.NewACIDFiler(filer, w); err != nil {
if filer, err = lldb.NewACIDFiler(filer, w, lldb.MinWAL(headroom)); err != nil {
return nil, err
}
@@ -589,12 +605,22 @@ func (s *file) Close() (err error) {
es := s.f0.Sync()
ef := s.f0.Close()
var ew error
var ew, estat, eremove error
if s.wal != nil {
remove := false
wn := s.wal.Name()
if s.removeEmptyWAL {
var stat os.FileInfo
stat, estat = s.wal.Stat()
remove = stat.Size() == 0
}
ew = s.wal.Close()
if remove {
eremove = os.Remove(wn)
}
}
el := s.lck.Close()
return errSet(&err, es, ef, ew, el)
return errSet(&err, es, ef, ew, el, estat, eremove)
}
func (s *file) Name() string { return s.name }

56
vendor/github.com/cznic/ql/ql.go generated vendored
View File

@@ -771,16 +771,17 @@ func cols2meta(f []*col) (s string) {
// DB represent the database capable of executing QL statements.
type DB struct {
cc *TCtx // Current transaction context
exprCache map[string]expression
exprCacheMu sync.Mutex
hasIndex2 int // 0: nope, 1: in progress, 2: yes.
isMem bool
mu sync.Mutex
queue []chan struct{}
root *root
rw bool // DB FSM
rwmu sync.RWMutex
store storage
tnl int // Transaction nesting level
exprCache map[string]expression
exprCacheMu sync.Mutex
hasIndex2 int // 0: nope, 1: in progress, 2: yes.
}
var selIndex2Expr = MustCompile("select Expr from __Index2_Expr where Index2_ID == $1")
@@ -1086,7 +1087,7 @@ func mustCompile(src string) List {
return list
}
// Execute executes statements in a list while substituting QL paramaters from
// Execute executes statements in a list while substituting QL parameters from
// arg.
//
// The resulting []Recordset corresponds to the SELECT FROM statements in the
@@ -1214,6 +1215,15 @@ func (db *DB) Execute(ctx *TCtx, l List, arg ...interface{}) (rs []Recordset, in
return
}
func (db *DB) muUnlock() {
if n := len(db.queue); n != 0 {
db.queue[0] <- struct{}{}
copy(db.queue, db.queue[1:])
db.queue = db.queue[:n-1]
}
db.mu.Unlock()
}
func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tnlb int, err error) {
db.mu.Lock()
tnla = db.tnl
@@ -1222,7 +1232,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
case false:
switch s.(type) {
case beginTransactionStmt:
defer db.mu.Unlock()
defer db.muUnlock()
if pc == nil {
return nil, tnla, tnlb, errors.New("BEGIN TRANSACTION: cannot start a transaction in nil TransactionCtx")
}
@@ -1239,19 +1249,19 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
db.rw = true
return
case commitStmt:
defer db.mu.Unlock()
defer db.muUnlock()
return nil, tnla, tnlb, errCommitNotInTransaction
case rollbackStmt:
defer db.mu.Unlock()
defer db.muUnlock()
return nil, tnla, tnlb, errRollbackNotInTransaction
default:
if s.isUpdating() {
db.mu.Unlock()
db.muUnlock()
return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
}
db.rwmu.RLock() // can safely grab before Unlock
db.mu.Unlock()
db.muUnlock()
defer db.rwmu.RUnlock()
rs, err = s.exec(&execCtx{db, arg}) // R/O tctx
return rs, tnla, tnlb, err
@@ -1259,7 +1269,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
default: // case true:
switch s.(type) {
case beginTransactionStmt:
defer db.mu.Unlock()
defer db.muUnlock()
if pc == nil {
return nil, tnla, tnlb, errBeginTransNoCtx
@@ -1267,12 +1277,16 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
if pc != db.cc {
for db.rw {
db.mu.Unlock() // Transaction isolation
ch := make(chan struct{}, 1)
db.queue = append(db.queue, ch)
db.mu.Unlock()
<-ch
db.mu.Lock()
}
db.rw = true
db.rwmu.Lock()
}
if err = db.store.BeginTransaction(); err != nil {
@@ -1285,7 +1299,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
tnlb = db.tnl
return
case commitStmt:
defer db.mu.Unlock()
defer db.muUnlock()
if pc != db.cc {
return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
}
@@ -1303,7 +1317,7 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
db.rwmu.Unlock()
return
case rollbackStmt:
defer db.mu.Unlock()
defer db.muUnlock()
defer func() { pc.LastInsertID = db.root.lastInsertID }()
if pc != db.cc {
return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
@@ -1324,18 +1338,18 @@ func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tn
default:
if pc == nil {
if s.isUpdating() {
db.mu.Unlock()
db.muUnlock()
return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
}
db.mu.Unlock() // must Unlock before RLock
db.muUnlock() // must Unlock before RLock
db.rwmu.RLock()
defer db.rwmu.RUnlock()
rs, err = s.exec(&execCtx{db, arg})
return rs, tnla, tnlb, err
}
defer db.mu.Unlock()
defer db.muUnlock()
defer func() { pc.LastInsertID = db.root.lastInsertID }()
if pc != db.cc {
return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
@@ -1361,7 +1375,7 @@ func (db *DB) Flush() (err error) {
// Close will close the DB. Successful Close is idempotent.
func (db *DB) Close() error {
db.mu.Lock()
defer db.mu.Unlock()
defer db.muUnlock()
if db.store == nil {
return nil
}
@@ -1380,17 +1394,17 @@ func (db *DB) do(r recordset, f func(data []interface{}) (bool, error)) (err err
switch db.rw {
case false:
db.rwmu.RLock() // can safely grab before Unlock
db.mu.Unlock()
db.muUnlock()
defer db.rwmu.RUnlock()
default: // case true:
if r.tx == nil {
db.mu.Unlock() // must Unlock before RLock
db.muUnlock() // must Unlock before RLock
db.rwmu.RLock()
defer db.rwmu.RUnlock()
break
}
defer db.mu.Unlock()
defer db.muUnlock()
if r.tx != db.cc {
return fmt.Errorf("invalid passed transaction context")
}
@@ -1569,7 +1583,7 @@ func (db *DB) info() (r *DbInfo, err error) {
// to obtain the result.
func (db *DB) Info() (r *DbInfo, err error) {
db.mu.Lock()
defer db.mu.Unlock()
defer db.muUnlock()
return db.info()
}

View File

@@ -11,7 +11,10 @@ import (
"encoding/base64"
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"runtime"
"sort"
"strconv"
"strings"
@@ -643,3 +646,42 @@ func prettyPrint(protect map[interface{}]struct{}, sf Formatter, prefix, suffix
sf.Format("%u}" + suffix)
}
}
// Gopath returns the value of the $GOPATH environment variable or its default
// value if not set.
func Gopath() string {
if r := os.Getenv("GOPATH"); r != "" {
return r
}
// go1.8: https://github.com/golang/go/blob/74628a8b9f102bddd5078ee426efe0fd57033115/doc/code.html#L122
switch runtime.GOOS {
case "plan9":
return os.Getenv("home")
case "windows":
return filepath.Join(os.Getenv("USERPROFILE"), "go")
default:
return filepath.Join(os.Getenv("HOME"), "go")
}
}
// ImportPath returns the import path of the caller or an error, if any.
func ImportPath() (string, error) {
_, file, _, ok := runtime.Caller(1)
if !ok {
return "", fmt.Errorf("runtime.Caller failed")
}
gopath := Gopath()
for _, v := range filepath.SplitList(gopath) {
gp := filepath.Join(v, "src")
path, err := filepath.Rel(gp, file)
if err != nil {
continue
}
return filepath.Dir(path), nil
}
return "", fmt.Errorf("cannot determine import path using GOPATH=%s", gopath)
}

View File

@@ -1,59 +0,0 @@
package examples
import (
"fmt"
"github.com/d4l3k/messagediff"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
func ExampleAtom() {
got := data2()
want := data1()
diff, equal := messagediff.PrettyDiff(want, got)
fmt.Printf("%v %s", equal, diff)
// Output: false modified: [0].FirstChild.NextSibling.Attr = " baz"
}
func data1() []*html.Node {
n := &html.Node{
Type: html.ElementNode, Data: atom.Span.String(),
Attr: []html.Attribute{
{Key: atom.Class.String(), Val: "foo"},
},
}
n.AppendChild(
&html.Node{
Type: html.ElementNode, Data: atom.Span.String(),
Attr: []html.Attribute{
{Key: atom.Class.String(), Val: "bar"},
},
},
)
n.AppendChild(&html.Node{
Type: html.TextNode, Data: "baz",
})
return []*html.Node{n}
}
func data2() []*html.Node {
n := &html.Node{
Type: html.ElementNode, Data: atom.Span.String(),
Attr: []html.Attribute{
{Key: atom.Class.String(), Val: "foo"},
},
}
n.AppendChild(
&html.Node{
Type: html.ElementNode, Data: atom.Span.String(),
Attr: []html.Attribute{
{Key: atom.Class.String(), Val: "bar"},
},
},
)
n.AppendChild(&html.Node{
Type: html.TextNode, Data: " baz",
})
return []*html.Node{n}
}

View File

@@ -41,20 +41,25 @@ func newDiff() *Diff {
}
func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
// The array underlying `path` could be modified in subsequent
// calls. Make sure we have a local copy.
localPath := make(Path, len(path))
copy(localPath, path)
// Validity checks. Should only trigger if nil is one of the original arguments.
if !aVal.IsValid() && !bVal.IsValid() {
return true
}
if !bVal.IsValid() {
d.Modified[&path] = nil
d.Modified[&localPath] = nil
return false
} else if !aVal.IsValid() {
d.Modified[&path] = bVal.Interface()
d.Modified[&localPath] = bVal.Interface()
return false
}
if aVal.Type() != bVal.Type() {
d.Modified[&path] = bVal.Interface()
d.Modified[&localPath] = bVal.Interface()
return false
}
kind := aVal.Kind()
@@ -96,7 +101,7 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
return true
}
if aVal.IsNil() || bVal.IsNil() {
d.Modified[&path] = bVal.Interface()
d.Modified[&localPath] = bVal.Interface()
return false
}
}
@@ -106,20 +111,20 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
aLen := aVal.Len()
bLen := bVal.Len()
for i := 0; i < min(aLen, bLen); i++ {
localPath := append(path, SliceIndex(i))
localPath := append(localPath, SliceIndex(i))
if eq := d.diff(aVal.Index(i), bVal.Index(i), localPath); !eq {
equal = false
}
}
if aLen > bLen {
for i := bLen; i < aLen; i++ {
localPath := append(path, SliceIndex(i))
localPath := append(localPath, SliceIndex(i))
d.Removed[&localPath] = aVal.Index(i).Interface()
equal = false
}
} else if aLen < bLen {
for i := aLen; i < bLen; i++ {
localPath := append(path, SliceIndex(i))
localPath := append(localPath, SliceIndex(i))
d.Added[&localPath] = bVal.Index(i).Interface()
equal = false
}
@@ -128,7 +133,7 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
for _, key := range aVal.MapKeys() {
aI := aVal.MapIndex(key)
bI := bVal.MapIndex(key)
localPath := append(path, MapKey{key.Interface()})
localPath := append(localPath, MapKey{key.Interface()})
if !bI.IsValid() {
d.Removed[&localPath] = aI.Interface()
equal = false
@@ -140,7 +145,7 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
aI := aVal.MapIndex(key)
if !aI.IsValid() {
bI := bVal.MapIndex(key)
localPath := append(path, MapKey{key.Interface()})
localPath := append(localPath, MapKey{key.Interface()})
d.Added[&localPath] = bI.Interface()
equal = false
}
@@ -150,7 +155,7 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
for i := 0; i < typ.NumField(); i++ {
index := []int{i}
field := typ.FieldByIndex(index)
localPath := append(path, StructField(field.Name))
localPath := append(localPath, StructField(field.Name))
aI := unsafeReflectValue(aVal.FieldByIndex(index))
bI := unsafeReflectValue(bVal.FieldByIndex(index))
if eq := d.diff(aI, bI, localPath); !eq {
@@ -158,12 +163,12 @@ func (d *Diff) diff(aVal, bVal reflect.Value, path Path) bool {
}
}
case reflect.Ptr:
equal = d.diff(aVal.Elem(), bVal.Elem(), path)
equal = d.diff(aVal.Elem(), bVal.Elem(), localPath)
default:
if reflect.DeepEqual(aVal.Interface(), bVal.Interface()) {
equal = true
} else {
d.Modified[&path] = bVal.Interface()
d.Modified[&localPath] = bVal.Interface()
equal = false
}
}

View File

@@ -1,164 +0,0 @@
package messagediff
import (
"testing"
"time"
)
type testStruct struct {
A, b int
C []int
D [3]int
}
type RecursiveStruct struct {
Key int
Child *RecursiveStruct
}
func newRecursiveStruct(key int) *RecursiveStruct {
a := &RecursiveStruct{
Key: key,
}
b := &RecursiveStruct{
Key: key,
Child: a,
}
a.Child = b
return a
}
type testCase struct {
a, b interface{}
diff string
equal bool
}
func checkTestCases(t *testing.T, testData []testCase) {
for i, td := range testData {
diff, equal := PrettyDiff(td.a, td.b)
if diff != td.diff {
t.Errorf("%d. PrettyDiff(%#v, %#v) diff = %#v; not %#v", i, td.a, td.b, diff, td.diff)
}
if equal != td.equal {
t.Errorf("%d. PrettyDiff(%#v, %#v) equal = %#v; not %#v", i, td.a, td.b, equal, td.equal)
}
}
}
func TestPrettyDiff(t *testing.T) {
testData := []testCase{
{
true,
false,
"modified: = false\n",
false,
},
{
true,
0,
"modified: = 0\n",
false,
},
{
[]int{0, 1, 2},
[]int{0, 1, 2, 3},
"added: [3] = 3\n",
false,
},
{
[]int{0, 1, 2, 3},
[]int{0, 1, 2},
"removed: [3] = 3\n",
false,
},
{
[]int{0},
[]int{1},
"modified: [0] = 1\n",
false,
},
{
&[]int{0},
&[]int{1},
"modified: [0] = 1\n",
false,
},
{
map[string]int{"a": 1, "b": 2},
map[string]int{"b": 4, "c": 3},
"added: [\"c\"] = 3\nmodified: [\"b\"] = 4\nremoved: [\"a\"] = 1\n",
false,
},
{
testStruct{1, 2, []int{1}, [3]int{4, 5, 6}},
testStruct{1, 3, []int{1, 2}, [3]int{4, 5, 6}},
"added: .C[1] = 2\nmodified: .b = 3\n",
false,
},
{
nil,
nil,
"",
true,
},
{
&struct{}{},
nil,
"modified: = <nil>\n",
false,
},
{
nil,
&struct{}{},
"modified: = &struct {}{}\n",
false,
},
{
time.Time{},
time.Time{},
"",
true,
},
{
time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
time.Time{},
"modified: .loc = (*time.Location)(nil)\nmodified: .sec = 0\n",
false,
},
}
checkTestCases(t, testData)
}
func TestPrettyDiffRecursive(t *testing.T) {
testData := []testCase{
{
newRecursiveStruct(1),
newRecursiveStruct(1),
"",
true,
},
{
newRecursiveStruct(1),
newRecursiveStruct(2),
"modified: .Child.Key = 2\nmodified: .Key = 2\n",
false,
},
}
checkTestCases(t, testData)
}
func TestPathString(t *testing.T) {
testData := []struct {
in Path
want string
}{{
Path{StructField("test"), SliceIndex(1), MapKey{"blue"}, MapKey{12.3}},
".test[1][\"blue\"][12.3]",
}}
for i, td := range testData {
if out := td.in.String(); out != td.want {
t.Errorf("%d. %#v.String() = %#v; not %#v", i, td.in, out, td.want)
}
}
}

View File

@@ -54,6 +54,10 @@ func Map(f *os.File, prot, flags int) (MMap, error) {
// If length < 0, the entire file will be mapped.
// If ANON is set in flags, f is ignored.
func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) {
if offset%int64(os.Getpagesize()) != 0 {
return nil, errors.New("offset parameter must be a multiple of the system's page size")
}
var fd uintptr
if flags&ANON == 0 {
fd = uintptr(f.Fd())

View File

@@ -38,7 +38,7 @@ func (self Contains) Index(s string) (int, []int) {
}
segments := acquireSegments(len(s) + 1)
for i, _ := range s {
for i := range s {
segments = append(segments, offset+i)
}

View File

@@ -15,7 +15,7 @@ func NewMax(l int) Max {
func (self Max) Match(s string) bool {
var l int
for _ = range s {
for range s {
l += 1
if l > self.Limit {
return false

View File

@@ -15,7 +15,7 @@ func NewMin(l int) Min {
func (self Min) Match(s string) bool {
var l int
for _ = range s {
for range s {
l += 1
if l >= self.Limit {
return true

View File

@@ -43,7 +43,7 @@ func (self Row) matchAll(s string) bool {
func (self Row) lenOk(s string) bool {
var i int
for _ = range s {
for range s {
i++
if i > self.RunesLength {
return false

View File

@@ -1,3 +0,0 @@
._*
*.js
*.js.map

View File

@@ -1,8 +0,0 @@
Walter Schulze <awalterschulze@gmail.com> Walter Schulze <walter@vastech.co.za>
Walter Schulze <awalterschulze@gmail.com> <walter@vastech.co.za>
Walter Schulze <awalterschulze@gmail.com> awalterschulze <awalterschulze@gmail.com>
Walter Schulze <awalterschulze@gmail.com> awalterschulze@gmail.com <awalterschulze@gmail.com>
John Tuley <john@tuley.org> <jtuley@pivotal.io>
Anton Povarov <anton.povarov@gmail.com> <antoxa@corp.badoo.com>
Denis Smirnov <denis.smirnov.91@gmail.com> dennwc
DongYun Kang <ceram1000@gmail.com> <ceram1000@gmail.com>

View File

@@ -1,25 +0,0 @@
env:
- PROTOBUF_VERSION=2.6.1
- PROTOBUF_VERSION=3.0.2
- PROTOBUF_VERSION=3.1.0
before_install:
- ./install-protobuf.sh
- PATH=/home/travis/bin:$PATH protoc --version
script:
- PATH=/home/travis/bin:$PATH make buildserverall
- echo $TRAVIS_GO_VERSION
- if [ "$TRAVIS_GO_VERSION" == 1.7.1 ] && [[ "$PROTOBUF_VERSION" == 3.1.0 ]]; then ! git status --porcelain | read || (git status; git diff; exit 1); fi
language: go
go:
- 1.5.4
- 1.6.3
- 1.7.1
matrix:
allow_failures:
- go: 1.5.4
- go: 1.6.3

View File

@@ -1,14 +0,0 @@
# This is the official list of GoGo authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS file, which
# lists people. For example, employees are listed in CONTRIBUTORS,
# but not in AUTHORS, because the employer holds the copyright.
# Names should be added to this file as one of
# Organization's name
# Individual's name <submission email address>
# Individual's name <submission email address> <email2> <emailN>
# Please keep the list sorted.
Vastech SA (PTY) LTD
Walter Schulze <awalterschulze@gmail.com>

View File

@@ -1,16 +0,0 @@
Anton Povarov <anton.povarov@gmail.com>
Clayton Coleman <ccoleman@redhat.com>
Denis Smirnov <denis.smirnov.91@gmail.com>
DongYun Kang <ceram1000@gmail.com>
Dwayne Schultz <dschultz@pivotal.io>
Georg Apitz <gapitz@pivotal.io>
Gustav Paul <gustav.paul@gmail.com>
Johan Brandhorst <johan.brandhorst@gmail.com>
John Tuley <john@tuley.org>
Laurent <laurent@adyoulike.com>
Patrick Lee <patrick@dropbox.com>
Stephen J Day <stephen.day@docker.com>
Tamir Duberstein <tamird@gmail.com>
Todd Eisenberger <teisenberger@dropbox.com>
Tormod Erevik Lea <tormodlea@gmail.com>
Walter Schulze <awalterschulze@gmail.com>

View File

@@ -1,5 +0,0 @@
The contributors to the Go protobuf repository:
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

View File

@@ -1,141 +0,0 @@
# Protocol Buffers for Go with Gadgets
#
# Copyright (c) 2013, The GoGo Authors. All rights reserved.
# http://github.com/gogo/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.PHONY: nuke regenerate tests clean install gofmt vet contributors
all: clean install regenerate install tests errcheck vet
buildserverall: clean install regenerate install tests vet js
install:
go install ./proto
go install ./gogoproto
go install ./jsonpb
go install ./protoc-gen-gogo
go install ./protoc-gen-gofast
go install ./protoc-gen-gogofast
go install ./protoc-gen-gogofaster
go install ./protoc-gen-gogoslick
go install ./protoc-gen-gostring
go install ./protoc-min-version
go install ./protoc-gen-combo
go install ./gogoreplace
clean:
go clean ./...
nuke:
go clean -i ./...
gofmt:
gofmt -l -s -w .
regenerate:
make -C protoc-gen-gogo/descriptor regenerate
make -C protoc-gen-gogo/plugin regenerate
make -C protoc-gen-gogo/testdata regenerate
make -C gogoproto regenerate
make -C proto/testdata regenerate
make -C jsonpb/jsonpb_test_proto regenerate
make -C _conformance regenerate
make -C types regenerate
make -C test regenerate
make -C test/example regenerate
make -C test/unrecognized regenerate
make -C test/group regenerate
make -C test/unrecognizedgroup regenerate
make -C test/enumstringer regenerate
make -C test/unmarshalmerge regenerate
make -C test/moredefaults regenerate
make -C test/issue8 regenerate
make -C test/enumprefix regenerate
make -C test/enumcustomname regenerate
make -C test/packed regenerate
make -C test/protosize regenerate
make -C test/tags regenerate
make -C test/oneof regenerate
make -C test/oneof3 regenerate
make -C test/theproto3 regenerate
make -C test/mapsproto2 regenerate
make -C test/issue42order regenerate
make -C proto generate-test-pbs
make -C test/importdedup regenerate
make -C test/custombytesnonstruct regenerate
make -C test/required regenerate
make -C test/casttype regenerate
make -C test/castvalue regenerate
make -C vanity/test regenerate
make -C test/sizeunderscore regenerate
make -C test/issue34 regenerate
make -C test/empty-issue70 regenerate
make -C test/indeximport-issue72 regenerate
make -C test/fuzztests regenerate
make -C test/oneofembed regenerate
make -C test/asymetric-issue125 regenerate
make -C test/filedotname regenerate
make -C test/nopackage regenerate
make -C test/types regenerate
make -C test/proto3extension regenerate
make -C test/stdtypes regenerate
make -C test/data regenerate
make gofmt
tests:
go build ./test/enumprefix
go test ./...
vet:
go vet ./...
go tool vet --shadow .
errcheck:
go get github.com/kisielk/errcheck
errcheck ./test/...
drone:
sudo apt-get install protobuf-compiler
(cd $(GOPATH)/src/github.com/gogo/protobuf && make buildserverall)
testall:
make -C protoc-gen-gogo/testdata test
make -C vanity/test test
make tests
bench:
(cd test/mixbench && go build .)
(cd test/mixbench && ./mixbench)
contributors:
git log --format='%aN <%aE>' | sort -fu > CONTRIBUTORS
js:
go get github.com/gopherjs/gopherjs
gopherjs build github.com/gogo/protobuf/protoc-gen-gogo
update:
(cd protobuf && make update)

View File

@@ -1,258 +0,0 @@
GoGoProtobuf http://github.com/gogo/protobuf extends
GoProtobuf http://github.com/golang/protobuf
# Go support for Protocol Buffers
Google's data interchange format.
Copyright 2010 The Go Authors.
https://github.com/golang/protobuf
This package and the code it generates requires at least Go 1.4.
This software implements Go bindings for protocol buffers. For
information about protocol buffers themselves, see
https://developers.google.com/protocol-buffers/
## Installation ##
To use this software, you must:
- Install the standard C++ implementation of protocol buffers from
https://developers.google.com/protocol-buffers/
- Of course, install the Go compiler and tools from
https://golang.org/
See
https://golang.org/doc/install
for details or, if you are using gccgo, follow the instructions at
https://golang.org/doc/install/gccgo
- Grab the code from the repository and install the proto package.
The simplest way is to run `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`.
The compiler plugin, protoc-gen-go, will be installed in $GOBIN,
defaulting to $GOPATH/bin. It must be in your $PATH for the protocol
compiler, protoc, to find it.
This software has two parts: a 'protocol compiler plugin' that
generates Go source files that, once compiled, can access and manage
protocol buffers; and a library that implements run-time support for
encoding (marshaling), decoding (unmarshaling), and accessing protocol
buffers.
There is support for gRPC in Go using protocol buffers.
See the note at the bottom of this file for details.
There are no insertion points in the plugin.
GoGoProtobuf provides extensions for protocol buffers and GoProtobuf
see http://github.com/gogo/protobuf/gogoproto/doc.go
## Using protocol buffers with Go ##
Once the software is installed, there are two steps to using it.
First you must compile the protocol buffer definitions and then import
them, with the support library, into your program.
To compile the protocol buffer definition, run protoc with the --gogo_out
parameter set to the directory you want to output the Go code to.
protoc --gogo_out=. *.proto
The generated files will be suffixed .pb.go. See the Test code below
for an example using such a file.
The package comment for the proto library contains text describing
the interface provided in Go for protocol buffers. Here is an edited
version.
If you are using any gogo.proto extensions you will need to specify the
proto_path to include the descriptor.proto and gogo.proto.
gogo.proto is located in github.com/gogo/protobuf/gogoproto
This should be fine, since your import is the same.
descriptor.proto is located in either github.com/gogo/protobuf/protobuf
or code.google.com/p/protobuf/trunk/src/
Its import is google/protobuf/descriptor.proto so it might need some help.
protoc --gogo_out=. -I=.:github.com/gogo/protobuf/protobuf *.proto
==========
The proto package converts data structures to and from the
wire format of protocol buffers. It works in concert with the
Go source code generated for .proto files by the protocol compiler.
A summary of the properties of the protocol buffer interface
for a protocol buffer variable v:
- Names are turned from camel_case to CamelCase for export.
- There are no methods on v to set fields; just treat
them as structure fields.
- There are getters that return a field's value if set,
and return the field's default value if unset.
The getters work even if the receiver is a nil message.
- The zero value for a struct is its correct initialization state.
All desired fields must be set before marshaling.
- A Reset() method will restore a protobuf struct to its zero state.
- Non-repeated fields are pointers to the values; nil means unset.
That is, optional or required field int32 f becomes F *int32.
- Repeated fields are slices.
- Helper functions are available to aid the setting of fields.
Helpers for getting values are superseded by the
GetFoo methods and their use is deprecated.
msg.Foo = proto.String("hello") // set field
- Constants are defined to hold the default values of all fields that
have them. They have the form Default_StructName_FieldName.
Because the getter methods handle defaulted values,
direct use of these constants should be rare.
- Enums are given type names and maps from names to values.
Enum values are prefixed with the enum's type name. Enum types have
a String method, and a Enum method to assist in message construction.
- Nested groups and enums have type names prefixed with the name of
the surrounding message type.
- Extensions are given descriptor names that start with E_,
followed by an underscore-delimited list of the nested messages
that contain it (if any) followed by the CamelCased name of the
extension field itself. HasExtension, ClearExtension, GetExtension
and SetExtension are functions for manipulating extensions.
- Oneof field sets are given a single field in their message,
with distinguished wrapper types for each possible field value.
- Marshal and Unmarshal are functions to encode and decode the wire format.
When the .proto file specifies `syntax="proto3"`, there are some differences:
- Non-repeated fields of non-message type are values instead of pointers.
- Getters are only generated for message and oneof fields.
- Enum types do not get an Enum method.
Consider file test.proto, containing
```proto
package example;
enum FOO { X = 17; };
message Test {
required string label = 1;
optional int32 type = 2 [default=77];
repeated int64 reps = 3;
optional group OptionalGroup = 4 {
required string RequiredField = 5;
}
}
```
To create and play with a Test object from the example package,
```go
package main
import (
"log"
"github.com/gogo/protobuf/proto"
"path/to/example"
)
func main() {
test := &example.Test {
Label: proto.String("hello"),
Type: proto.Int32(17),
Reps: []int64{1, 2, 3},
Optionalgroup: &example.Test_OptionalGroup {
RequiredField: proto.String("good bye"),
},
}
data, err := proto.Marshal(test)
if err != nil {
log.Fatal("marshaling error: ", err)
}
newTest := &example.Test{}
err = proto.Unmarshal(data, newTest)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// Now test and newTest contain the same data.
if test.GetLabel() != newTest.GetLabel() {
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
}
// etc.
}
```
## Parameters ##
To pass extra parameters to the plugin, use a comma-separated
parameter list separated from the output directory by a colon:
protoc --gogo_out=plugins=grpc,import_path=mypackage:. *.proto
- `import_prefix=xxx` - a prefix that is added onto the beginning of
all imports. Useful for things like generating protos in a
subdirectory, or regenerating vendored protobufs in-place.
- `import_path=foo/bar` - used as the package if no input files
declare `go_package`. If it contains slashes, everything up to the
rightmost slash is ignored.
- `plugins=plugin1+plugin2` - specifies the list of sub-plugins to
load. The only plugin in this repo is `grpc`.
- `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is
associated with Go package quux/shme. This is subject to the
import_prefix parameter.
## gRPC Support ##
If a proto file specifies RPC services, protoc-gen-go can be instructed to
generate code compatible with gRPC (http://www.grpc.io/). To do this, pass
the `plugins` parameter to protoc-gen-go; the usual way is to insert it into
the --go_out argument to protoc:
protoc --gogo_out=plugins=grpc:. *.proto
## Compatibility ##
The library and the generated code are expected to be stable over time.
However, we reserve the right to make breaking changes without notice for the
following reasons:
- Security. A security issue in the specification or implementation may come to
light whose resolution requires breaking compatibility. We reserve the right
to address such security issues.
- Unspecified behavior. There are some aspects of the Protocol Buffers
specification that are undefined. Programs that depend on such unspecified
behavior may break in future releases.
- Specification errors or changes. If it becomes necessary to address an
inconsistency, incompleteness, or change in the Protocol Buffers
specification, resolving the issue could affect the meaning or legality of
existing programs. We reserve the right to address such issues, including
updating the implementations.
- Bugs. If the library has a bug that violates the specification, a program
that depends on the buggy behavior may break if the bug is fixed. We reserve
the right to fix such bugs.
- Adding methods or fields to generated structs. These may conflict with field
names that already exist in a schema, causing applications to break. When the
code generator encounters a field in the schema that would collide with a
generated field or method name, the code generator will append an underscore
to the generated field or method name.
- Adding, removing, or changing methods or fields in generated structs that
start with `XXX`. These parts of the generated code are exported out of
necessity, but should not be considered part of the public API.
- Adding, removing, or changing unexported symbols in generated code.
Any breaking changes outside of these will be announced 6 months in advance to
protobuf@googlegroups.com.
You should, whenever possible, use generated code created by the `protoc-gen-go`
tool built at the same commit as the `proto` package. The `proto` package
declares package-level constants in the form `ProtoPackageIsVersionX`.
Application code and generated code may depend on one of these constants to
ensure that compilation will fail if the available version of the proto library
is too old. Whenever we make a change to the generated code that requires newer
library support, in the same commit we will increment the version number of the
generated code and declare a new package-level constant whose name incorporates
the latest version number. Removing a compatibility constant is considered a
breaking change and would be subject to the announcement policy stated above.
## Plugins ##
The `protoc-gen-go/generator` package exposes a plugin interface,
which is used by the gRPC code generation. This interface is not
supported and is subject to incompatible changes without notice.

View File

@@ -1,116 +0,0 @@
# Protocol Buffers for Go with Gadgets
[![Build Status](https://travis-ci.org/gogo/protobuf.svg?branch=master)](https://travis-ci.org/gogo/protobuf)
gogoprotobuf is a fork of <a href="https://github.com/golang/protobuf">golang/protobuf</a> with extra code generation features.
This code generation is used to achieve:
- fast marshalling and unmarshalling
- more canonical Go structures
- goprotobuf compatibility
- less typing by optionally generating extra helper code
- peace of mind by optionally generating test and benchmark code
- other serialization formats
Keeping track of how up to date gogoprotobuf is relative to golang/protobuf is done in this
<a href="https://github.com/gogo/protobuf/issues/191">issue</a>
## Users
These projects use gogoprotobuf:
- <a href="http://godoc.org/github.com/coreos/etcd">etcd</a> - <a href="https://blog.gopheracademy.com/advent-2015/etcd-distributed-key-value-store-with-grpc-http2/">blog</a> - <a href="https://github.com/coreos/etcd/blob/master/etcdserver/etcdserverpb/etcdserver.proto">sample proto file</a>
- <a href="https://www.spacemonkey.com/">spacemonkey</a> - <a href="https://www.spacemonkey.com/blog/posts/go-space-monkey">blog</a>
- <a href="http://badoo.com">badoo</a> - <a href="https://github.com/badoo/lsd/blob/32061f501c5eca9c76c596d790b450501ba27b2f/proto/lsd.proto">sample proto file</a>
- <a href="https://github.com/mesos/mesos-go">mesos-go</a> - <a href="https://github.com/mesos/mesos-go/blob/master/mesosproto/mesos.proto">sample proto file</a>
- <a href="https://github.com/mozilla-services/heka">heka</a> - <a href="https://github.com/mozilla-services/heka/commit/eb72fbf7d2d28249fbaf8d8dc6607f4eb6f03351">the switch from golang/protobuf to gogo/protobuf when it was still on code.google.com</a>
- <a href="https://github.com/cockroachdb/cockroach">cockroachdb</a> - <a href="https://github.com/cockroachdb/cockroach/blob/651d54d393e391a30154e9117ab4b18d9ee6d845/roachpb/metadata.proto">sample proto file</a>
- <a href="https://github.com/jbenet/go-ipfs">go-ipfs</a> - <a href="https://github.com/ipfs/go-ipfs/blob/2b6da0c024f28abeb16947fb452787196a6b56a2/merkledag/pb/merkledag.proto">sample proto file</a>
- <a href="https://github.com/philhofer/rkive">rkive-go</a> - <a href="https://github.com/philhofer/rkive/blob/e5dd884d3ea07b341321073882ae28aa16dd11be/rpbc/riak_dt.proto">sample proto file</a>
- <a href="https://www.dropbox.com">dropbox</a>
- <a href="https://srclib.org/">srclib</a> - <a href="https://github.com/sourcegraph/srclib/blob/6538858f0c410cac5c63440317b8d009e889d3fb/graph/def.proto">sample proto file</a>
- <a href="http://www.adyoulike.com/">adyoulike</a>
- <a href="http://www.cloudfoundry.org/">cloudfoundry</a> - <a href="https://github.com/cloudfoundry/bbs/blob/d673710b8c4211037805129944ee4c5373d6588a/models/events.proto">sample proto file</a>
- <a href="http://kubernetes.io/">kubernetes</a> - <a href="https://github.com/kubernetes/kubernetes/tree/88d8628137f94ee816aaa6606ae8cd045dee0bff/cmd/libs/go2idl">go2idl built on top of gogoprotobuf</a>
- <a href="https://dgraph.io/">dgraph</a> - <a href="https://github.com/dgraph-io/dgraph/releases/tag/v0.4.3">release notes</a> - <a href="https://discuss.dgraph.io/t/gogoprotobuf-is-extremely-fast/639">benchmarks</a></a>
- <a href="https://github.com/centrifugal/centrifugo">centrifugo</a> - <a href="https://forum.golangbridge.org/t/centrifugo-real-time-messaging-websocket-or-sockjs-server-v1-5-0-released/2861">release notes</a> - <a href="https://medium.com/@fzambia/centrifugo-protobuf-inside-json-outside-21d39bdabd68#.o3icmgjqd">blog</a>
- <a href="https://github.com/docker/swarmkit">docker swarmkit</a> - <a href="https://github.com/docker/swarmkit/blob/63600e01af3b8da2a0ed1c9fa6e1ae4299d75edb/api/objects.proto">sample proto file</a>
- <a href="https://nats.io/">nats.io</a> - <a href="https://github.com/nats-io/go-nats-streaming/blob/master/pb/protocol.proto">go-nats-streaming</a>
- <a href="https://github.com/pingcap/tidb">tidb</a> - Communication between <a href="https://github.com/pingcap/tipb/blob/master/generate-go.sh#L4">tidb</a> and <a href="https://github.com/pingcap/kvproto/blob/master/generate_go.sh#L3">tikv</a>
Please lets us know if you are using gogoprotobuf by posting on our <a href="https://groups.google.com/forum/#!topic/gogoprotobuf/Brw76BxmFpQ">GoogleGroup</a>.
### Mentioned
- <a href="http://www.slideshare.net/albertstrasheim/serialization-in-go">Cloudflare - go serialization talk - Albert Strasheim</a>
- <a href="http://gophercon.sourcegraph.com/post/83747547505/writing-a-high-performance-database-in-go">gophercon</a>
- <a href="https://github.com/alecthomas/go_serialization_benchmarks">alecthomas' go serialization benchmarks</a>
## Getting Started
There are several ways to use gogoprotobuf, but for all you need to install go and protoc.
After that you can choose:
- Speed
- More Speed and more generated code
- Most Speed and most customization
### Installation
To install it, you must first have Go (at least version 1.3.3) installed (see [http://golang.org/doc/install](http://golang.org/doc/install)). Go 1.7.1 is continuously tested.
Next, install the standard protocol buffer implementation from [https://github.com/google/protobuf](https://github.com/google/protobuf).
Most versions from 2.3.1 should not give any problems, but 2.6.1, 3.0.2 and 3.1.0 are continuously tested.
### Speed
Install the protoc-gen-gofast binary
go get github.com/gogo/protobuf/protoc-gen-gofast
Use it to generate faster marshaling and unmarshaling go code for your protocol buffers.
protoc --gofast_out=. myproto.proto
This does not allow you to use any of the other gogoprotobuf [extensions](https://github.com/gogo/protobuf/blob/master/extensions.md).
### More Speed and more generated code
Fields without pointers cause less time in the garbage collector.
More code generation results in more convenient methods.
Other binaries are also included:
protoc-gen-gogofast (same as gofast, but imports gogoprotobuf)
protoc-gen-gogofaster (same as gogofast, without XXX_unrecognized, less pointer fields)
protoc-gen-gogoslick (same as gogofaster, but with generated string, gostring and equal methods)
Installing any of these binaries is easy. Simply run:
go get github.com/gogo/protobuf/proto
go get github.com/gogo/protobuf/{binary}
go get github.com/gogo/protobuf/gogoproto
These binaries allow you to using gogoprotobuf [extensions](https://github.com/gogo/protobuf/blob/master/extensions.md).
### Most Speed and most customization
Customizing the fields of the messages to be the fields that you actually want to use removes the need to copy between the structs you use and structs you use to serialize.
gogoprotobuf also offers more serialization formats and generation of tests and even more methods.
Please visit the [extensions](https://github.com/gogo/protobuf/blob/master/extensions.md) page for more documentation.
Install protoc-gen-gogo:
go get github.com/gogo/protobuf/proto
go get github.com/gogo/protobuf/jsonpb
go get github.com/gogo/protobuf/protoc-gen-gogo
go get github.com/gogo/protobuf/gogoproto
## GRPC
It works the same as golang/protobuf, simply specify the plugin.
Here is an example using gofast:
protoc --gofast_out=plugins=grpc:. my.proto

View File

@@ -1,40 +0,0 @@
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2016 The Go Authors. All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
regenerate:
protoc-min-version --version="3.0.0" --proto_path=$(GOPATH)/src:$(GOPATH)/src/github.com/gogo/protobuf/protobuf:. --gogo_out=\
Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/field_mask.proto=github.com/gogo/protobuf/types\
:. conformance_proto/conformance.proto

View File

@@ -1,161 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2016 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// conformance implements the conformance test subprocess protocol as
// documented in conformance.proto.
package main
import (
"encoding/binary"
"fmt"
"io"
"os"
pb "github.com/gogo/protobuf/_conformance/conformance_proto"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
)
func main() {
var sizeBuf [4]byte
inbuf := make([]byte, 0, 4096)
outbuf := proto.NewBuffer(nil)
for {
if _, err := io.ReadFull(os.Stdin, sizeBuf[:]); err == io.EOF {
break
} else if err != nil {
fmt.Fprintln(os.Stderr, "go conformance: read request:", err)
os.Exit(1)
}
size := binary.LittleEndian.Uint32(sizeBuf[:])
if int(size) > cap(inbuf) {
inbuf = make([]byte, size)
}
inbuf = inbuf[:size]
if _, err := io.ReadFull(os.Stdin, inbuf); err != nil {
fmt.Fprintln(os.Stderr, "go conformance: read request:", err)
os.Exit(1)
}
req := new(pb.ConformanceRequest)
if err := proto.Unmarshal(inbuf, req); err != nil {
fmt.Fprintln(os.Stderr, "go conformance: parse request:", err)
os.Exit(1)
}
res := handle(req)
if err := outbuf.Marshal(res); err != nil {
fmt.Fprintln(os.Stderr, "go conformance: marshal response:", err)
os.Exit(1)
}
binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(outbuf.Bytes())))
if _, err := os.Stdout.Write(sizeBuf[:]); err != nil {
fmt.Fprintln(os.Stderr, "go conformance: write response:", err)
os.Exit(1)
}
if _, err := os.Stdout.Write(outbuf.Bytes()); err != nil {
fmt.Fprintln(os.Stderr, "go conformance: write response:", err)
os.Exit(1)
}
outbuf.Reset()
}
}
var jsonMarshaler = jsonpb.Marshaler{
OrigName: true,
}
func handle(req *pb.ConformanceRequest) *pb.ConformanceResponse {
var err error
var msg pb.TestAllTypes
switch p := req.Payload.(type) {
case *pb.ConformanceRequest_ProtobufPayload:
err = proto.Unmarshal(p.ProtobufPayload, &msg)
case *pb.ConformanceRequest_JsonPayload:
err = jsonpb.UnmarshalString(p.JsonPayload, &msg)
if err != nil && err.Error() == "unmarshaling Any not supported yet" {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_Skipped{
Skipped: err.Error(),
},
}
}
default:
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_RuntimeError{
RuntimeError: "unknown request payload type",
},
}
}
if err != nil {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_ParseError{
ParseError: err.Error(),
},
}
}
switch req.RequestedOutputFormat {
case pb.WireFormat_PROTOBUF:
p, err := proto.Marshal(&msg)
if err != nil {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_SerializeError{
SerializeError: err.Error(),
},
}
}
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_ProtobufPayload{
ProtobufPayload: p,
},
}
case pb.WireFormat_JSON:
p, err := jsonMarshaler.MarshalToString(&msg)
if err != nil {
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_SerializeError{
SerializeError: err.Error(),
},
}
}
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_JsonPayload{
JsonPayload: p,
},
}
default:
return &pb.ConformanceResponse{
Result: &pb.ConformanceResponse_RuntimeError{
RuntimeError: "unknown output format",
},
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,285 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package conformance;
option java_package = "com.google.protobuf.conformance";
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
// This defines the conformance testing protocol. This protocol exists between
// the conformance test suite itself and the code being tested. For each test,
// the suite will send a ConformanceRequest message and expect a
// ConformanceResponse message.
//
// You can either run the tests in two different ways:
//
// 1. in-process (using the interface in conformance_test.h).
//
// 2. as a sub-process communicating over a pipe. Information about how to
// do this is in conformance_test_runner.cc.
//
// Pros/cons of the two approaches:
//
// - running as a sub-process is much simpler for languages other than C/C++.
//
// - running as a sub-process may be more tricky in unusual environments like
// iOS apps, where fork/stdin/stdout are not available.
enum WireFormat {
UNSPECIFIED = 0;
PROTOBUF = 1;
JSON = 2;
}
// Represents a single test case's input. The testee should:
//
// 1. parse this proto (which should always succeed)
// 2. parse the protobuf or JSON payload in "payload" (which may fail)
// 3. if the parse succeeded, serialize the message in the requested format.
message ConformanceRequest {
// The payload (whether protobuf of JSON) is always for a TestAllTypes proto
// (see below).
oneof payload {
bytes protobuf_payload = 1;
string json_payload = 2;
}
// Which format should the testee serialize its message to?
WireFormat requested_output_format = 3;
}
// Represents a single test case's output.
message ConformanceResponse {
oneof result {
// This string should be set to indicate parsing failed. The string can
// provide more information about the parse error if it is available.
//
// Setting this string does not necessarily mean the testee failed the
// test. Some of the test cases are intentionally invalid input.
string parse_error = 1;
// If the input was successfully parsed but errors occurred when
// serializing it to the requested output format, set the error message in
// this field.
string serialize_error = 6;
// This should be set if some other error occurred. This will always
// indicate that the test failed. The string can provide more information
// about the failure.
string runtime_error = 2;
// If the input was successfully parsed and the requested output was
// protobuf, serialize it to protobuf and set it in this field.
bytes protobuf_payload = 3;
// If the input was successfully parsed and the requested output was JSON,
// serialize to JSON and set it in this field.
string json_payload = 4;
// For when the testee skipped the test, likely because a certain feature
// wasn't supported, like JSON input/output.
string skipped = 5;
}
}
// This proto includes every type of field in both singular and repeated
// forms.
message TestAllTypes {
message NestedMessage {
int32 a = 1;
TestAllTypes corecursive = 2;
}
enum NestedEnum {
FOO = 0;
BAR = 1;
BAZ = 2;
NEG = -1; // Intentionally negative.
}
// Singular
int32 optional_int32 = 1;
int64 optional_int64 = 2;
uint32 optional_uint32 = 3;
uint64 optional_uint64 = 4;
sint32 optional_sint32 = 5;
sint64 optional_sint64 = 6;
fixed32 optional_fixed32 = 7;
fixed64 optional_fixed64 = 8;
sfixed32 optional_sfixed32 = 9;
sfixed64 optional_sfixed64 = 10;
float optional_float = 11;
double optional_double = 12;
bool optional_bool = 13;
string optional_string = 14;
bytes optional_bytes = 15;
NestedMessage optional_nested_message = 18;
ForeignMessage optional_foreign_message = 19;
NestedEnum optional_nested_enum = 21;
ForeignEnum optional_foreign_enum = 22;
string optional_string_piece = 24 [ctype=STRING_PIECE];
string optional_cord = 25 [ctype=CORD];
TestAllTypes recursive_message = 27;
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated NestedMessage repeated_nested_message = 48;
repeated ForeignMessage repeated_foreign_message = 49;
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnum repeated_foreign_enum = 52;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Map
map < int32, int32> map_int32_int32 = 56;
map < int64, int64> map_int64_int64 = 57;
map < uint32, uint32> map_uint32_uint32 = 58;
map < uint64, uint64> map_uint64_uint64 = 59;
map < sint32, sint32> map_sint32_sint32 = 60;
map < sint64, sint64> map_sint64_sint64 = 61;
map < fixed32, fixed32> map_fixed32_fixed32 = 62;
map < fixed64, fixed64> map_fixed64_fixed64 = 63;
map <sfixed32, sfixed32> map_sfixed32_sfixed32 = 64;
map <sfixed64, sfixed64> map_sfixed64_sfixed64 = 65;
map < int32, float> map_int32_float = 66;
map < int32, double> map_int32_double = 67;
map < bool, bool> map_bool_bool = 68;
map < string, string> map_string_string = 69;
map < string, bytes> map_string_bytes = 70;
map < string, NestedMessage> map_string_nested_message = 71;
map < string, ForeignMessage> map_string_foreign_message = 72;
map < string, NestedEnum> map_string_nested_enum = 73;
map < string, ForeignEnum> map_string_foreign_enum = 74;
oneof oneof_field {
uint32 oneof_uint32 = 111;
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
bool oneof_bool = 115;
uint64 oneof_uint64 = 116;
float oneof_float = 117;
double oneof_double = 118;
NestedEnum oneof_enum = 119;
}
// Well-known types
google.protobuf.BoolValue optional_bool_wrapper = 201;
google.protobuf.Int32Value optional_int32_wrapper = 202;
google.protobuf.Int64Value optional_int64_wrapper = 203;
google.protobuf.UInt32Value optional_uint32_wrapper = 204;
google.protobuf.UInt64Value optional_uint64_wrapper = 205;
google.protobuf.FloatValue optional_float_wrapper = 206;
google.protobuf.DoubleValue optional_double_wrapper = 207;
google.protobuf.StringValue optional_string_wrapper = 208;
google.protobuf.BytesValue optional_bytes_wrapper = 209;
repeated google.protobuf.BoolValue repeated_bool_wrapper = 211;
repeated google.protobuf.Int32Value repeated_int32_wrapper = 212;
repeated google.protobuf.Int64Value repeated_int64_wrapper = 213;
repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214;
repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215;
repeated google.protobuf.FloatValue repeated_float_wrapper = 216;
repeated google.protobuf.DoubleValue repeated_double_wrapper = 217;
repeated google.protobuf.StringValue repeated_string_wrapper = 218;
repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219;
google.protobuf.Duration optional_duration = 301;
google.protobuf.Timestamp optional_timestamp = 302;
google.protobuf.FieldMask optional_field_mask = 303;
google.protobuf.Struct optional_struct = 304;
google.protobuf.Any optional_any = 305;
google.protobuf.Value optional_value = 306;
repeated google.protobuf.Duration repeated_duration = 311;
repeated google.protobuf.Timestamp repeated_timestamp = 312;
repeated google.protobuf.FieldMask repeated_fieldmask = 313;
repeated google.protobuf.Struct repeated_struct = 324;
repeated google.protobuf.Any repeated_any = 315;
repeated google.protobuf.Value repeated_value = 316;
// Test field-name-to-JSON-name convention.
// (protobuf says names can be any valid C/C++ identifier.)
int32 fieldname1 = 401;
int32 field_name2 = 402;
int32 _field_name3 = 403;
int32 field__name4_ = 404;
int32 field0name5 = 405;
int32 field_0_name6 = 406;
int32 fieldName7 = 407;
int32 FieldName8 = 408;
int32 field_Name9 = 409;
int32 Field_Name10 = 410;
int32 FIELD_NAME11 = 411;
int32 FIELD_name12 = 412;
int32 __field_name13 = 413;
int32 __Field_name14 = 414;
int32 field__name15 = 415;
int32 field__Name16 = 416;
int32 field_name17__ = 417;
int32 Field_name18__ = 418;
}
message ForeignMessage {
int32 c = 1;
}
enum ForeignEnum {
FOREIGN_FOO = 0;
FOREIGN_BAR = 1;
FOREIGN_BAZ = 2;
}

View File

@@ -1,190 +0,0 @@
# Benchmarks
## How to reproduce
For a comparison run:
make bench
followed by [benchcmp](http://code.google.com/p/go/source/browse/misc/benchcmp benchcmp) on the resulting files:
$GOROOT/misc/benchcmp $GOPATH/src/github.com/gogo/protobuf/test/mixbench/marshal.txt $GOPATH/src/github.com/gogo/protobuf/test/mixbench/marshaler.txt
$GOROOT/misc/benchcmp $GOPATH/src/github.com/gogo/protobuf/test/mixbench/unmarshal.txt $GOPATH/src/github.com/gogo/protobuf/test/mixbench/unmarshaler.txt
Benchmarks ran on Revision: 11c56be39364
June 2013
Processor 2,66 GHz Intel Core i7
Memory 8 GB 1067 MHz DDR3
## Marshaler
<table>
<tr><td>benchmark</td><td>old ns/op</td><td>new ns/op</td><td>delta</td></tr>
<tr><td>BenchmarkNidOptNativeProtoMarshal</td><td>2656</td><td>889</td><td>-66.53%</td></tr>
<tr><td>BenchmarkNinOptNativeProtoMarshal</td><td>2651</td><td>1015</td><td>-61.71%</td></tr>
<tr><td>BenchmarkNidRepNativeProtoMarshal</td><td>42661</td><td>12519</td><td>-70.65%</td></tr>
<tr><td>BenchmarkNinRepNativeProtoMarshal</td><td>42306</td><td>12354</td><td>-70.80%</td></tr>
<tr><td>BenchmarkNidRepPackedNativeProtoMarshal</td><td>34148</td><td>11902</td><td>-65.15%</td></tr>
<tr><td>BenchmarkNinRepPackedNativeProtoMarshal</td><td>33375</td><td>11969</td><td>-64.14%</td></tr>
<tr><td>BenchmarkNidOptStructProtoMarshal</td><td>7148</td><td>3727</td><td>-47.86%</td></tr>
<tr><td>BenchmarkNinOptStructProtoMarshal</td><td>6956</td><td>3481</td><td>-49.96%</td></tr>
<tr><td>BenchmarkNidRepStructProtoMarshal</td><td>46551</td><td>19492</td><td>-58.13%</td></tr>
<tr><td>BenchmarkNinRepStructProtoMarshal</td><td>46715</td><td>19043</td><td>-59.24%</td></tr>
<tr><td>BenchmarkNidEmbeddedStructProtoMarshal</td><td>5231</td><td>2050</td><td>-60.81%</td></tr>
<tr><td>BenchmarkNinEmbeddedStructProtoMarshal</td><td>4665</td><td>2000</td><td>-57.13%</td></tr>
<tr><td>BenchmarkNidNestedStructProtoMarshal</td><td>181106</td><td>103604</td><td>-42.79%</td></tr>
<tr><td>BenchmarkNinNestedStructProtoMarshal</td><td>182053</td><td>102069</td><td>-43.93%</td></tr>
<tr><td>BenchmarkNidOptCustomProtoMarshal</td><td>1209</td><td>310</td><td>-74.36%</td></tr>
<tr><td>BenchmarkNinOptCustomProtoMarshal</td><td>1435</td><td>277</td><td>-80.70%</td></tr>
<tr><td>BenchmarkNidRepCustomProtoMarshal</td><td>4126</td><td>763</td><td>-81.51%</td></tr>
<tr><td>BenchmarkNinRepCustomProtoMarshal</td><td>3972</td><td>769</td><td>-80.64%</td></tr>
<tr><td>BenchmarkNinOptNativeUnionProtoMarshal</td><td>973</td><td>303</td><td>-68.86%</td></tr>
<tr><td>BenchmarkNinOptStructUnionProtoMarshal</td><td>1536</td><td>521</td><td>-66.08%</td></tr>
<tr><td>BenchmarkNinEmbeddedStructUnionProtoMarshal</td><td>2327</td><td>884</td><td>-62.01%</td></tr>
<tr><td>BenchmarkNinNestedStructUnionProtoMarshal</td><td>2070</td><td>743</td><td>-64.11%</td></tr>
<tr><td>BenchmarkTreeProtoMarshal</td><td>1554</td><td>838</td><td>-46.07%</td></tr>
<tr><td>BenchmarkOrBranchProtoMarshal</td><td>3156</td><td>2012</td><td>-36.25%</td></tr>
<tr><td>BenchmarkAndBranchProtoMarshal</td><td>3183</td><td>1996</td><td>-37.29%</td></tr>
<tr><td>BenchmarkLeafProtoMarshal</td><td>965</td><td>606</td><td>-37.20%</td></tr>
<tr><td>BenchmarkDeepTreeProtoMarshal</td><td>2316</td><td>1283</td><td>-44.60%</td></tr>
<tr><td>BenchmarkADeepBranchProtoMarshal</td><td>2719</td><td>1492</td><td>-45.13%</td></tr>
<tr><td>BenchmarkAndDeepBranchProtoMarshal</td><td>4663</td><td>2922</td><td>-37.34%</td></tr>
<tr><td>BenchmarkDeepLeafProtoMarshal</td><td>1849</td><td>1016</td><td>-45.05%</td></tr>
<tr><td>BenchmarkNilProtoMarshal</td><td>439</td><td>76</td><td>-82.53%</td></tr>
<tr><td>BenchmarkNidOptEnumProtoMarshal</td><td>514</td><td>152</td><td>-70.43%</td></tr>
<tr><td>BenchmarkNinOptEnumProtoMarshal</td><td>550</td><td>158</td><td>-71.27%</td></tr>
<tr><td>BenchmarkNidRepEnumProtoMarshal</td><td>647</td><td>207</td><td>-68.01%</td></tr>
<tr><td>BenchmarkNinRepEnumProtoMarshal</td><td>662</td><td>213</td><td>-67.82%</td></tr>
<tr><td>BenchmarkTimerProtoMarshal</td><td>934</td><td>271</td><td>-70.99%</td></tr>
<tr><td>BenchmarkMyExtendableProtoMarshal</td><td>608</td><td>185</td><td>-69.57%</td></tr>
<tr><td>BenchmarkOtherExtenableProtoMarshal</td><td>1112</td><td>332</td><td>-70.14%</td></tr>
</table>
<table>
<tr><td>benchmark</td><td>old MB/s</td><td>new MB/s</td><td>speedup</td></tr>
<tr><td>BenchmarkNidOptNativeProtoMarshal</td><td>126.86</td><td>378.86</td><td>2.99x</td></tr>
<tr><td>BenchmarkNinOptNativeProtoMarshal</td><td>114.27</td><td>298.42</td><td>2.61x</td></tr>
<tr><td>BenchmarkNidRepNativeProtoMarshal</td><td>164.25</td><td>561.20</td><td>3.42x</td></tr>
<tr><td>BenchmarkNinRepNativeProtoMarshal</td><td>166.10</td><td>568.23</td><td>3.42x</td></tr>
<tr><td>BenchmarkNidRepPackedNativeProtoMarshal</td><td>99.10</td><td>283.97</td><td>2.87x</td></tr>
<tr><td>BenchmarkNinRepPackedNativeProtoMarshal</td><td>101.30</td><td>282.31</td><td>2.79x</td></tr>
<tr><td>BenchmarkNidOptStructProtoMarshal</td><td>176.83</td><td>339.07</td><td>1.92x</td></tr>
<tr><td>BenchmarkNinOptStructProtoMarshal</td><td>163.59</td><td>326.57</td><td>2.00x</td></tr>
<tr><td>BenchmarkNidRepStructProtoMarshal</td><td>178.84</td><td>427.49</td><td>2.39x</td></tr>
<tr><td>BenchmarkNinRepStructProtoMarshal</td><td>178.70</td><td>437.69</td><td>2.45x</td></tr>
<tr><td>BenchmarkNidEmbeddedStructProtoMarshal</td><td>124.24</td><td>317.56</td><td>2.56x</td></tr>
<tr><td>BenchmarkNinEmbeddedStructProtoMarshal</td><td>132.03</td><td>307.99</td><td>2.33x</td></tr>
<tr><td>BenchmarkNidNestedStructProtoMarshal</td><td>192.91</td><td>337.86</td><td>1.75x</td></tr>
<tr><td>BenchmarkNinNestedStructProtoMarshal</td><td>192.44</td><td>344.45</td><td>1.79x</td></tr>
<tr><td>BenchmarkNidOptCustomProtoMarshal</td><td>29.77</td><td>116.03</td><td>3.90x</td></tr>
<tr><td>BenchmarkNinOptCustomProtoMarshal</td><td>22.29</td><td>115.38</td><td>5.18x</td></tr>
<tr><td>BenchmarkNidRepCustomProtoMarshal</td><td>35.14</td><td>189.80</td><td>5.40x</td></tr>
<tr><td>BenchmarkNinRepCustomProtoMarshal</td><td>36.50</td><td>188.40</td><td>5.16x</td></tr>
<tr><td>BenchmarkNinOptNativeUnionProtoMarshal</td><td>32.87</td><td>105.39</td><td>3.21x</td></tr>
<tr><td>BenchmarkNinOptStructUnionProtoMarshal</td><td>66.40</td><td>195.76</td><td>2.95x</td></tr>
<tr><td>BenchmarkNinEmbeddedStructUnionProtoMarshal</td><td>93.24</td><td>245.26</td><td>2.63x</td></tr>
<tr><td>BenchmarkNinNestedStructUnionProtoMarshal</td><td>57.49</td><td>160.06</td><td>2.78x</td></tr>
<tr><td>BenchmarkTreeProtoMarshal</td><td>137.64</td><td>255.12</td><td>1.85x</td></tr>
<tr><td>BenchmarkOrBranchProtoMarshal</td><td>137.80</td><td>216.10</td><td>1.57x</td></tr>
<tr><td>BenchmarkAndBranchProtoMarshal</td><td>136.64</td><td>217.89</td><td>1.59x</td></tr>
<tr><td>BenchmarkLeafProtoMarshal</td><td>214.48</td><td>341.53</td><td>1.59x</td></tr>
<tr><td>BenchmarkDeepTreeProtoMarshal</td><td>95.85</td><td>173.03</td><td>1.81x</td></tr>
<tr><td>BenchmarkADeepBranchProtoMarshal</td><td>82.73</td><td>150.78</td><td>1.82x</td></tr>
<tr><td>BenchmarkAndDeepBranchProtoMarshal</td><td>96.72</td><td>153.98</td><td>1.59x</td></tr>
<tr><td>BenchmarkDeepLeafProtoMarshal</td><td>117.34</td><td>213.41</td><td>1.82x</td></tr>
<tr><td>BenchmarkNidOptEnumProtoMarshal</td><td>3.89</td><td>13.16</td><td>3.38x</td></tr>
<tr><td>BenchmarkNinOptEnumProtoMarshal</td><td>1.82</td><td>6.30</td><td>3.46x</td></tr>
<tr><td>BenchmarkNidRepEnumProtoMarshal</td><td>12.36</td><td>38.50</td><td>3.11x</td></tr>
<tr><td>BenchmarkNinRepEnumProtoMarshal</td><td>12.08</td><td>37.53</td><td>3.11x</td></tr>
<tr><td>BenchmarkTimerProtoMarshal</td><td>73.81</td><td>253.87</td><td>3.44x</td></tr>
<tr><td>BenchmarkMyExtendableProtoMarshal</td><td>13.15</td><td>43.08</td><td>3.28x</td></tr>
<tr><td>BenchmarkOtherExtenableProtoMarshal</td><td>24.28</td><td>81.09</td><td>3.34x</td></tr>
</table>
## Unmarshaler
<table>
<tr><td>benchmark</td><td>old ns/op</td><td>new ns/op</td><td>delta</td></tr>
<tr><td>BenchmarkNidOptNativeProtoUnmarshal</td><td>2521</td><td>1006</td><td>-60.10%</td></tr>
<tr><td>BenchmarkNinOptNativeProtoUnmarshal</td><td>2529</td><td>1750</td><td>-30.80%</td></tr>
<tr><td>BenchmarkNidRepNativeProtoUnmarshal</td><td>49067</td><td>35299</td><td>-28.06%</td></tr>
<tr><td>BenchmarkNinRepNativeProtoUnmarshal</td><td>47990</td><td>35456</td><td>-26.12%</td></tr>
<tr><td>BenchmarkNidRepPackedNativeProtoUnmarshal</td><td>26456</td><td>23950</td><td>-9.47%</td></tr>
<tr><td>BenchmarkNinRepPackedNativeProtoUnmarshal</td><td>26499</td><td>24037</td><td>-9.29%</td></tr>
<tr><td>BenchmarkNidOptStructProtoUnmarshal</td><td>6803</td><td>3873</td><td>-43.07%</td></tr>
<tr><td>BenchmarkNinOptStructProtoUnmarshal</td><td>6786</td><td>4154</td><td>-38.79%</td></tr>
<tr><td>BenchmarkNidRepStructProtoUnmarshal</td><td>56276</td><td>31970</td><td>-43.19%</td></tr>
<tr><td>BenchmarkNinRepStructProtoUnmarshal</td><td>48750</td><td>31832</td><td>-34.70%</td></tr>
<tr><td>BenchmarkNidEmbeddedStructProtoUnmarshal</td><td>4556</td><td>1973</td><td>-56.69%</td></tr>
<tr><td>BenchmarkNinEmbeddedStructProtoUnmarshal</td><td>4485</td><td>1975</td><td>-55.96%</td></tr>
<tr><td>BenchmarkNidNestedStructProtoUnmarshal</td><td>223395</td><td>135844</td><td>-39.19%</td></tr>
<tr><td>BenchmarkNinNestedStructProtoUnmarshal</td><td>226446</td><td>134022</td><td>-40.82%</td></tr>
<tr><td>BenchmarkNidOptCustomProtoUnmarshal</td><td>1859</td><td>300</td><td>-83.86%</td></tr>
<tr><td>BenchmarkNinOptCustomProtoUnmarshal</td><td>1486</td><td>402</td><td>-72.95%</td></tr>
<tr><td>BenchmarkNidRepCustomProtoUnmarshal</td><td>8229</td><td>1669</td><td>-79.72%</td></tr>
<tr><td>BenchmarkNinRepCustomProtoUnmarshal</td><td>8253</td><td>1649</td><td>-80.02%</td></tr>
<tr><td>BenchmarkNinOptNativeUnionProtoUnmarshal</td><td>840</td><td>307</td><td>-63.45%</td></tr>
<tr><td>BenchmarkNinOptStructUnionProtoUnmarshal</td><td>1395</td><td>639</td><td>-54.19%</td></tr>
<tr><td>BenchmarkNinEmbeddedStructUnionProtoUnmarshal</td><td>2297</td><td>1167</td><td>-49.19%</td></tr>
<tr><td>BenchmarkNinNestedStructUnionProtoUnmarshal</td><td>1820</td><td>889</td><td>-51.15%</td></tr>
<tr><td>BenchmarkTreeProtoUnmarshal</td><td>1521</td><td>720</td><td>-52.66%</td></tr>
<tr><td>BenchmarkOrBranchProtoUnmarshal</td><td>2669</td><td>1385</td><td>-48.11%</td></tr>
<tr><td>BenchmarkAndBranchProtoUnmarshal</td><td>2667</td><td>1420</td><td>-46.76%</td></tr>
<tr><td>BenchmarkLeafProtoUnmarshal</td><td>1171</td><td>584</td><td>-50.13%</td></tr>
<tr><td>BenchmarkDeepTreeProtoUnmarshal</td><td>2065</td><td>1081</td><td>-47.65%</td></tr>
<tr><td>BenchmarkADeepBranchProtoUnmarshal</td><td>2695</td><td>1178</td><td>-56.29%</td></tr>
<tr><td>BenchmarkAndDeepBranchProtoUnmarshal</td><td>4055</td><td>1918</td><td>-52.70%</td></tr>
<tr><td>BenchmarkDeepLeafProtoUnmarshal</td><td>1758</td><td>865</td><td>-50.80%</td></tr>
<tr><td>BenchmarkNilProtoUnmarshal</td><td>564</td><td>63</td><td>-88.79%</td></tr>
<tr><td>BenchmarkNidOptEnumProtoUnmarshal</td><td>762</td><td>73</td><td>-90.34%</td></tr>
<tr><td>BenchmarkNinOptEnumProtoUnmarshal</td><td>764</td><td>163</td><td>-78.66%</td></tr>
<tr><td>BenchmarkNidRepEnumProtoUnmarshal</td><td>1078</td><td>447</td><td>-58.53%</td></tr>
<tr><td>BenchmarkNinRepEnumProtoUnmarshal</td><td>1071</td><td>479</td><td>-55.28%</td></tr>
<tr><td>BenchmarkTimerProtoUnmarshal</td><td>1128</td><td>362</td><td>-67.91%</td></tr>
<tr><td>BenchmarkMyExtendableProtoUnmarshal</td><td>808</td><td>217</td><td>-73.14%</td></tr>
<tr><td>BenchmarkOtherExtenableProtoUnmarshal</td><td>1233</td><td>517</td><td>-58.07%</td></tr>
</table>
<table>
<tr><td>benchmark</td><td>old MB/s</td><td>new MB/s</td><td>speedup</td></tr>
<tr><td>BenchmarkNidOptNativeProtoUnmarshal</td><td>133.67</td><td>334.98</td><td>2.51x</td></tr>
<tr><td>BenchmarkNinOptNativeProtoUnmarshal</td><td>119.77</td><td>173.08</td><td>1.45x</td></tr>
<tr><td>BenchmarkNidRepNativeProtoUnmarshal</td><td>143.23</td><td>199.12</td><td>1.39x</td></tr>
<tr><td>BenchmarkNinRepNativeProtoUnmarshal</td><td>146.07</td><td>198.16</td><td>1.36x</td></tr>
<tr><td>BenchmarkNidRepPackedNativeProtoUnmarshal</td><td>127.80</td><td>141.04</td><td>1.10x</td></tr>
<tr><td>BenchmarkNinRepPackedNativeProtoUnmarshal</td><td>127.55</td><td>140.78</td><td>1.10x</td></tr>
<tr><td>BenchmarkNidOptStructProtoUnmarshal</td><td>185.79</td><td>326.31</td><td>1.76x</td></tr>
<tr><td>BenchmarkNinOptStructProtoUnmarshal</td><td>167.68</td><td>273.66</td><td>1.63x</td></tr>
<tr><td>BenchmarkNidRepStructProtoUnmarshal</td><td>147.88</td><td>260.39</td><td>1.76x</td></tr>
<tr><td>BenchmarkNinRepStructProtoUnmarshal</td><td>171.20</td><td>261.97</td><td>1.53x</td></tr>
<tr><td>BenchmarkNidEmbeddedStructProtoUnmarshal</td><td>142.86</td><td>329.42</td><td>2.31x</td></tr>
<tr><td>BenchmarkNinEmbeddedStructProtoUnmarshal</td><td>137.33</td><td>311.83</td><td>2.27x</td></tr>
<tr><td>BenchmarkNidNestedStructProtoUnmarshal</td><td>154.97</td><td>259.47</td><td>1.67x</td></tr>
<tr><td>BenchmarkNinNestedStructProtoUnmarshal</td><td>154.32</td><td>258.42</td><td>1.67x</td></tr>
<tr><td>BenchmarkNidOptCustomProtoUnmarshal</td><td>19.36</td><td>119.66</td><td>6.18x</td></tr>
<tr><td>BenchmarkNinOptCustomProtoUnmarshal</td><td>21.52</td><td>79.50</td><td>3.69x</td></tr>
<tr><td>BenchmarkNidRepCustomProtoUnmarshal</td><td>17.62</td><td>86.86</td><td>4.93x</td></tr>
<tr><td>BenchmarkNinRepCustomProtoUnmarshal</td><td>17.57</td><td>87.92</td><td>5.00x</td></tr>
<tr><td>BenchmarkNinOptNativeUnionProtoUnmarshal</td><td>38.07</td><td>104.12</td><td>2.73x</td></tr>
<tr><td>BenchmarkNinOptStructUnionProtoUnmarshal</td><td>73.08</td><td>159.54</td><td>2.18x</td></tr>
<tr><td>BenchmarkNinEmbeddedStructUnionProtoUnmarshal</td><td>94.00</td><td>185.92</td><td>1.98x</td></tr>
<tr><td>BenchmarkNinNestedStructUnionProtoUnmarshal</td><td>65.35</td><td>133.75</td><td>2.05x</td></tr>
<tr><td>BenchmarkTreeProtoUnmarshal</td><td>141.28</td><td>297.13</td><td>2.10x</td></tr>
<tr><td>BenchmarkOrBranchProtoUnmarshal</td><td>162.56</td><td>313.96</td><td>1.93x</td></tr>
<tr><td>BenchmarkAndBranchProtoUnmarshal</td><td>163.06</td><td>306.15</td><td>1.88x</td></tr>
<tr><td>BenchmarkLeafProtoUnmarshal</td><td>176.72</td><td>354.19</td><td>2.00x</td></tr>
<tr><td>BenchmarkDeepTreeProtoUnmarshal</td><td>107.50</td><td>205.30</td><td>1.91x</td></tr>
<tr><td>BenchmarkADeepBranchProtoUnmarshal</td><td>83.48</td><td>190.88</td><td>2.29x</td></tr>
<tr><td>BenchmarkAndDeepBranchProtoUnmarshal</td><td>110.97</td><td>234.60</td><td>2.11x</td></tr>
<tr><td>BenchmarkDeepLeafProtoUnmarshal</td><td>123.40</td><td>250.73</td><td>2.03x</td></tr>
<tr><td>BenchmarkNidOptEnumProtoUnmarshal</td><td>2.62</td><td>27.16</td><td>10.37x</td></tr>
<tr><td>BenchmarkNinOptEnumProtoUnmarshal</td><td>1.31</td><td>6.11</td><td>4.66x</td></tr>
<tr><td>BenchmarkNidRepEnumProtoUnmarshal</td><td>7.42</td><td>17.88</td><td>2.41x</td></tr>
<tr><td>BenchmarkNinRepEnumProtoUnmarshal</td><td>7.47</td><td>16.69</td><td>2.23x</td></tr>
<tr><td>BenchmarkTimerProtoUnmarshal</td><td>61.12</td><td>190.34</td><td>3.11x</td></tr>
<tr><td>BenchmarkMyExtendableProtoUnmarshal</td><td>9.90</td><td>36.71</td><td>3.71x</td></tr>
<tr><td>BenchmarkOtherExtenableProtoUnmarshal</td><td>21.90</td><td>52.13</td><td>2.38x</td></tr>
</table>

View File

@@ -1,91 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package codec
import (
"github.com/gogo/protobuf/proto"
)
type Codec interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
String() string
}
type marshaler interface {
MarshalTo(data []byte) (n int, err error)
}
func getSize(v interface{}) (int, bool) {
if sz, ok := v.(interface {
Size() (n int)
}); ok {
return sz.Size(), true
} else if sz, ok := v.(interface {
ProtoSize() (n int)
}); ok {
return sz.ProtoSize(), true
} else {
return 0, false
}
}
type codec struct {
buf []byte
}
func (this *codec) String() string {
return "proto"
}
func New(size int) Codec {
return &codec{make([]byte, size)}
}
func (this *codec) Marshal(v interface{}) ([]byte, error) {
if m, ok := v.(marshaler); ok {
n, ok := getSize(v)
if !ok {
return proto.Marshal(v.(proto.Message))
}
if n > len(this.buf) {
this.buf = make([]byte, n)
}
_, err := m.MarshalTo(this.buf)
if err != nil {
return nil, err
}
return this.buf[:n], nil
}
return proto.Marshal(v.(proto.Message))
}
func (this *codec) Unmarshal(data []byte, v interface{}) error {
return proto.Unmarshal(data, v.(proto.Message))
}

View File

@@ -1,54 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package codec
import (
"github.com/gogo/protobuf/test"
"math/rand"
"testing"
"time"
)
func TestCodec(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
in := test.NewPopulatedNinOptStruct(r, true)
c := New(r.Intn(1024))
data, err := c.Marshal(in)
if err != nil {
t.Fatal(err)
}
out := &test.NinOptStruct{}
err = c.Unmarshal(data, out)
if err != nil {
t.Fatal(err)
}
if err := in.VerboseEqual(out); err != nil {
t.Fatal(err)
}
}

View File

@@ -1,167 +0,0 @@
# gogoprotobuf Extensions
Here is an [example.proto](https://github.com/gogo/protobuf/blob/master/test/example/example.proto) which uses most of the gogoprotobuf code generation plugins.
Please also look at the example [Makefile](https://github.com/gogo/protobuf/blob/master/test/example/Makefile) which shows how to specify the `descriptor.proto` and `gogo.proto` in your proto_path
The documentation at [http://godoc.org/github.com/gogo/protobuf/gogoproto](http://godoc.org/github.com/gogo/protobuf/gogoproto) describes the extensions made to goprotobuf in more detail.
Also see [http://godoc.org/github.com/gogo/protobuf/plugin/](http://godoc.org/github.com/gogo/protobuf/plugin/) for documentation of each of the extensions which have their own plugins.
# Fast Marshalling and Unmarshalling
Generating a `Marshal`, `MarshalTo`, `Size` (or `ProtoSize`) and `Unmarshal` method for a struct results in faster marshalling and unmarshalling than when using reflect.
See [BenchComparison](https://github.com/gogo/protobuf/blob/master/bench.md) for a comparison between reflect and generated code used for marshalling and unmarshalling.
<table>
<tr><td><b>Name</b></td><td><b>Option</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Default</b></td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/marshalto">marshaler</a></td><td>Message</td><td>bool</td><td>if true, a Marshal and MarshalTo method is generated for the specific message</td><td>false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/size">sizer</a></td><td>Message</td><td>bool</td><td>if true, a Size method is generated for the specific message</td><td>false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/unmarshal">unmarshaler</a></td><td> Message </td><td> bool </td><td> if true, an Unmarshal method is generated for the specific message </td><td> false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/size">protosizer</a></td><td>Message</td><td>bool</td><td>if true, a ProtoSize method is generated for the specific message</td><td>false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/marshalto"> unsafe_marshaler</a> </td><td> Message </td><td> bool </td><td> if true, a Marshal and MarshalTo method is generated for the specific message. The generated code uses the unsafe package. </td><td> false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/unmarshal">unsafe_unmarshaler</a></td><td> Message </td><td> bool </td><td> if true, an Unmarshal method is generated for the specific message. The generated code uses the unsafe package. </td><td> false</td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/marshalto">stable_marshaler</a></td><td> Message </td><td> bool </td><td> if true, a Marshal and MarshalTo method is generated for the specific message, but unlike marshaler the output is guaranteed to be deterministic, at the sacrifice of some speed</td><td> false </td></tr>
</table>
# More Canonical Go Structures
Lots of times working with a goprotobuf struct will lead you to a place where you create another struct that is easier to work with and then have a function to copy the values between the two structs.
You might also find that basic structs that started their life as part of an API need to be sent over the wire. With gob, you could just send it. With goprotobuf, you need to make a new struct.
`gogoprotobuf` tries to fix these problems with the nullable, embed, customtype, customname, casttype, castkey and castvalue field extensions.
<table>
<tr><td><b>Name</b></td><td><b>Option</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Default</b></td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto">nullable</a></td><td> Field </td><td> bool </td><td> if false, a field is generated without a pointer (see warning below). </td><td> true </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto">embed</a></td><td> Field </td><td> bool </td><td> if true, the field is generated as an embedded field. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto">customtype</a> </td><td> Field </td><td> string </td><td> It works with the Marshal and Unmarshal methods, to allow you to have your own types in your struct, but marshal to bytes. For example, custom.Uuid or custom.Fixed128 </td><td> goprotobuf type </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto"> customname</a> (beta) </td><td> Field </td><td> string </td><td> Changes the generated fieldname. This is especially useful when generated methods conflict with fieldnames. </td><td> goprotobuf field name </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto"> casttype</a> (beta) </td><td> Field </td><td> string </td><td> Changes the generated field type. It assumes that this type is castable to the original goprotobuf field type. It currently does not support maps, structs or enums. </td><td> goprotobuf field type </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto"> castkey </a> (beta) </td><td> Field </td><td> string </td><td> Changes the generated fieldtype for a map key. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps. </td><td> goprotobuf field type </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/gogoproto"> castvalue </a> (beta) </td><td> Field </td><td> string </td><td> Changes the generated fieldtype for a map value. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps. </td><td> goprotobuf field type </td></tr>
<tr><td>enum_customname (beta)</td><td> Enum </td><td> string </td><td>Sets the type name of an enum. If goproto_enum_prefix is enabled, this value will be used as a prefix when generating enum values.</td><td>goprotobuf enum type name. Helps with golint issues.</td></tr>
<tr><td>enumvalue_customname (beta) </td><td> Enum Value </td><td> string </td><td>Changes the generated enum name. Helps with golint issues.</td><td>goprotobuf enum value name</td></tr>
<tr><td><a href="https://github.com/gogo/protobuf/blob/master/test/types/types.proto">stdtime</a></td><td> Timestamp Field </td><td> bool </td><td>Changes the Well Known Timestamp Type to time.Time</td><td>Timestamp</td></tr>
<tr><td><a href="https://github.com/gogo/protobuf/blob/master/test/types/types.proto">stdduration</a></td><td> Duration Field </td><td> bool </td><td>Changes the Well Known Duration Type to time.Duration</td><td>Duration</td></tr>
</table>
`Warning about nullable: according to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set.`
`Warning about customtype: It is your responsibility to test all cases of your marshaling, unmarshaling and size methods implemented for your custom type.`
Issues with customtype include:
* <a href="https://github.com/gogo/protobuf/issues/199">A Bytes method is not allowed.<a/>
* <a href="https://github.com/gogo/protobuf/issues/132">Defining a customtype as a fake proto message is broken.</a>
* <a href="https://github.com/gogo/protobuf/issues/147">proto.Clone is broken.</a>
* <a href="https://github.com/gogo/protobuf/issues/125">Using a proto message as a customtype is not allowed.</a>
* <a href="https://github.com/gogo/protobuf/issues/200">cusomtype of type map can not UnmarshalText</a>
* <a href="https://github.com/gogo/protobuf/issues/201">customtype of type struct cannot jsonpb unmarshal</a>
# Goprotobuf Compatibility
Gogoprotobuf is compatible with Goprotobuf, because it is compatible with protocol buffers (see the section on tests below).
Gogoprotobuf generates the same code as goprotobuf if no extensions are used.
The enumprefix, getters and stringer extensions can be used to remove some of the unnecessary code generated by goprotobuf.
<table>
<tr><td><b>Name</b></td><td><b>Option</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Default</b></td></tr>
<tr><td> gogoproto_import </td><td> File </td><td> bool </td><td> if false, the generated code imports github.com/golang/protobuf/proto instead of github.com/gogo/protobuf/proto. </td><td> true </td></tr>
<tr><td> goproto_enum_prefix </td><td> Enum </td><td> bool </td><td> if false, generates the enum constant names without the messagetype prefix </td><td> true </td></tr>
<tr><td> goproto_getters </td><td> Message </td><td> bool </td><td> if false, the message is generated without get methods, this is useful when you would rather want to use face </td><td> true </td></tr>
<tr><td> goproto_stringer </td><td> Message </td><td> bool </td><td> if false, the message is generated without the default string method, this is useful for rather using stringer </td><td> true </td></tr>
<tr><td> goproto_enum_stringer (experimental) </td><td> Enum </td><td> bool </td><td> if false, the enum is generated without the default string method, this is useful for rather using enum_stringer </td><td> true </td></tr>
<tr><td> goproto_extensions_map (beta) </td><td> Message </td><td> bool </td><td> if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension </td><td> true </td></tr>
<tr><td> goproto_unrecognized (beta) </td><td> Message </td><td> bool </td><td>if false, XXX_unrecognized field is not generated. This is useful to reduce GC pressure at the cost of losing information about unrecognized fields. </td><td> true </td></tr>
</table>
# Less Typing
The Protocol Buffer language is very parseable and extra code can be easily generated for structures.
Helper methods, functions and interfaces can be generated by triggering certain extensions like gostring.
<table>
<tr><td><b>Name</b></td><td><b>Option</b></td><td><b>Type</b></td><td><b>Description</b></td><td><b>Default</b></td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/gostring">gostring</a></td><td> Message </td><td> bool </td><td> if true, a `GoString` method is generated. This returns a string representing valid go code to reproduce the current state of the struct. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/union"> onlyone</a> (deprecated) </td><td> Message </td><td> bool </td><td> if true, all fields must be nullable and only one of the fields may be set, like a union. Two methods are generated: `GetValue() interface{}` and `SetValue(v interface{}) (set bool)`. These provide easier interaction with a union. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/equal"> equal</a></td><td> Message </td><td> bool </td><td> if true, an Equal method is generated </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/compare"> compare</a></td><td> Message </td><td> bool </td><td> if true, a Compare method is generated. This is very useful for quickly implementing sort on a list of protobuf structs </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/equal"> verbose_equal</a> </td><td> Message </td><td> bool </td><td> if true, a verbose equal method is generated for the message. This returns an error which describes the exact element which is not equal to the exact element in the other struct. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/stringer"> stringer</a> </td><td> Message </td><td> bool </td><td> if true, a String method is generated for the message. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/face">face</a> </td><td> Message </td><td> bool </td><td> if true, a function will be generated which can convert a structure which satisfies an interface (face) to the specified structure. This interface contains getters for each of the fields in the struct. The specified struct is also generated with the getters. This allows it to satisfy its own face. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/description"> description</a> (beta) </td><td> Message </td><td> bool </td><td> if true, a Description method is generated for the message. </td><td> false </td></tr>
<tr><td> <a href="http://godoc.org/github.com/gogo/protobuf/plugin/populate"> populate</a> </td><td> Message </td><td> bool </td><td> if true, a `NewPopulated<MessageName>` function is generated. This is necessary for generated tests. </td><td> false </td></tr>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/enumstringer"> enum_stringer</a> (experimental) </td><td> Enum </td><td> bool </td><td> if true, a String method is generated for an Enum </td><td> false </td></tr>
</table>
Issues with Compare include:
* <a href="https://github.com/gogo/protobuf/issues/221">Oneof is not supported yet</a>
* <a href="https://github.com/gogo/protobuf/issues/230">Not all Well Known Types are supported yet</a>
* <a href="https://github.com/gogo/protobuf/issues/231">Maps are not supported</a>
#Peace of Mind
Test and Benchmark generation is done with the following extensions:
<table>
<tr><td><a href="http://godoc.org/github.com/gogo/protobuf/plugin/testgen">testgen</a> </td><td> Message </td><td> bool </td><td> if true, tests are generated for proto, json and prototext marshalling as well as for some of the other enabled plugins </td><td> false </td></tr>
<tr><td> benchgen </td><td> Message </td><td> bool </td><td> if true, benchmarks are generated for proto, json and prototext marshalling as well as for some of the other enabled plugins </td><td> false </td></tr>
</table>
# More Serialization Formats
Other serialization formats like xml and json typically use reflect to marshal and unmarshal structured data. Manipulating these structs into something other than the default Go requires editing tags. The following extensions provide ways of editing these tags for the generated protobuf structs.
<table>
<tr><td><a href="https://github.com/gogo/protobuf/blob/master/test/tags/tags.proto">jsontag</a> (beta) </td><td> Field </td><td> string </td><td> if set, the json tag value between the double quotes is replaced with this string </td><td> fieldname </td></tr>
<tr><td><a href="https://github.com/gogo/protobuf/blob/master/test/tags/tags.proto">moretags</a> (beta) </td><td> Field </td><td> string </td><td> if set, this string is appended to the tag string </td><td> empty </td></tr>
</table>
<a href="https://groups.google.com/forum/#!topic/gogoprotobuf/xmFnqAS6MIc">Here is a longer explanation of jsontag and moretags</a>
# File Options
Each of the boolean message and enum extensions also have a file extension:
* `marshaler_all`
* `sizer_all`
* `protosizer_all`
* `unmarshaler_all`
* `unsafe_marshaler_all`
* `unsafe_unmarshaler_all`
* `stable_marshaler_all`
* `goproto_enum_prefix_all`
* `goproto_getters_all`
* `goproto_stringer_all`
* `goproto_enum_stringer_all`
* `goproto_extensions_map_all`
* `goproto_unrecognized_all`
* `gostring_all`
* `onlyone_all`
* `equal_all`
* `compare_all`
* `verbose_equal_all`
* `stringer_all`
* `enum_stringer_all`
* `face_all`
* `description_all`
* `populate_all`
* `testgen_all`
* `benchgen_all`
Each of these are the same as their Message Option counterparts, except they apply to all messages in the file. Their Message option counterparts can also be used to overwrite their effect.
# Tests
* The normal barrage of tests are run with: `make tests`
* A few weird tests: `make testall`
* Tests for compatibility with [golang/protobuf](https://github.com/golang/protobuf) are handled by a different project [harmonytests](https://github.com/gogo/harmonytests), since it requires goprotobuf.
* Cross version tests are made with [Travis CI](https://travis-ci.org/gogo/protobuf).
* GRPC Tests are also handled by a different project [grpctests](https://github.com/gogo/grpctests), since it depends on a lot of grpc libraries.
* Thanks to [go-fuzz](https://github.com/dvyukov/go-fuzz/) we have proper [fuzztests](https://github.com/gogo/fuzztests).

View File

@@ -1,37 +0,0 @@
# Protocol Buffers for Go with Gadgets
#
# Copyright (c) 2013, The GoGo Authors. All rights reserved.
# http://github.com/gogo/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
regenerate:
go install github.com/gogo/protobuf/protoc-gen-gogo
protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. --proto_path=../../../../:../protobuf/:. *.proto
restore:
cp gogo.pb.golden gogo.pb.go
preserve:
cp gogo.pb.go gogo.pb.golden

View File

@@ -148,6 +148,7 @@ The enumprefix, getters and stringer extensions can be used to remove some of th
- goproto_stringer, if false, the message is generated without the default string method, this is useful for rather using stringer, or allowing you to write your own string method.
- goproto_extensions_map (beta), if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension
- goproto_unrecognized (beta), if false, XXX_unrecognized field is not generated. This is useful in conjunction with gogoproto.nullable=false, to generate structures completely devoid of pointers and reduce GC pressure at the cost of losing information about unrecognized fields.
- goproto_registration (beta), if true, the generated files will register all messages and types against both gogo/protobuf and golang/protobuf. This is necessary when using third-party packages which read registrations from golang/protobuf (such as the grpc-gateway).
Less Typing and Peace of Mind is explained in their specific plugin folders godoc:

View File

@@ -64,6 +64,15 @@ var E_EnumCustomname = &proto.ExtensionDesc{
Filename: "gogo.proto",
}
var E_Enumdecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62024,
Name: "gogoproto.enumdecl",
Tag: "varint,62024,opt,name=enumdecl",
Filename: "gogo.proto",
}
var E_EnumvalueCustomname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
ExtensionType: (*string)(nil),
@@ -307,6 +316,33 @@ var E_CompareAll = &proto.ExtensionDesc{
Filename: "gogo.proto",
}
var E_TypedeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63030,
Name: "gogoproto.typedecl_all",
Tag: "varint,63030,opt,name=typedecl_all,json=typedeclAll",
Filename: "gogo.proto",
}
var E_EnumdeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63031,
Name: "gogoproto.enumdecl_all",
Tag: "varint,63031,opt,name=enumdecl_all,json=enumdeclAll",
Filename: "gogo.proto",
}
var E_GoprotoRegistration = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63032,
Name: "gogoproto.goproto_registration",
Tag: "varint,63032,opt,name=goproto_registration,json=goprotoRegistration",
Filename: "gogo.proto",
}
var E_GoprotoGetters = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
@@ -505,6 +541,15 @@ var E_Compare = &proto.ExtensionDesc{
Filename: "gogo.proto",
}
var E_Typedecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64030,
Name: "gogoproto.typedecl",
Tag: "varint,64030,opt,name=typedecl",
Filename: "gogo.proto",
}
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
@@ -609,6 +654,7 @@ func init() {
proto.RegisterExtension(E_GoprotoEnumStringer)
proto.RegisterExtension(E_EnumStringer)
proto.RegisterExtension(E_EnumCustomname)
proto.RegisterExtension(E_Enumdecl)
proto.RegisterExtension(E_EnumvalueCustomname)
proto.RegisterExtension(E_GoprotoGettersAll)
proto.RegisterExtension(E_GoprotoEnumPrefixAll)
@@ -636,6 +682,9 @@ func init() {
proto.RegisterExtension(E_GogoprotoImport)
proto.RegisterExtension(E_ProtosizerAll)
proto.RegisterExtension(E_CompareAll)
proto.RegisterExtension(E_TypedeclAll)
proto.RegisterExtension(E_EnumdeclAll)
proto.RegisterExtension(E_GoprotoRegistration)
proto.RegisterExtension(E_GoprotoGetters)
proto.RegisterExtension(E_GoprotoStringer)
proto.RegisterExtension(E_VerboseEqual)
@@ -658,6 +707,7 @@ func init() {
proto.RegisterExtension(E_GoprotoUnrecognized)
proto.RegisterExtension(E_Protosizer)
proto.RegisterExtension(E_Compare)
proto.RegisterExtension(E_Typedecl)
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
@@ -674,76 +724,81 @@ func init() {
func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
var fileDescriptorGogo = []byte{
// 1129 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x97, 0xc9, 0x6f, 0x1c, 0x45,
0x14, 0x87, 0x85, 0x70, 0x64, 0xcf, 0xf3, 0x86, 0xc7, 0xc6, 0x84, 0x08, 0x44, 0x72, 0xe3, 0xe4,
0x9c, 0x22, 0x94, 0xb2, 0x22, 0xcb, 0xb1, 0x9c, 0x51, 0x10, 0x86, 0x91, 0x89, 0x03, 0x88, 0xc3,
0xa8, 0x67, 0xa6, 0xdc, 0x69, 0xe8, 0xee, 0x6a, 0xba, 0xaa, 0xa3, 0x38, 0x37, 0x14, 0x16, 0x21,
0xc4, 0x8e, 0x04, 0x09, 0x09, 0xcb, 0x81, 0x7d, 0x0d, 0xcb, 0x9d, 0x0b, 0x70, 0xe6, 0x7f, 0xe0,
0x02, 0x84, 0xdd, 0x37, 0x5f, 0x50, 0x75, 0xbf, 0xd7, 0x53, 0xdd, 0x1e, 0xa9, 0x6a, 0x6e, 0xe3,
0x71, 0x7d, 0xdf, 0x54, 0xbf, 0x37, 0xf5, 0x7e, 0x53, 0x00, 0xbe, 0xf0, 0xc5, 0x52, 0x92, 0x0a,
0x25, 0x9a, 0x0d, 0xfd, 0x3a, 0x7f, 0x79, 0xe8, 0xb0, 0x2f, 0x84, 0x1f, 0xf2, 0xa3, 0xf9, 0x5f,
0xdd, 0x6c, 0xfb, 0x68, 0x9f, 0xcb, 0x5e, 0x1a, 0x24, 0x4a, 0xa4, 0xc5, 0x62, 0x76, 0x3f, 0xcc,
0xe3, 0xe2, 0x0e, 0x8f, 0xb3, 0xa8, 0x93, 0xa4, 0x7c, 0x3b, 0xb8, 0xd0, 0xbc, 0x63, 0xa9, 0x20,
0x97, 0x88, 0x5c, 0x5a, 0x8f, 0xb3, 0xe8, 0x81, 0x44, 0x05, 0x22, 0x96, 0x07, 0xaf, 0xff, 0x72,
0xf3, 0xe1, 0x9b, 0xee, 0x9e, 0xd8, 0x9c, 0x43, 0x54, 0xff, 0xaf, 0x9d, 0x83, 0x6c, 0x13, 0x6e,
0xad, 0xf8, 0xa4, 0x4a, 0x83, 0xd8, 0xe7, 0xa9, 0xc5, 0xf8, 0x03, 0x1a, 0xe7, 0x0d, 0xe3, 0x83,
0x88, 0xb2, 0x35, 0x98, 0x1e, 0xc5, 0xf5, 0x23, 0xba, 0xa6, 0xb8, 0x29, 0x69, 0xc1, 0x6c, 0x2e,
0xe9, 0x65, 0x52, 0x89, 0x28, 0xf6, 0x22, 0x6e, 0xd1, 0xfc, 0x94, 0x6b, 0x1a, 0x9b, 0x33, 0x1a,
0x5b, 0x2b, 0x29, 0x76, 0x16, 0x16, 0xf4, 0x3b, 0xe7, 0xbd, 0x30, 0xe3, 0xa6, 0xed, 0xc8, 0x50,
0xdb, 0x59, 0xbd, 0x8c, 0x94, 0x3f, 0x5f, 0x1a, 0xcb, 0x95, 0xf3, 0xa5, 0xc0, 0xf0, 0x1a, 0x9d,
0xf0, 0xb9, 0x52, 0x3c, 0x95, 0x1d, 0x2f, 0x0c, 0x87, 0x6c, 0xf2, 0x54, 0x10, 0x96, 0xc6, 0xcb,
0x37, 0xaa, 0x9d, 0x68, 0x15, 0xe4, 0x6a, 0x18, 0xb2, 0x2d, 0xb8, 0x6d, 0x48, 0x67, 0x1d, 0x9c,
0x57, 0xd0, 0xb9, 0xb0, 0xaf, 0xbb, 0x5a, 0xdb, 0x06, 0x7a, 0xbf, 0xec, 0x87, 0x83, 0xf3, 0x2d,
0x74, 0x36, 0x91, 0xa5, 0xb6, 0x68, 0xe3, 0xbd, 0x30, 0x77, 0x9e, 0xa7, 0x5d, 0x21, 0x79, 0x87,
0x3f, 0x91, 0x79, 0xa1, 0x83, 0xee, 0x2a, 0xea, 0x66, 0x11, 0x5c, 0xd7, 0x9c, 0x76, 0x1d, 0x87,
0x89, 0x6d, 0xaf, 0xc7, 0x1d, 0x14, 0xd7, 0x50, 0x31, 0xae, 0xd7, 0x6b, 0x74, 0x15, 0xa6, 0x7c,
0x51, 0x3c, 0x92, 0x03, 0xfe, 0x36, 0xe2, 0x93, 0xc4, 0xa0, 0x22, 0x11, 0x49, 0x16, 0x7a, 0xca,
0x65, 0x07, 0xef, 0x90, 0x82, 0x18, 0x54, 0x8c, 0x50, 0xd6, 0x77, 0x49, 0x21, 0x8d, 0x7a, 0xae,
0xc0, 0xa4, 0x88, 0xc3, 0x1d, 0x11, 0xbb, 0x6c, 0xe2, 0x3d, 0x34, 0x00, 0x22, 0x5a, 0xb0, 0x0c,
0x0d, 0xd7, 0x46, 0xbc, 0x8f, 0xf8, 0x04, 0xa7, 0x0e, 0xb4, 0x60, 0x96, 0x86, 0x4c, 0x20, 0x62,
0x07, 0xc5, 0x07, 0xa8, 0x98, 0x31, 0x30, 0x7c, 0x0c, 0xc5, 0xa5, 0xf2, 0xb9, 0x8b, 0xe4, 0x43,
0x7a, 0x0c, 0x44, 0xb0, 0x94, 0x5d, 0x1e, 0xf7, 0xce, 0xb9, 0x19, 0x3e, 0xa2, 0x52, 0x12, 0xa3,
0x15, 0x6b, 0x30, 0x1d, 0x79, 0xa9, 0x3c, 0xe7, 0x85, 0x4e, 0xed, 0xf8, 0x18, 0x1d, 0x53, 0x25,
0x84, 0x15, 0xc9, 0xe2, 0x51, 0x34, 0x9f, 0x50, 0x45, 0x0c, 0x0c, 0x8f, 0x9e, 0x54, 0x5e, 0x37,
0xe4, 0x9d, 0x51, 0x6c, 0x9f, 0xd2, 0xd1, 0x2b, 0xd8, 0x0d, 0xd3, 0xb8, 0x0c, 0x0d, 0x19, 0x5c,
0x74, 0xd2, 0x7c, 0x46, 0x9d, 0xce, 0x01, 0x0d, 0x3f, 0x02, 0xb7, 0x0f, 0x1d, 0xf5, 0x0e, 0xb2,
0xcf, 0x51, 0xb6, 0x38, 0x64, 0xdc, 0xe3, 0x48, 0x18, 0x55, 0xf9, 0x05, 0x8d, 0x04, 0x5e, 0x73,
0xb5, 0x61, 0x21, 0x8b, 0xa5, 0xb7, 0x3d, 0x5a, 0xd5, 0xbe, 0xa4, 0xaa, 0x15, 0x6c, 0xa5, 0x6a,
0x67, 0x60, 0x11, 0x8d, 0xa3, 0xf5, 0xf5, 0x2b, 0x1a, 0xac, 0x05, 0xbd, 0x55, 0xed, 0xee, 0xa3,
0x70, 0xa8, 0x2c, 0xe7, 0x05, 0xc5, 0x63, 0xa9, 0x99, 0x4e, 0xe4, 0x25, 0x0e, 0xe6, 0xeb, 0x68,
0xa6, 0x89, 0xbf, 0x5e, 0x0a, 0x36, 0xbc, 0x44, 0xcb, 0x1f, 0x86, 0x83, 0x24, 0xcf, 0xe2, 0x94,
0xf7, 0x84, 0x1f, 0x07, 0x17, 0x79, 0xdf, 0x41, 0xfd, 0x75, 0xad, 0x55, 0x5b, 0x06, 0xae, 0xcd,
0xa7, 0xe1, 0x96, 0xf2, 0xf7, 0x46, 0x27, 0x88, 0x12, 0x91, 0x2a, 0x8b, 0xf1, 0x1b, 0xea, 0x54,
0xc9, 0x9d, 0xce, 0x31, 0xb6, 0x0e, 0x33, 0xf9, 0x9f, 0xae, 0x5f, 0xc9, 0x6f, 0x51, 0x34, 0x3d,
0xa0, 0x70, 0x70, 0xf4, 0x44, 0x94, 0x78, 0xa9, 0xcb, 0xfc, 0xfb, 0x8e, 0x06, 0x07, 0x22, 0xc5,
0xb7, 0x6f, 0xb6, 0x96, 0xc4, 0xcd, 0xbb, 0xf6, 0x49, 0x36, 0xb8, 0x94, 0x9e, 0x5f, 0x7a, 0x9e,
0xdc, 0xc5, 0x33, 0x5b, 0x0d, 0x62, 0x76, 0x9f, 0x2e, 0x4f, 0x35, 0x2e, 0xed, 0xb2, 0x4b, 0xbb,
0x65, 0x85, 0x2a, 0x69, 0xc9, 0x4e, 0xc1, 0x74, 0x25, 0x2a, 0xed, 0xaa, 0xa7, 0x50, 0x35, 0x65,
0x26, 0x25, 0x3b, 0x06, 0x63, 0x3a, 0xf6, 0xec, 0xf8, 0xd3, 0x88, 0xe7, 0xcb, 0xd9, 0x09, 0x98,
0xa0, 0xb8, 0xb3, 0xa3, 0xcf, 0x20, 0x5a, 0x22, 0x1a, 0xa7, 0xa8, 0xb3, 0xe3, 0xcf, 0x12, 0x4e,
0x88, 0xc6, 0xdd, 0x4b, 0xf8, 0xfd, 0xf3, 0x63, 0x38, 0xae, 0xa8, 0x76, 0xcb, 0x30, 0x8e, 0x19,
0x67, 0xa7, 0x9f, 0xc3, 0x0f, 0x27, 0x82, 0xdd, 0x03, 0x07, 0x1c, 0x0b, 0xfe, 0x02, 0xa2, 0xc5,
0x7a, 0xb6, 0x06, 0x93, 0x46, 0xae, 0xd9, 0xf1, 0x17, 0x11, 0x37, 0x29, 0xbd, 0x75, 0xcc, 0x35,
0xbb, 0xe0, 0x25, 0xda, 0x3a, 0x12, 0xba, 0x6c, 0x14, 0x69, 0x76, 0xfa, 0x65, 0xaa, 0x3a, 0x21,
0x6c, 0x05, 0x1a, 0xe5, 0x98, 0xb2, 0xf3, 0xaf, 0x20, 0x3f, 0x60, 0x74, 0x05, 0x8c, 0x31, 0x69,
0x57, 0xbc, 0x4a, 0x15, 0x30, 0x28, 0x7d, 0x8c, 0xea, 0xd1, 0x67, 0x37, 0xbd, 0x46, 0xc7, 0xa8,
0x96, 0x7c, 0xba, 0x9b, 0xf9, 0xb4, 0xb0, 0x2b, 0x5e, 0xa7, 0x6e, 0xe6, 0xeb, 0xf5, 0x36, 0xea,
0x59, 0x62, 0x77, 0xbc, 0x41, 0xdb, 0xa8, 0x45, 0x09, 0x6b, 0x43, 0x73, 0x7f, 0x8e, 0xd8, 0x7d,
0x6f, 0xa2, 0x6f, 0x6e, 0x5f, 0x8c, 0xb0, 0x87, 0x60, 0x71, 0x78, 0x86, 0xd8, 0xad, 0x97, 0x77,
0x6b, 0xbf, 0xfa, 0xcd, 0x08, 0x61, 0x67, 0x06, 0xbf, 0xfa, 0xcd, 0xfc, 0xb0, 0x6b, 0xaf, 0xec,
0x56, 0x2f, 0x76, 0x66, 0x7c, 0xb0, 0x55, 0x80, 0xc1, 0xe8, 0xb6, 0xbb, 0xae, 0xa2, 0xcb, 0x80,
0xf4, 0xd1, 0xc0, 0xc9, 0x6d, 0xe7, 0xaf, 0xd1, 0xd1, 0x40, 0x82, 0x2d, 0xc3, 0x44, 0x9c, 0x85,
0xa1, 0xfe, 0x72, 0x34, 0xef, 0x1c, 0x12, 0x13, 0x3c, 0xec, 0x13, 0xfb, 0xeb, 0x1e, 0x1e, 0x0c,
0x02, 0xd8, 0x31, 0x38, 0xc0, 0xa3, 0x2e, 0xef, 0xdb, 0xc8, 0xdf, 0xf6, 0x68, 0x20, 0xe8, 0xd5,
0x6c, 0x05, 0xa0, 0xb8, 0x34, 0xaa, 0x9d, 0xc4, 0xfa, 0xa9, 0xbf, 0xef, 0x15, 0x77, 0x50, 0x03,
0x19, 0x08, 0xf2, 0x5b, 0xa7, 0x45, 0x70, 0xa3, 0x2a, 0xc8, 0x2f, 0x9a, 0xc7, 0x61, 0xfc, 0x31,
0x29, 0x62, 0xe5, 0xf9, 0x36, 0xfa, 0x0f, 0xa4, 0x69, 0xbd, 0x2e, 0x58, 0x24, 0x52, 0xae, 0x3c,
0x5f, 0xda, 0xd8, 0x3f, 0x91, 0x2d, 0x01, 0x0d, 0xf7, 0x3c, 0xa9, 0x5c, 0x9e, 0xfb, 0x2f, 0x82,
0x09, 0xd0, 0x9b, 0xd6, 0xaf, 0x1f, 0xe7, 0x3b, 0x36, 0xf6, 0x6f, 0xda, 0x34, 0xae, 0x67, 0x27,
0xa0, 0xa1, 0x5f, 0xe6, 0xf7, 0x6d, 0x1b, 0xfc, 0x0f, 0xc2, 0x03, 0x42, 0x7f, 0xb2, 0x54, 0x7d,
0x15, 0xd8, 0x8b, 0xfd, 0x2f, 0x76, 0x9a, 0xd6, 0xb3, 0x55, 0x98, 0x94, 0xaa, 0xdf, 0xcf, 0x52,
0x2f, 0x1f, 0xfe, 0x16, 0xfc, 0xbf, 0xbd, 0xf2, 0x32, 0x57, 0x32, 0x27, 0x8f, 0xc0, 0x7c, 0x4f,
0x44, 0x75, 0xf0, 0x24, 0xb4, 0x44, 0x4b, 0xb4, 0xf3, 0x63, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0xff,
0xff, 0x3f, 0x9b, 0x2b, 0x54, 0xfc, 0x11, 0x00, 0x00,
// 1201 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xcb, 0x6f, 0x1c, 0x45,
0x13, 0xc0, 0xf5, 0xe9, 0x73, 0x64, 0x6f, 0xf9, 0x85, 0xd7, 0xc6, 0x84, 0x08, 0x44, 0x72, 0xe3,
0xe4, 0x9c, 0x22, 0x94, 0xb6, 0x22, 0xcb, 0xb1, 0x1c, 0x2b, 0x11, 0x06, 0x63, 0xe2, 0x00, 0xe2,
0xb0, 0x9a, 0xdd, 0x6d, 0x4f, 0x06, 0x66, 0xa6, 0x87, 0x99, 0x9e, 0x28, 0xce, 0x0d, 0x85, 0x87,
0x10, 0xe2, 0x8d, 0x04, 0x09, 0x49, 0x80, 0x03, 0xef, 0x67, 0x78, 0x1f, 0xb9, 0xf0, 0xb8, 0xf2,
0x3f, 0x70, 0x01, 0xcc, 0xdb, 0x37, 0x5f, 0x50, 0xcd, 0x56, 0xcd, 0xf6, 0xac, 0x57, 0xea, 0xde,
0xdb, 0xec, 0xba, 0x7f, 0xbf, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x31, 0x80, 0xaf, 0x7c, 0x35, 0x97,
0xa4, 0x4a, 0xab, 0x7a, 0x0d, 0xaf, 0x8b, 0xcb, 0x03, 0x07, 0x7d, 0xa5, 0xfc, 0x50, 0x1e, 0x2e,
0x3e, 0x35, 0xf3, 0xcd, 0xc3, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77,
0xc1, 0x34, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0x37, 0x83, 0xf3, 0xf5, 0x5b, 0xe6,
0x3a, 0xe4, 0x1c, 0x93, 0x73, 0xcb, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0xfe, 0xeb,
0x3f, 0xff, 0xff, 0xe0, 0xff, 0x6e, 0x1f, 0x59, 0x9f, 0x22, 0x14, 0xff, 0xb6, 0x56, 0x80, 0x62,
0x1d, 0x6e, 0xac, 0xf8, 0x32, 0x9d, 0x06, 0xb1, 0x2f, 0x53, 0x8b, 0xf1, 0x3b, 0x32, 0x4e, 0x1b,
0xc6, 0x7b, 0x09, 0x15, 0x4b, 0x30, 0x3e, 0x88, 0xeb, 0x7b, 0x72, 0x8d, 0x49, 0x53, 0xb2, 0x02,
0x93, 0x85, 0xa4, 0x95, 0x67, 0x5a, 0x45, 0xb1, 0x17, 0x49, 0x8b, 0xe6, 0x87, 0x42, 0x53, 0x5b,
0x9f, 0x40, 0x6c, 0xa9, 0xa4, 0x84, 0x80, 0x11, 0xfc, 0xa6, 0x2d, 0x5b, 0xa1, 0xc5, 0xf0, 0x23,
0x05, 0x52, 0xae, 0x17, 0x67, 0x60, 0x06, 0xaf, 0xcf, 0x79, 0x61, 0x2e, 0xcd, 0x48, 0x0e, 0xf5,
0xf5, 0x9c, 0xc1, 0x65, 0x2c, 0xfb, 0xe9, 0xe2, 0x50, 0x11, 0xce, 0x74, 0x29, 0x30, 0x62, 0x32,
0xaa, 0xe8, 0x4b, 0xad, 0x65, 0x9a, 0x35, 0xbc, 0xb0, 0x5f, 0x78, 0x27, 0x82, 0xb0, 0x34, 0x5e,
0xda, 0xae, 0x56, 0x71, 0xa5, 0x43, 0x2e, 0x86, 0xa1, 0xd8, 0x80, 0x9b, 0xfa, 0x3c, 0x15, 0x0e,
0xce, 0xcb, 0xe4, 0x9c, 0xd9, 0xf3, 0x64, 0xa0, 0x76, 0x0d, 0xf8, 0xfb, 0xb2, 0x96, 0x0e, 0xce,
0xd7, 0xc8, 0x59, 0x27, 0x96, 0x4b, 0x8a, 0xc6, 0x53, 0x30, 0x75, 0x4e, 0xa6, 0x4d, 0x95, 0xc9,
0x86, 0x7c, 0x24, 0xf7, 0x42, 0x07, 0xdd, 0x15, 0xd2, 0x4d, 0x12, 0xb8, 0x8c, 0x1c, 0xba, 0x8e,
0xc2, 0xc8, 0xa6, 0xd7, 0x92, 0x0e, 0x8a, 0xab, 0xa4, 0x18, 0xc6, 0xf5, 0x88, 0x2e, 0xc2, 0x98,
0xaf, 0x3a, 0xb7, 0xe4, 0x80, 0x5f, 0x23, 0x7c, 0x94, 0x19, 0x52, 0x24, 0x2a, 0xc9, 0x43, 0x4f,
0xbb, 0x44, 0xf0, 0x3a, 0x2b, 0x98, 0x21, 0xc5, 0x00, 0x69, 0x7d, 0x83, 0x15, 0x99, 0x91, 0xcf,
0x05, 0x18, 0x55, 0x71, 0xb8, 0xa5, 0x62, 0x97, 0x20, 0xde, 0x24, 0x03, 0x10, 0x82, 0x82, 0x79,
0xa8, 0xb9, 0x16, 0xe2, 0xad, 0x6d, 0xde, 0x1e, 0x5c, 0x81, 0x15, 0x98, 0xe4, 0x06, 0x15, 0xa8,
0xd8, 0x41, 0xf1, 0x36, 0x29, 0x26, 0x0c, 0x8c, 0x6e, 0x43, 0xcb, 0x4c, 0xfb, 0xd2, 0x45, 0xf2,
0x0e, 0xdf, 0x06, 0x21, 0x94, 0xca, 0xa6, 0x8c, 0x5b, 0x67, 0xdd, 0x0c, 0xef, 0x72, 0x2a, 0x99,
0x41, 0xc5, 0x12, 0x8c, 0x47, 0x5e, 0x9a, 0x9d, 0xf5, 0x42, 0xa7, 0x72, 0xbc, 0x47, 0x8e, 0xb1,
0x12, 0xa2, 0x8c, 0xe4, 0xf1, 0x20, 0x9a, 0xf7, 0x39, 0x23, 0x06, 0x46, 0x5b, 0x2f, 0xd3, 0x5e,
0x33, 0x94, 0x8d, 0x41, 0x6c, 0x1f, 0xf0, 0xd6, 0xeb, 0xb0, 0xab, 0xa6, 0x71, 0x1e, 0x6a, 0x59,
0x70, 0xc1, 0x49, 0xf3, 0x21, 0x57, 0xba, 0x00, 0x10, 0x7e, 0x00, 0x6e, 0xee, 0x3b, 0x26, 0x1c,
0x64, 0x1f, 0x91, 0x6c, 0xb6, 0xcf, 0xa8, 0xa0, 0x96, 0x30, 0xa8, 0xf2, 0x63, 0x6e, 0x09, 0xb2,
0xc7, 0xb5, 0x06, 0x33, 0x79, 0x9c, 0x79, 0x9b, 0x83, 0x65, 0xed, 0x13, 0xce, 0x5a, 0x87, 0xad,
0x64, 0xed, 0x34, 0xcc, 0x92, 0x71, 0xb0, 0xba, 0x7e, 0xca, 0x8d, 0xb5, 0x43, 0x6f, 0x54, 0xab,
0xfb, 0x20, 0x1c, 0x28, 0xd3, 0x79, 0x5e, 0xcb, 0x38, 0x43, 0xa6, 0x11, 0x79, 0x89, 0x83, 0xf9,
0x3a, 0x99, 0xb9, 0xe3, 0x2f, 0x97, 0x82, 0x55, 0x2f, 0x41, 0xf9, 0xfd, 0xb0, 0x9f, 0xe5, 0x79,
0x9c, 0xca, 0x96, 0xf2, 0xe3, 0xe0, 0x82, 0x6c, 0x3b, 0xa8, 0x3f, 0xeb, 0x29, 0xd5, 0x86, 0x81,
0xa3, 0xf9, 0x24, 0xdc, 0x50, 0x9e, 0x55, 0x1a, 0x41, 0x94, 0xa8, 0x54, 0x5b, 0x8c, 0x9f, 0x73,
0xa5, 0x4a, 0xee, 0x64, 0x81, 0x89, 0x65, 0x98, 0x28, 0x3e, 0xba, 0x3e, 0x92, 0x5f, 0x90, 0x68,
0xbc, 0x4b, 0x51, 0xe3, 0x68, 0xa9, 0x28, 0xf1, 0x52, 0x97, 0xfe, 0xf7, 0x25, 0x37, 0x0e, 0x42,
0xa8, 0x71, 0xe8, 0xad, 0x44, 0xe2, 0xb4, 0x77, 0x30, 0x7c, 0xc5, 0x8d, 0x83, 0x19, 0x52, 0xf0,
0x81, 0xc1, 0x41, 0xf1, 0x35, 0x2b, 0x98, 0x41, 0xc5, 0x3d, 0xdd, 0x41, 0x9b, 0x4a, 0x3f, 0xc8,
0x74, 0xea, 0xe1, 0x6a, 0x8b, 0xea, 0x9b, 0xed, 0xea, 0x21, 0x6c, 0xdd, 0x40, 0xc5, 0x29, 0x98,
0xec, 0x39, 0x62, 0xd4, 0x6f, 0xdb, 0x63, 0x5b, 0x95, 0x59, 0xe6, 0xf9, 0xa5, 0xf0, 0xd1, 0x1d,
0x6a, 0x46, 0xd5, 0x13, 0x86, 0xb8, 0x13, 0xeb, 0x5e, 0x3d, 0x07, 0xd8, 0x65, 0x17, 0x77, 0xca,
0xd2, 0x57, 0x8e, 0x01, 0xe2, 0x04, 0x8c, 0x57, 0xce, 0x00, 0x76, 0xd5, 0x63, 0xa4, 0x1a, 0x33,
0x8f, 0x00, 0xe2, 0x08, 0x0c, 0xe1, 0x3c, 0xb7, 0xe3, 0x8f, 0x13, 0x5e, 0x2c, 0x17, 0xc7, 0x60,
0x84, 0xe7, 0xb8, 0x1d, 0x7d, 0x82, 0xd0, 0x12, 0x41, 0x9c, 0x67, 0xb8, 0x1d, 0x7f, 0x92, 0x71,
0x46, 0x10, 0x77, 0x4f, 0xe1, 0xb7, 0x4f, 0x0f, 0x51, 0x1f, 0xe6, 0xdc, 0xcd, 0xc3, 0x30, 0x0d,
0x6f, 0x3b, 0xfd, 0x14, 0xfd, 0x38, 0x13, 0xe2, 0x0e, 0xd8, 0xe7, 0x98, 0xf0, 0x67, 0x08, 0xed,
0xac, 0x17, 0x4b, 0x30, 0x6a, 0x0c, 0x6c, 0x3b, 0xfe, 0x2c, 0xe1, 0x26, 0x85, 0xa1, 0xd3, 0xc0,
0xb6, 0x0b, 0x9e, 0xe3, 0xd0, 0x89, 0xc0, 0xb4, 0xf1, 0xac, 0xb6, 0xd3, 0xcf, 0x73, 0xd6, 0x19,
0x11, 0x0b, 0x50, 0x2b, 0xfb, 0xaf, 0x9d, 0x7f, 0x81, 0xf8, 0x2e, 0x83, 0x19, 0x30, 0xfa, 0xbf,
0x5d, 0xf1, 0x22, 0x67, 0xc0, 0xa0, 0x70, 0x1b, 0xf5, 0xce, 0x74, 0xbb, 0xe9, 0x25, 0xde, 0x46,
0x3d, 0x23, 0x1d, 0xab, 0x59, 0xb4, 0x41, 0xbb, 0xe2, 0x65, 0xae, 0x66, 0xb1, 0x1e, 0xc3, 0xe8,
0x1d, 0x92, 0x76, 0xc7, 0x2b, 0x1c, 0x46, 0xcf, 0x8c, 0x14, 0x6b, 0x50, 0xdf, 0x3b, 0x20, 0xed,
0xbe, 0x57, 0xc9, 0x37, 0xb5, 0x67, 0x3e, 0x8a, 0xfb, 0x60, 0xb6, 0xff, 0x70, 0xb4, 0x5b, 0x2f,
0xed, 0xf4, 0xbc, 0xce, 0x98, 0xb3, 0x51, 0x9c, 0xee, 0x76, 0x59, 0x73, 0x30, 0xda, 0xb5, 0x97,
0x77, 0xaa, 0x8d, 0xd6, 0x9c, 0x8b, 0x62, 0x11, 0xa0, 0x3b, 0x93, 0xec, 0xae, 0x2b, 0xe4, 0x32,
0x20, 0xdc, 0x1a, 0x34, 0x92, 0xec, 0xfc, 0x55, 0xde, 0x1a, 0x44, 0xe0, 0xd6, 0xe0, 0x69, 0x64,
0xa7, 0xaf, 0xf1, 0xd6, 0x60, 0x44, 0xcc, 0xc3, 0x48, 0x9c, 0x87, 0x21, 0x3e, 0x5b, 0xf5, 0x5b,
0xfb, 0x8c, 0x1b, 0x19, 0xb6, 0x19, 0xfe, 0x65, 0x97, 0x60, 0x06, 0xc4, 0x11, 0xd8, 0x27, 0xa3,
0xa6, 0x6c, 0xdb, 0xc8, 0x5f, 0x77, 0xb9, 0x9f, 0xe0, 0x6a, 0xb1, 0x00, 0xd0, 0x79, 0x99, 0xc6,
0x28, 0x6c, 0xec, 0x6f, 0xbb, 0x9d, 0xf7, 0x7a, 0x03, 0xe9, 0x0a, 0x8a, 0xb7, 0x71, 0x8b, 0x60,
0xbb, 0x2a, 0x28, 0x5e, 0xc0, 0x8f, 0xc2, 0xf0, 0x43, 0x99, 0x8a, 0xb5, 0xe7, 0xdb, 0xe8, 0xdf,
0x89, 0xe6, 0xf5, 0x98, 0xb0, 0x48, 0xa5, 0x52, 0x7b, 0x7e, 0x66, 0x63, 0xff, 0x20, 0xb6, 0x04,
0x10, 0x6e, 0x79, 0x99, 0x76, 0xb9, 0xef, 0x3f, 0x19, 0x66, 0x00, 0x83, 0xc6, 0xeb, 0x87, 0xe5,
0x96, 0x8d, 0xfd, 0x8b, 0x83, 0xa6, 0xf5, 0xe2, 0x18, 0xd4, 0xf0, 0xb2, 0xf8, 0x3f, 0x84, 0x0d,
0xfe, 0x9b, 0xe0, 0x2e, 0x81, 0xbf, 0x9c, 0xe9, 0xb6, 0x0e, 0xec, 0xc9, 0xfe, 0x87, 0x2a, 0xcd,
0xeb, 0xc5, 0x22, 0x8c, 0x66, 0xba, 0xdd, 0xce, 0xe9, 0x44, 0x63, 0xc1, 0xff, 0xdd, 0x2d, 0x5f,
0x72, 0x4b, 0xe6, 0xf8, 0x21, 0x98, 0x6e, 0xa9, 0xa8, 0x17, 0x3c, 0x0e, 0x2b, 0x6a, 0x45, 0xad,
0x15, 0xbb, 0xe8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x9c, 0xec, 0xd8, 0x50, 0x13, 0x00,
0x00,
}

View File

@@ -1,45 +0,0 @@
// Code generated by protoc-gen-go.
// source: gogo.proto
// DO NOT EDIT!
package gogoproto
import proto "github.com/gogo/protobuf/proto"
import json "encoding/json"
import math "math"
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
var _ = proto.Marshal
var _ = &json.SyntaxError{}
var _ = math.Inf
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 51235,
Name: "gogoproto.nullable",
Tag: "varint,51235,opt,name=nullable",
}
var E_Embed = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 51236,
Name: "gogoproto.embed",
Tag: "varint,51236,opt,name=embed",
}
var E_Customtype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 51237,
Name: "gogoproto.customtype",
Tag: "bytes,51237,opt,name=customtype",
}
func init() {
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
}

View File

@@ -1,125 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto2";
package gogoproto;
import "google/protobuf/descriptor.proto";
option java_package = "com.google.protobuf";
option java_outer_classname = "GoGoProtos";
extend google.protobuf.EnumOptions {
optional bool goproto_enum_prefix = 62001;
optional bool goproto_enum_stringer = 62021;
optional bool enum_stringer = 62022;
optional string enum_customname = 62023;
}
extend google.protobuf.EnumValueOptions {
optional string enumvalue_customname = 66001;
}
extend google.protobuf.FileOptions {
optional bool goproto_getters_all = 63001;
optional bool goproto_enum_prefix_all = 63002;
optional bool goproto_stringer_all = 63003;
optional bool verbose_equal_all = 63004;
optional bool face_all = 63005;
optional bool gostring_all = 63006;
optional bool populate_all = 63007;
optional bool stringer_all = 63008;
optional bool onlyone_all = 63009;
optional bool equal_all = 63013;
optional bool description_all = 63014;
optional bool testgen_all = 63015;
optional bool benchgen_all = 63016;
optional bool marshaler_all = 63017;
optional bool unmarshaler_all = 63018;
optional bool stable_marshaler_all = 63019;
optional bool sizer_all = 63020;
optional bool goproto_enum_stringer_all = 63021;
optional bool enum_stringer_all = 63022;
optional bool unsafe_marshaler_all = 63023;
optional bool unsafe_unmarshaler_all = 63024;
optional bool goproto_extensions_map_all = 63025;
optional bool goproto_unrecognized_all = 63026;
optional bool gogoproto_import = 63027;
optional bool protosizer_all = 63028;
optional bool compare_all = 63029;
}
extend google.protobuf.MessageOptions {
optional bool goproto_getters = 64001;
optional bool goproto_stringer = 64003;
optional bool verbose_equal = 64004;
optional bool face = 64005;
optional bool gostring = 64006;
optional bool populate = 64007;
optional bool stringer = 67008;
optional bool onlyone = 64009;
optional bool equal = 64013;
optional bool description = 64014;
optional bool testgen = 64015;
optional bool benchgen = 64016;
optional bool marshaler = 64017;
optional bool unmarshaler = 64018;
optional bool stable_marshaler = 64019;
optional bool sizer = 64020;
optional bool unsafe_marshaler = 64023;
optional bool unsafe_unmarshaler = 64024;
optional bool goproto_extensions_map = 64025;
optional bool goproto_unrecognized = 64026;
optional bool protosizer = 64028;
optional bool compare = 64029;
}
extend google.protobuf.FieldOptions {
optional bool nullable = 65001;
optional bool embed = 65002;
optional string customtype = 65003;
optional string customname = 65004;
optional string jsontag = 65005;
optional string moretags = 65006;
optional string casttype = 65007;
optional string castkey = 65008;
optional string castvalue = 65009;
optional bool stdtime = 65010;
optional bool stdduration = 65011;
}

View File

@@ -90,6 +90,14 @@ func IsCastValue(field *google_protobuf.FieldDescriptorProto) bool {
return false
}
func HasEnumDecl(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_Enumdecl, proto.GetBoolExtension(file.Options, E_EnumdeclAll, true))
}
func HasTypeDecl(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Typedecl, proto.GetBoolExtension(file.Options, E_TypedeclAll, true))
}
func GetCustomType(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
@@ -343,3 +351,7 @@ func ImportsGoGoProto(file *google_protobuf.FileDescriptorProto) bool {
func HasCompare(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Compare, proto.GetBoolExtension(file.Options, E_CompareAll, false))
}
func RegistersGolangProto(file *google_protobuf.FileDescriptorProto) bool {
return proto.GetBoolExtension(file.Options, E_GoprotoRegistration, false)
}

View File

@@ -1,25 +0,0 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
)
func main() {
args := os.Args
if len(args) != 4 {
fmt.Println("gogoreplace wants three arguments")
fmt.Println(" gogoreplace oldsubstring newsubstring filename")
os.Exit(1)
}
data, err := ioutil.ReadFile(args[3])
if err != nil {
panic(err)
}
data = bytes.Replace(data, []byte(args[1]), []byte(args[2]), -1)
if err := ioutil.WriteFile(args[3], data, 0666); err != nil {
panic(err)
}
}

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -ex
die() {
echo "$@" >&2
exit 1
}
case "$PROTOBUF_VERSION" in
2*)
basename=protobuf-$PROTOBUF_VERSION
;;
3*)
basename=protobuf-cpp-$PROTOBUF_VERSION
;;
*)
die "unknown protobuf version: $PROTOBUF_VERSION"
;;
esac
cd /home/travis
wget https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/$basename.tar.gz
tar xzf $basename.tar.gz
cd protobuf-$PROTOBUF_VERSION
./configure --prefix=/home/travis && make -j2 && make install

View File

@@ -1,102 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package io
import (
"github.com/gogo/protobuf/proto"
"io"
)
func NewFullWriter(w io.Writer) WriteCloser {
return &fullWriter{w, nil}
}
type fullWriter struct {
w io.Writer
buffer []byte
}
func (this *fullWriter) WriteMsg(msg proto.Message) (err error) {
var data []byte
if m, ok := msg.(marshaler); ok {
n, ok := getSize(m)
if !ok {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
if n >= len(this.buffer) {
this.buffer = make([]byte, n)
}
_, err = m.MarshalTo(this.buffer)
if err != nil {
return err
}
data = this.buffer[:n]
} else {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
_, err = this.w.Write(data)
return err
}
func (this *fullWriter) Close() error {
if closer, ok := this.w.(io.Closer); ok {
return closer.Close()
}
return nil
}
type fullReader struct {
r io.Reader
buf []byte
}
func NewFullReader(r io.Reader, maxSize int) ReadCloser {
return &fullReader{r, make([]byte, maxSize)}
}
func (this *fullReader) ReadMsg(msg proto.Message) error {
length, err := this.r.Read(this.buf)
if err != nil {
return err
}
return proto.Unmarshal(this.buf[:length], msg)
}
func (this *fullReader) Close() error {
if closer, ok := this.r.(io.Closer); ok {
return closer.Close()
}
return nil
}

View File

@@ -1,70 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package io
import (
"github.com/gogo/protobuf/proto"
"io"
)
type Writer interface {
WriteMsg(proto.Message) error
}
type WriteCloser interface {
Writer
io.Closer
}
type Reader interface {
ReadMsg(msg proto.Message) error
}
type ReadCloser interface {
Reader
io.Closer
}
type marshaler interface {
MarshalTo(data []byte) (n int, err error)
}
func getSize(v interface{}) (int, bool) {
if sz, ok := v.(interface {
Size() (n int)
}); ok {
return sz.Size(), true
} else if sz, ok := v.(interface {
ProtoSize() (n int)
}); ok {
return sz.ProtoSize(), true
} else {
return 0, false
}
}

View File

@@ -1,221 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package io_test
import (
"bytes"
"encoding/binary"
"github.com/gogo/protobuf/io"
"github.com/gogo/protobuf/test"
goio "io"
"math/rand"
"testing"
"time"
)
func iotest(writer io.WriteCloser, reader io.ReadCloser) error {
size := 1000
msgs := make([]*test.NinOptNative, size)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := range msgs {
msgs[i] = test.NewPopulatedNinOptNative(r, true)
//issue 31
if i == 5 {
msgs[i] = &test.NinOptNative{}
}
//issue 31
if i == 999 {
msgs[i] = &test.NinOptNative{}
}
err := writer.WriteMsg(msgs[i])
if err != nil {
return err
}
}
if err := writer.Close(); err != nil {
return err
}
i := 0
for {
msg := &test.NinOptNative{}
if err := reader.ReadMsg(msg); err != nil {
if err == goio.EOF {
break
}
return err
}
if err := msg.VerboseEqual(msgs[i]); err != nil {
return err
}
i++
}
if i != size {
panic("not enough messages read")
}
if err := reader.Close(); err != nil {
return err
}
return nil
}
type buffer struct {
*bytes.Buffer
closed bool
}
func (this *buffer) Close() error {
this.closed = true
return nil
}
func newBuffer() *buffer {
return &buffer{bytes.NewBuffer(nil), false}
}
func TestBigUint32Normal(t *testing.T) {
buf := newBuffer()
writer := io.NewUint32DelimitedWriter(buf, binary.BigEndian)
reader := io.NewUint32DelimitedReader(buf, binary.BigEndian, 1024*1024)
if err := iotest(writer, reader); err != nil {
t.Error(err)
}
if !buf.closed {
t.Fatalf("did not close buffer")
}
}
func TestBigUint32MaxSize(t *testing.T) {
buf := newBuffer()
writer := io.NewUint32DelimitedWriter(buf, binary.BigEndian)
reader := io.NewUint32DelimitedReader(buf, binary.BigEndian, 20)
if err := iotest(writer, reader); err != goio.ErrShortBuffer {
t.Error(err)
} else {
t.Logf("%s", err)
}
}
func TestLittleUint32Normal(t *testing.T) {
buf := newBuffer()
writer := io.NewUint32DelimitedWriter(buf, binary.LittleEndian)
reader := io.NewUint32DelimitedReader(buf, binary.LittleEndian, 1024*1024)
if err := iotest(writer, reader); err != nil {
t.Error(err)
}
if !buf.closed {
t.Fatalf("did not close buffer")
}
}
func TestLittleUint32MaxSize(t *testing.T) {
buf := newBuffer()
writer := io.NewUint32DelimitedWriter(buf, binary.LittleEndian)
reader := io.NewUint32DelimitedReader(buf, binary.LittleEndian, 20)
if err := iotest(writer, reader); err != goio.ErrShortBuffer {
t.Error(err)
} else {
t.Logf("%s", err)
}
}
func TestVarintNormal(t *testing.T) {
buf := newBuffer()
writer := io.NewDelimitedWriter(buf)
reader := io.NewDelimitedReader(buf, 1024*1024)
if err := iotest(writer, reader); err != nil {
t.Error(err)
}
if !buf.closed {
t.Fatalf("did not close buffer")
}
}
func TestVarintNoClose(t *testing.T) {
buf := bytes.NewBuffer(nil)
writer := io.NewDelimitedWriter(buf)
reader := io.NewDelimitedReader(buf, 1024*1024)
if err := iotest(writer, reader); err != nil {
t.Error(err)
}
}
//issue 32
func TestVarintMaxSize(t *testing.T) {
buf := newBuffer()
writer := io.NewDelimitedWriter(buf)
reader := io.NewDelimitedReader(buf, 20)
if err := iotest(writer, reader); err != goio.ErrShortBuffer {
t.Error(err)
} else {
t.Logf("%s", err)
}
}
func TestVarintError(t *testing.T) {
buf := newBuffer()
buf.Write([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f})
reader := io.NewDelimitedReader(buf, 1024*1024)
msg := &test.NinOptNative{}
err := reader.ReadMsg(msg)
if err == nil {
t.Fatalf("Expected error")
}
}
func TestFull(t *testing.T) {
buf := newBuffer()
writer := io.NewFullWriter(buf)
reader := io.NewFullReader(buf, 1024*1024)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
msgIn := test.NewPopulatedNinOptNative(r, true)
if err := writer.WriteMsg(msgIn); err != nil {
panic(err)
}
if err := writer.Close(); err != nil {
panic(err)
}
msgOut := &test.NinOptNative{}
if err := reader.ReadMsg(msgOut); err != nil {
panic(err)
}
if err := msgIn.VerboseEqual(msgOut); err != nil {
panic(err)
}
if err := reader.ReadMsg(msgOut); err != nil {
if err != goio.EOF {
panic(err)
}
}
if err := reader.Close(); err != nil {
panic(err)
}
if !buf.closed {
t.Fatalf("did not close buffer")
}
}

View File

@@ -1,126 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package io
import (
"encoding/binary"
"github.com/gogo/protobuf/proto"
"io"
)
func NewUint32DelimitedWriter(w io.Writer, byteOrder binary.ByteOrder) WriteCloser {
return &uint32Writer{w, byteOrder, nil}
}
func NewSizeUint32DelimitedWriter(w io.Writer, byteOrder binary.ByteOrder, size int) WriteCloser {
return &uint32Writer{w, byteOrder, make([]byte, size)}
}
type uint32Writer struct {
w io.Writer
byteOrder binary.ByteOrder
buffer []byte
}
func (this *uint32Writer) WriteMsg(msg proto.Message) (err error) {
var data []byte
if m, ok := msg.(marshaler); ok {
n, ok := getSize(m)
if !ok {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
if n >= len(this.buffer) {
this.buffer = make([]byte, n)
}
_, err = m.MarshalTo(this.buffer)
if err != nil {
return err
}
data = this.buffer[:n]
} else {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
length := uint32(len(data))
if err = binary.Write(this.w, this.byteOrder, &length); err != nil {
return err
}
_, err = this.w.Write(data)
return err
}
func (this *uint32Writer) Close() error {
if closer, ok := this.w.(io.Closer); ok {
return closer.Close()
}
return nil
}
type uint32Reader struct {
r io.Reader
byteOrder binary.ByteOrder
lenBuf []byte
buf []byte
maxSize int
}
func NewUint32DelimitedReader(r io.Reader, byteOrder binary.ByteOrder, maxSize int) ReadCloser {
return &uint32Reader{r, byteOrder, make([]byte, 4), nil, maxSize}
}
func (this *uint32Reader) ReadMsg(msg proto.Message) error {
if _, err := io.ReadFull(this.r, this.lenBuf); err != nil {
return err
}
length32 := this.byteOrder.Uint32(this.lenBuf)
length := int(length32)
if length < 0 || length > this.maxSize {
return io.ErrShortBuffer
}
if length >= len(this.buf) {
this.buf = make([]byte, length)
}
_, err := io.ReadFull(this.r, this.buf[:length])
if err != nil {
return err
}
return proto.Unmarshal(this.buf[:length], msg)
}
func (this *uint32Reader) Close() error {
if closer, ok := this.r.(io.Closer); ok {
return closer.Close()
}
return nil
}

View File

@@ -1,134 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package io
import (
"bufio"
"encoding/binary"
"errors"
"github.com/gogo/protobuf/proto"
"io"
)
var (
errSmallBuffer = errors.New("Buffer Too Small")
errLargeValue = errors.New("Value is Larger than 64 bits")
)
func NewDelimitedWriter(w io.Writer) WriteCloser {
return &varintWriter{w, make([]byte, 10), nil}
}
type varintWriter struct {
w io.Writer
lenBuf []byte
buffer []byte
}
func (this *varintWriter) WriteMsg(msg proto.Message) (err error) {
var data []byte
if m, ok := msg.(marshaler); ok {
n, ok := getSize(m)
if !ok {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
if n >= len(this.buffer) {
this.buffer = make([]byte, n)
}
_, err = m.MarshalTo(this.buffer)
if err != nil {
return err
}
data = this.buffer[:n]
} else {
data, err = proto.Marshal(msg)
if err != nil {
return err
}
}
length := uint64(len(data))
n := binary.PutUvarint(this.lenBuf, length)
_, err = this.w.Write(this.lenBuf[:n])
if err != nil {
return err
}
_, err = this.w.Write(data)
return err
}
func (this *varintWriter) Close() error {
if closer, ok := this.w.(io.Closer); ok {
return closer.Close()
}
return nil
}
func NewDelimitedReader(r io.Reader, maxSize int) ReadCloser {
var closer io.Closer
if c, ok := r.(io.Closer); ok {
closer = c
}
return &varintReader{bufio.NewReader(r), nil, maxSize, closer}
}
type varintReader struct {
r *bufio.Reader
buf []byte
maxSize int
closer io.Closer
}
func (this *varintReader) ReadMsg(msg proto.Message) error {
length64, err := binary.ReadUvarint(this.r)
if err != nil {
return err
}
length := int(length64)
if length < 0 || length > this.maxSize {
return io.ErrShortBuffer
}
if len(this.buf) < length {
this.buf = make([]byte, length)
}
buf := this.buf[:length]
if _, err := io.ReadFull(this.r, buf); err != nil {
return err
}
return proto.Unmarshal(buf, msg)
}
func (this *varintReader) Close() error {
if this.closer != nil {
return this.closer.Close()
}
return nil
}

View File

@@ -1,959 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON.
It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json.
This package produces a different output than the standard "encoding/json" package,
which does not operate correctly on protocol buffers.
*/
package jsonpb
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/types"
)
// Marshaler is a configurable object for converting between
// protocol buffer objects and a JSON representation for them.
type Marshaler struct {
// Whether to render enum values as integers, as opposed to string values.
EnumsAsInts bool
// Whether to render fields with zero values.
EmitDefaults bool
// A string to indent each level by. The presence of this field will
// also cause a space to appear between the field separator and
// value, and for newlines to be appear between fields and array
// elements.
Indent string
// Whether to use the original (.proto) name for fields.
OrigName bool
}
// Marshal marshals a protocol buffer into JSON.
func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
writer := &errWriter{writer: out}
return m.marshalObject(writer, pb, "", "")
}
// MarshalToString converts a protocol buffer object to JSON string.
func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) {
var buf bytes.Buffer
if err := m.Marshal(&buf, pb); err != nil {
return "", err
}
return buf.String(), nil
}
type int32Slice []int32
// For sorting extensions ids to ensure stable output.
func (s int32Slice) Len() int { return len(s) }
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
type isWkt interface {
XXX_WellKnownType() string
}
// marshalObject writes a struct to the Writer.
func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
s := reflect.ValueOf(v).Elem()
// Handle well-known types.
if wkt, ok := v.(isWkt); ok {
switch wkt.XXX_WellKnownType() {
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
// "Wrappers use the same representation in JSON
// as the wrapped primitive type, ..."
sprop := proto.GetProperties(s.Type())
return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent)
case "Any":
// Any is a bit more involved.
return m.marshalAny(out, v, indent)
case "Duration":
// "Generated output always contains 3, 6, or 9 fractional digits,
// depending on required precision."
s, ns := s.Field(0).Int(), s.Field(1).Int()
d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
x := fmt.Sprintf("%.9f", d.Seconds())
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
out.write(`"`)
out.write(x)
out.write(`s"`)
return out.err
case "Struct":
// Let marshalValue handle the `fields` map.
// TODO: pass the correct Properties if needed.
return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent)
case "Timestamp":
// "RFC 3339, where generated output will always be Z-normalized
// and uses 3, 6 or 9 fractional digits."
s, ns := s.Field(0).Int(), s.Field(1).Int()
t := time.Unix(s, ns).UTC()
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
x := t.Format("2006-01-02T15:04:05.000000000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
out.write(`"`)
out.write(x)
out.write(`Z"`)
return out.err
case "Value":
// Value has a single oneof.
kind := s.Field(0)
if kind.IsNil() {
// "absence of any variant indicates an error"
return errors.New("nil Value")
}
// oneof -> *T -> T -> T.F
x := kind.Elem().Elem().Field(0)
// TODO: pass the correct Properties if needed.
return m.marshalValue(out, &proto.Properties{}, x, indent)
}
}
out.write("{")
if m.Indent != "" {
out.write("\n")
}
firstField := true
if typeURL != "" {
if err := m.marshalTypeURL(out, indent, typeURL); err != nil {
return err
}
firstField = false
}
for i := 0; i < s.NumField(); i++ {
value := s.Field(i)
valueField := s.Type().Field(i)
if strings.HasPrefix(valueField.Name, "XXX_") {
continue
}
// IsNil will panic on most value kinds.
switch value.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
if value.IsNil() {
continue
}
}
if !m.EmitDefaults {
switch value.Kind() {
case reflect.Bool:
if !value.Bool() {
continue
}
case reflect.Int32, reflect.Int64:
if value.Int() == 0 {
continue
}
case reflect.Uint32, reflect.Uint64:
if value.Uint() == 0 {
continue
}
case reflect.Float32, reflect.Float64:
if value.Float() == 0 {
continue
}
case reflect.String:
if value.Len() == 0 {
continue
}
}
}
// Oneof fields need special handling.
if valueField.Tag.Get("protobuf_oneof") != "" {
// value is an interface containing &T{real_value}.
sv := value.Elem().Elem() // interface -> *T -> T
value = sv.Field(0)
valueField = sv.Type().Field(0)
}
prop := jsonProperties(valueField, m.OrigName)
if !firstField {
m.writeSep(out)
}
// If the map value is a cast type, it may not implement proto.Message, therefore
// allow the struct tag to declare the underlying message type. Instead of changing
// the signatures of the child types (and because prop.mvalue is not public), use
// CustomType as a passer.
if value.Kind() == reflect.Map {
if tag := valueField.Tag.Get("protobuf"); tag != "" {
for _, v := range strings.Split(tag, ",") {
if !strings.HasPrefix(v, "castvaluetype=") {
continue
}
v = strings.TrimPrefix(v, "castvaluetype=")
prop.CustomType = v
break
}
}
}
if err := m.marshalField(out, prop, value, indent); err != nil {
return err
}
firstField = false
}
// Handle proto2 extensions.
if ep, ok := v.(proto.Message); ok {
extensions := proto.RegisteredExtensions(v)
// Sort extensions for stable output.
ids := make([]int32, 0, len(extensions))
for id, desc := range extensions {
if !proto.HasExtension(ep, desc) {
continue
}
ids = append(ids, id)
}
sort.Sort(int32Slice(ids))
for _, id := range ids {
desc := extensions[id]
if desc == nil {
// unknown extension
continue
}
ext, extErr := proto.GetExtension(ep, desc)
if extErr != nil {
return extErr
}
value := reflect.ValueOf(ext)
var prop proto.Properties
prop.Parse(desc.Tag)
prop.JSONName = fmt.Sprintf("[%s]", desc.Name)
if !firstField {
m.writeSep(out)
}
if err := m.marshalField(out, &prop, value, indent); err != nil {
return err
}
firstField = false
}
}
if m.Indent != "" {
out.write("\n")
out.write(indent)
}
out.write("}")
return out.err
}
func (m *Marshaler) writeSep(out *errWriter) {
if m.Indent != "" {
out.write(",\n")
} else {
out.write(",")
}
}
func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error {
// "If the Any contains a value that has a special JSON mapping,
// it will be converted as follows: {"@type": xxx, "value": yyy}.
// Otherwise, the value will be converted into a JSON object,
// and the "@type" field will be inserted to indicate the actual data type."
v := reflect.ValueOf(any).Elem()
turl := v.Field(0).String()
val := v.Field(1).Bytes()
// Only the part of type_url after the last slash is relevant.
mname := turl
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
mname = mname[slash+1:]
}
mt := proto.MessageType(mname)
if mt == nil {
return fmt.Errorf("unknown message type %q", mname)
}
msg := reflect.New(mt.Elem()).Interface().(proto.Message)
if err := proto.Unmarshal(val, msg); err != nil {
return err
}
if _, ok := msg.(isWkt); ok {
out.write("{")
if m.Indent != "" {
out.write("\n")
}
if err := m.marshalTypeURL(out, indent, turl); err != nil {
return err
}
m.writeSep(out)
if m.Indent != "" {
out.write(indent)
out.write(m.Indent)
out.write(`"value": `)
} else {
out.write(`"value":`)
}
if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil {
return err
}
if m.Indent != "" {
out.write("\n")
out.write(indent)
}
out.write("}")
return out.err
}
return m.marshalObject(out, msg, indent, turl)
}
func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error {
if m.Indent != "" {
out.write(indent)
out.write(m.Indent)
}
out.write(`"@type":`)
if m.Indent != "" {
out.write(" ")
}
b, err := json.Marshal(typeURL)
if err != nil {
return err
}
out.write(string(b))
return out.err
}
// marshalField writes field description and value to the Writer.
func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
if m.Indent != "" {
out.write(indent)
out.write(m.Indent)
}
out.write(`"`)
out.write(prop.JSONName)
out.write(`":`)
if m.Indent != "" {
out.write(" ")
}
if err := m.marshalValue(out, prop, v, indent); err != nil {
return err
}
return nil
}
// marshalValue writes the value to the Writer.
func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
v = reflect.Indirect(v)
// Handle repeated elements.
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
out.write("[")
comma := ""
for i := 0; i < v.Len(); i++ {
sliceVal := v.Index(i)
out.write(comma)
if m.Indent != "" {
out.write("\n")
out.write(indent)
out.write(m.Indent)
out.write(m.Indent)
}
if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil {
return err
}
comma = ","
}
if m.Indent != "" {
out.write("\n")
out.write(indent)
out.write(m.Indent)
}
out.write("]")
return out.err
}
// Handle well-known types.
// Most are handled up in marshalObject (because 99% are messages).
if wkt, ok := v.Interface().(isWkt); ok {
switch wkt.XXX_WellKnownType() {
case "NullValue":
out.write("null")
return out.err
}
}
if t, ok := v.Interface().(time.Time); ok {
ts, err := types.TimestampProto(t)
if err != nil {
return err
}
return m.marshalValue(out, prop, reflect.ValueOf(ts), indent)
}
if d, ok := v.Interface().(time.Duration); ok {
dur := types.DurationProto(d)
return m.marshalValue(out, prop, reflect.ValueOf(dur), indent)
}
// Handle enumerations.
if !m.EnumsAsInts && prop.Enum != "" {
// Unknown enum values will are stringified by the proto library as their
// value. Such values should _not_ be quoted or they will be interpreted
// as an enum string instead of their value.
enumStr := v.Interface().(fmt.Stringer).String()
var valStr string
if v.Kind() == reflect.Ptr {
valStr = strconv.Itoa(int(v.Elem().Int()))
} else {
valStr = strconv.Itoa(int(v.Int()))
}
if m, ok := v.Interface().(interface {
MarshalJSON() ([]byte, error)
}); ok {
data, err := m.MarshalJSON()
if err != nil {
return err
}
enumStr = string(data)
enumStr, err = strconv.Unquote(enumStr)
if err != nil {
return err
}
}
isKnownEnum := enumStr != valStr
if isKnownEnum {
out.write(`"`)
}
out.write(enumStr)
if isKnownEnum {
out.write(`"`)
}
return out.err
}
// Handle nested messages.
if v.Kind() == reflect.Struct {
i := v
if v.CanAddr() {
i = v.Addr()
} else {
i = reflect.New(v.Type())
i.Elem().Set(v)
}
iface := i.Interface()
if iface == nil {
out.write(`null`)
return out.err
}
pm, ok := iface.(proto.Message)
if !ok {
if prop.CustomType == "" {
return fmt.Errorf("%v does not implement proto.Message", v.Type())
}
t := proto.MessageType(prop.CustomType)
if t == nil || !i.Type().ConvertibleTo(t) {
return fmt.Errorf("%v declared custom type %s but it is not convertible to %v", v.Type(), prop.CustomType, t)
}
pm = i.Convert(t).Interface().(proto.Message)
}
return m.marshalObject(out, pm, indent+m.Indent, "")
}
// Handle maps.
// Since Go randomizes map iteration, we sort keys for stable output.
if v.Kind() == reflect.Map {
out.write(`{`)
keys := v.MapKeys()
sort.Sort(mapKeys(keys))
for i, k := range keys {
if i > 0 {
out.write(`,`)
}
if m.Indent != "" {
out.write("\n")
out.write(indent)
out.write(m.Indent)
out.write(m.Indent)
}
b, err := json.Marshal(k.Interface())
if err != nil {
return err
}
s := string(b)
// If the JSON is not a string value, encode it again to make it one.
if !strings.HasPrefix(s, `"`) {
b, err := json.Marshal(s)
if err != nil {
return err
}
s = string(b)
}
out.write(s)
out.write(`:`)
if m.Indent != "" {
out.write(` `)
}
if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil {
return err
}
}
if m.Indent != "" {
out.write("\n")
out.write(indent)
out.write(m.Indent)
}
out.write(`}`)
return out.err
}
// Default handling defers to the encoding/json library.
b, err := json.Marshal(v.Interface())
if err != nil {
return err
}
needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64)
if needToQuote {
out.write(`"`)
}
out.write(string(b))
if needToQuote {
out.write(`"`)
}
return out.err
}
// Unmarshaler is a configurable object for converting from a JSON
// representation to a protocol buffer object.
type Unmarshaler struct {
// Whether to allow messages to contain unknown fields, as opposed to
// failing to unmarshal.
AllowUnknownFields bool
}
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
// This function is lenient and will decode any options permutations of the
// related Marshaler.
func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
inputValue := json.RawMessage{}
if err := dec.Decode(&inputValue); err != nil {
return err
}
return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
}
// Unmarshal unmarshals a JSON object stream into a protocol
// buffer. This function is lenient and will decode any options
// permutations of the related Marshaler.
func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error {
dec := json.NewDecoder(r)
return u.UnmarshalNext(dec, pb)
}
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
// This function is lenient and will decode any options permutations of the
// related Marshaler.
func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
return new(Unmarshaler).UnmarshalNext(dec, pb)
}
// Unmarshal unmarshals a JSON object stream into a protocol
// buffer. This function is lenient and will decode any options
// permutations of the related Marshaler.
func Unmarshal(r io.Reader, pb proto.Message) error {
return new(Unmarshaler).Unmarshal(r, pb)
}
// UnmarshalString will populate the fields of a protocol buffer based
// on a JSON string. This function is lenient and will decode any options
// permutations of the related Marshaler.
func UnmarshalString(str string, pb proto.Message) error {
return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb)
}
// unmarshalValue converts/copies a value into the target.
// prop may be nil.
func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
targetType := target.Type()
// Allocate memory for pointer fields.
if targetType.Kind() == reflect.Ptr {
target.Set(reflect.New(targetType.Elem()))
return u.unmarshalValue(target.Elem(), inputValue, prop)
}
// Handle well-known types.
if wkt, ok := target.Addr().Interface().(isWkt); ok {
switch wkt.XXX_WellKnownType() {
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
// "Wrappers use the same representation in JSON
// as the wrapped primitive type, except that null is allowed."
// encoding/json will turn JSON `null` into Go `nil`,
// so we don't have to do any extra work.
return u.unmarshalValue(target.Field(0), inputValue, prop)
case "Any":
return fmt.Errorf("unmarshaling Any not supported yet")
case "Duration":
ivStr := string(inputValue)
if ivStr == "null" {
target.Field(0).SetInt(0)
target.Field(1).SetInt(0)
return nil
}
unq, err := strconv.Unquote(ivStr)
if err != nil {
return err
}
d, err := time.ParseDuration(unq)
if err != nil {
return fmt.Errorf("bad Duration: %v", err)
}
ns := d.Nanoseconds()
s := ns / 1e9
ns %= 1e9
target.Field(0).SetInt(s)
target.Field(1).SetInt(ns)
return nil
case "Timestamp":
ivStr := string(inputValue)
if ivStr == "null" {
target.Field(0).SetInt(0)
target.Field(1).SetInt(0)
return nil
}
unq, err := strconv.Unquote(ivStr)
if err != nil {
return err
}
t, err := time.Parse(time.RFC3339Nano, unq)
if err != nil {
return fmt.Errorf("bad Timestamp: %v", err)
}
target.Field(0).SetInt(int64(t.Unix()))
target.Field(1).SetInt(int64(t.Nanosecond()))
return nil
}
}
if t, ok := target.Addr().Interface().(*time.Time); ok {
ts := &types.Timestamp{}
if err := u.unmarshalValue(reflect.ValueOf(ts).Elem(), inputValue, prop); err != nil {
return err
}
tt, err := types.TimestampFromProto(ts)
if err != nil {
return err
}
*t = tt
return nil
}
if d, ok := target.Addr().Interface().(*time.Duration); ok {
dur := &types.Duration{}
if err := u.unmarshalValue(reflect.ValueOf(dur).Elem(), inputValue, prop); err != nil {
return err
}
dd, err := types.DurationFromProto(dur)
if err != nil {
return err
}
*d = dd
return nil
}
// Handle enums, which have an underlying type of int32,
// and may appear as strings.
// The case of an enum appearing as a number is handled
// at the bottom of this function.
if inputValue[0] == '"' && prop != nil && prop.Enum != "" {
vmap := proto.EnumValueMap(prop.Enum)
// Don't need to do unquoting; valid enum names
// are from a limited character set.
s := inputValue[1 : len(inputValue)-1]
n, ok := vmap[string(s)]
if !ok {
return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum)
}
if target.Kind() == reflect.Ptr { // proto2
target.Set(reflect.New(targetType.Elem()))
target = target.Elem()
}
target.SetInt(int64(n))
return nil
}
// Handle nested messages.
if targetType.Kind() == reflect.Struct {
var jsonFields map[string]json.RawMessage
if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
return err
}
consumeField := func(prop *proto.Properties) (json.RawMessage, bool) {
// Be liberal in what names we accept; both orig_name and camelName are okay.
fieldNames := acceptedJSONFieldNames(prop)
vOrig, okOrig := jsonFields[fieldNames.orig]
vCamel, okCamel := jsonFields[fieldNames.camel]
if !okOrig && !okCamel {
return nil, false
}
// If, for some reason, both are present in the data, favour the camelName.
var raw json.RawMessage
if okOrig {
raw = vOrig
delete(jsonFields, fieldNames.orig)
}
if okCamel {
raw = vCamel
delete(jsonFields, fieldNames.camel)
}
return raw, true
}
sprops := proto.GetProperties(targetType)
for i := 0; i < target.NumField(); i++ {
ft := target.Type().Field(i)
if strings.HasPrefix(ft.Name, "XXX_") {
continue
}
valueForField, ok := consumeField(sprops.Prop[i])
if !ok {
continue
}
if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
return err
}
}
// Check for any oneof fields.
if len(jsonFields) > 0 {
for _, oop := range sprops.OneofTypes {
raw, ok := consumeField(oop.Prop)
if !ok {
continue
}
nv := reflect.New(oop.Type.Elem())
target.Field(oop.Field).Set(nv)
if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
return err
}
}
}
if !u.AllowUnknownFields && len(jsonFields) > 0 {
// Pick any field to be the scapegoat.
var f string
for fname := range jsonFields {
f = fname
break
}
return fmt.Errorf("unknown field %q in %v", f, targetType)
}
return nil
}
// Handle arrays
if targetType.Kind() == reflect.Slice {
if targetType.Elem().Kind() == reflect.Uint8 {
outRef := reflect.New(targetType)
outVal := outRef.Interface()
//CustomType with underlying type []byte
if _, ok := outVal.(interface {
UnmarshalJSON([]byte) error
}); ok {
if err := json.Unmarshal(inputValue, outVal); err != nil {
return err
}
target.Set(outRef.Elem())
return nil
}
// Special case for encoded bytes. Pre-go1.5 doesn't support unmarshalling
// strings into aliased []byte types.
// https://github.com/golang/go/commit/4302fd0409da5e4f1d71471a6770dacdc3301197
// https://github.com/golang/go/commit/c60707b14d6be26bf4213114d13070bff00d0b0a
var out []byte
if err := json.Unmarshal(inputValue, &out); err != nil {
return err
}
target.SetBytes(out)
return nil
}
var slc []json.RawMessage
if err := json.Unmarshal(inputValue, &slc); err != nil {
return err
}
len := len(slc)
target.Set(reflect.MakeSlice(targetType, len, len))
for i := 0; i < len; i++ {
if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil {
return err
}
}
return nil
}
// Handle maps (whose keys are always strings)
if targetType.Kind() == reflect.Map {
var mp map[string]json.RawMessage
if err := json.Unmarshal(inputValue, &mp); err != nil {
return err
}
target.Set(reflect.MakeMap(targetType))
var keyprop, valprop *proto.Properties
if prop != nil {
// These could still be nil if the protobuf metadata is broken somehow.
// TODO: This won't work because the fields are unexported.
// We should probably just reparse them.
//keyprop, valprop = prop.mkeyprop, prop.mvalprop
}
for ks, raw := range mp {
// Unmarshal map key. The core json library already decoded the key into a
// string, so we handle that specially. Other types were quoted post-serialization.
var k reflect.Value
if targetType.Key().Kind() == reflect.String {
k = reflect.ValueOf(ks)
} else {
k = reflect.New(targetType.Key()).Elem()
if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
return err
}
}
if !k.Type().AssignableTo(targetType.Key()) {
k = k.Convert(targetType.Key())
}
// Unmarshal map value.
v := reflect.New(targetType.Elem()).Elem()
if err := u.unmarshalValue(v, raw, valprop); err != nil {
return err
}
target.SetMapIndex(k, v)
}
return nil
}
// 64-bit integers can be encoded as strings. In this case we drop
// the quotes and proceed as normal.
isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64
if isNum && strings.HasPrefix(string(inputValue), `"`) {
inputValue = inputValue[1 : len(inputValue)-1]
}
// Use the encoding/json for parsing other value types.
return json.Unmarshal(inputValue, target.Addr().Interface())
}
// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute.
func jsonProperties(f reflect.StructField, origName bool) *proto.Properties {
var prop proto.Properties
prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
if origName || prop.JSONName == "" {
prop.JSONName = prop.OrigName
}
return &prop
}
type fieldNames struct {
orig, camel string
}
func acceptedJSONFieldNames(prop *proto.Properties) fieldNames {
opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName}
if prop.JSONName != "" {
opts.camel = prop.JSONName
}
return opts
}
// Writer wrapper inspired by https://blog.golang.org/errors-are-values
type errWriter struct {
writer io.Writer
err error
}
func (w *errWriter) write(str string) {
if w.err != nil {
return
}
_, w.err = w.writer.Write([]byte(str))
}
// Map fields may have key types of non-float scalars, strings and enums.
// The easiest way to sort them in some deterministic order is to use fmt.
// If this turns out to be inefficient we can always consider other options,
// such as doing a Schwartzian transform.
//
// Numeric keys are sorted in numeric order per
// https://developers.google.com/protocol-buffers/docs/proto#maps.
type mapKeys []reflect.Value
func (s mapKeys) Len() int { return len(s) }
func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s mapKeys) Less(i, j int) bool {
if k := s[i].Kind(); k == s[j].Kind() {
switch k {
case reflect.Int32, reflect.Int64:
return s[i].Int() < s[j].Int()
case reflect.Uint32, reflect.Uint64:
return s[i].Uint() < s[j].Uint()
}
}
return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
}

View File

@@ -1,558 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package jsonpb
import (
"bytes"
"encoding/json"
"io"
"reflect"
"strings"
"testing"
pb "github.com/gogo/protobuf/jsonpb/jsonpb_test_proto"
"github.com/gogo/protobuf/proto"
proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
"github.com/gogo/protobuf/types"
)
var (
marshaler = Marshaler{}
marshalerAllOptions = Marshaler{
Indent: " ",
}
simpleObject = &pb.Simple{
OInt32: proto.Int32(-32),
OInt64: proto.Int64(-6400000000),
OUint32: proto.Uint32(32),
OUint64: proto.Uint64(6400000000),
OSint32: proto.Int32(-13),
OSint64: proto.Int64(-2600000000),
OFloat: proto.Float32(3.14),
ODouble: proto.Float64(6.02214179e23),
OBool: proto.Bool(true),
OString: proto.String("hello \"there\""),
OBytes: []byte("beep boop"),
OCastBytes: pb.Bytes("wow"),
}
simpleObjectJSON = `{` +
`"oBool":true,` +
`"oInt32":-32,` +
`"oInt64":"-6400000000",` +
`"oUint32":32,` +
`"oUint64":"6400000000",` +
`"oSint32":-13,` +
`"oSint64":"-2600000000",` +
`"oFloat":3.14,` +
`"oDouble":6.02214179e+23,` +
`"oString":"hello \"there\"",` +
`"oBytes":"YmVlcCBib29w",` +
`"oCastBytes":"d293"` +
`}`
simpleObjectPrettyJSON = `{
"oBool": true,
"oInt32": -32,
"oInt64": "-6400000000",
"oUint32": 32,
"oUint64": "6400000000",
"oSint32": -13,
"oSint64": "-2600000000",
"oFloat": 3.14,
"oDouble": 6.02214179e+23,
"oString": "hello \"there\"",
"oBytes": "YmVlcCBib29w",
"oCastBytes": "d293"
}`
repeatsObject = &pb.Repeats{
RBool: []bool{true, false, true},
RInt32: []int32{-3, -4, -5},
RInt64: []int64{-123456789, -987654321},
RUint32: []uint32{1, 2, 3},
RUint64: []uint64{6789012345, 3456789012},
RSint32: []int32{-1, -2, -3},
RSint64: []int64{-6789012345, -3456789012},
RFloat: []float32{3.14, 6.28},
RDouble: []float64{299792458 * 1e20, 6.62606957e-34},
RString: []string{"happy", "days"},
RBytes: [][]byte{[]byte("skittles"), []byte("m&m's")},
}
repeatsObjectJSON = `{` +
`"rBool":[true,false,true],` +
`"rInt32":[-3,-4,-5],` +
`"rInt64":["-123456789","-987654321"],` +
`"rUint32":[1,2,3],` +
`"rUint64":["6789012345","3456789012"],` +
`"rSint32":[-1,-2,-3],` +
`"rSint64":["-6789012345","-3456789012"],` +
`"rFloat":[3.14,6.28],` +
`"rDouble":[2.99792458e+28,6.62606957e-34],` +
`"rString":["happy","days"],` +
`"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` +
`}`
repeatsObjectPrettyJSON = `{
"rBool": [
true,
false,
true
],
"rInt32": [
-3,
-4,
-5
],
"rInt64": [
"-123456789",
"-987654321"
],
"rUint32": [
1,
2,
3
],
"rUint64": [
"6789012345",
"3456789012"
],
"rSint32": [
-1,
-2,
-3
],
"rSint64": [
"-6789012345",
"-3456789012"
],
"rFloat": [
3.14,
6.28
],
"rDouble": [
2.99792458e+28,
6.62606957e-34
],
"rString": [
"happy",
"days"
],
"rBytes": [
"c2tpdHRsZXM=",
"bSZtJ3M="
]
}`
innerSimple = &pb.Simple{OInt32: proto.Int32(-32)}
innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)}
innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}}
innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}}
complexObject = &pb.Widget{
Color: pb.Widget_GREEN.Enum(),
RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE},
Simple: innerSimple,
RSimple: []*pb.Simple{innerSimple, innerSimple2},
Repeats: innerRepeats,
RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2},
}
complexObjectJSON = `{"color":"GREEN",` +
`"rColor":["RED","GREEN","BLUE"],` +
`"simple":{"oInt32":-32},` +
`"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` +
`"repeats":{"rString":["roses","red"]},` +
`"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` +
`}`
complexObjectPrettyJSON = `{
"color": "GREEN",
"rColor": [
"RED",
"GREEN",
"BLUE"
],
"simple": {
"oInt32": -32
},
"rSimple": [
{
"oInt32": -32
},
{
"oInt64": "25"
}
],
"repeats": {
"rString": [
"roses",
"red"
]
},
"rRepeats": [
{
"rString": [
"roses",
"red"
]
},
{
"rString": [
"violets",
"blue"
]
}
]
}`
colorPrettyJSON = `{
"color": 2
}`
colorListPrettyJSON = `{
"color": 1000,
"rColor": [
"RED"
]
}`
nummyPrettyJSON = `{
"nummy": {
"1": 2,
"3": 4
}
}`
objjyPrettyJSON = `{
"objjy": {
"1": {
"dub": 1
}
}
}`
realNumber = &pb.Real{Value: proto.Float64(3.14159265359)}
realNumberName = "Pi"
complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)}
realNumberJSON = `{` +
`"value":3.14159265359,` +
`"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` +
`"[jsonpb.name]":"Pi"` +
`}`
anySimple = &pb.KnownTypes{
An: &types.Any{
TypeUrl: "something.example.com/jsonpb.Simple",
Value: []byte{
// &pb.Simple{OBool:true}
1 << 3, 1,
},
},
}
anySimpleJSON = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}`
anySimplePrettyJSON = `{
"an": {
"@type": "something.example.com/jsonpb.Simple",
"oBool": true
}
}`
anyWellKnown = &pb.KnownTypes{
An: &types.Any{
TypeUrl: "type.googleapis.com/google.protobuf.Duration",
Value: []byte{
// &durpb.Duration{Seconds: 1, Nanos: 212000000 }
1 << 3, 1, // seconds
2 << 3, 0x80, 0xba, 0x8b, 0x65, // nanos
},
},
}
anyWellKnownJSON = `{"an":{"@type":"type.googleapis.com/google.protobuf.Duration","value":"1.212s"}}`
anyWellKnownPrettyJSON = `{
"an": {
"@type": "type.googleapis.com/google.protobuf.Duration",
"value": "1.212s"
}
}`
)
func init() {
if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil {
panic(err)
}
if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil {
panic(err)
}
}
var marshalingTests = []struct {
desc string
marshaler Marshaler
pb proto.Message
json string
}{
{"simple flat object", marshaler, simpleObject, simpleObjectJSON},
{"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectPrettyJSON},
{"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON},
{"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON},
{"nested message/enum flat object", marshaler, complexObject, complexObjectJSON},
{"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON},
{"enum-string flat object", Marshaler{},
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
{"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "},
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON},
{"unknown enum value object", marshalerAllOptions,
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON},
{"repeated proto3 enum", Marshaler{},
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}},
`{"rFunny":["PUNS","SLAPSTICK"]}`},
{"repeated proto3 enum as int", Marshaler{EnumsAsInts: true},
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}},
`{"rFunny":[1,2]}`},
{"empty value", marshaler, &pb.Simple3{}, `{}`},
{"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`},
{"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
{"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
{"map<string, string>", marshaler,
&pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
`{"strry":{"\"one\"":"two","three":"four"}}`},
{"map<int32, Object>", marshaler,
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
{"map<int32, Object>", marshalerAllOptions,
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, objjyPrettyJSON},
{"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}},
`{"buggy":{"1234":"yup"}}`},
{"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
// TODO: This is broken.
//{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}`},
{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
{"map<int32, bool>", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<int64, bool>", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint32, bool>", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint64, bool>", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}},
`{"mInt64Str":{"213":"cat"}}`},
{"proto2 map<bool, Object>", marshaler,
&pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: {OInt32: proto.Int32(1)}}},
`{"mBoolSimple":{"true":{"oInt32":1}}}`},
{"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`},
{"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{Title: "Grand Poobah"}}, `{"title":"Grand Poobah"}`},
{"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)},
`{"o_int32":4}`},
{"proto2 extension", marshaler, realNumber, realNumberJSON},
{"Any with message", marshaler, anySimple, anySimpleJSON},
{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}, `{"dur":"3.000s"}`},
{"Struct", marshaler, &pb.KnownTypes{St: &types.Struct{
Fields: map[string]*types.Value{
"one": {Kind: &types.Value_StringValue{StringValue: "loneliest number"}},
"two": {Kind: &types.Value_NullValue{NullValue: types.NULL_VALUE}},
},
}}, `{"st":{"one":"loneliest number","two":null}}`},
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &types.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
{"FloatValue", marshaler, &pb.KnownTypes{Flt: &types.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
{"Int64Value", marshaler, &pb.KnownTypes{I64: &types.Int64Value{Value: -3}}, `{"i64":"-3"}`},
{"UInt64Value", marshaler, &pb.KnownTypes{U64: &types.UInt64Value{Value: 3}}, `{"u64":"3"}`},
{"Int32Value", marshaler, &pb.KnownTypes{I32: &types.Int32Value{Value: -4}}, `{"i32":-4}`},
{"UInt32Value", marshaler, &pb.KnownTypes{U32: &types.UInt32Value{Value: 4}}, `{"u32":4}`},
{"BoolValue", marshaler, &pb.KnownTypes{Bool: &types.BoolValue{Value: true}}, `{"bool":true}`},
{"StringValue", marshaler, &pb.KnownTypes{Str: &types.StringValue{Value: "plush"}}, `{"str":"plush"}`},
{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &types.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
}
func TestMarshaling(t *testing.T) {
for _, tt := range marshalingTests {
json, err := tt.marshaler.MarshalToString(tt.pb)
if err != nil {
t.Errorf("%s: marshaling error: %v", tt.desc, err)
} else if tt.json != json {
t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json)
}
}
}
var unmarshalingTests = []struct {
desc string
unmarshaler Unmarshaler
json string
pb proto.Message
}{
{"simple flat object", Unmarshaler{}, simpleObjectJSON, simpleObject},
{"simple pretty object", Unmarshaler{}, simpleObjectPrettyJSON, simpleObject},
{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"unknown enum value object",
Unmarshaler{},
"{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}",
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}},
// TODO: This is broken.
//{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{Salary: 31000}}},
{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{Country: "Australia"}}},
{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{Country: "Australia"}}},
{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{HomeAddress: "Australia"}}},
{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{HomeAddress: "Australia"}}},
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 3}}},
{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: &types.Duration{Seconds: 0}}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -2, Nanos: 999999995}}},
{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: -62135596800, Nanos: 0}}},
{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: &types.Timestamp{Seconds: 0, Nanos: 0}}},
{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &types.DoubleValue{Value: 1.2}}},
{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &types.FloatValue{Value: 1.2}}},
{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &types.Int64Value{Value: -3}}},
{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &types.UInt64Value{Value: 3}}},
{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &types.Int32Value{Value: -4}}},
{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &types.UInt32Value{Value: 4}}},
{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &types.BoolValue{Value: true}}},
{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &types.StringValue{Value: "plush"}}},
{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &types.BytesValue{Value: []byte("wow")}}},
// `null` is also a permissible value. Let's just test one.
{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: &types.DoubleValue{}}},
}
func TestUnmarshaling(t *testing.T) {
for _, tt := range unmarshalingTests {
// Make a new instance of the type of our expected object.
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
if err != nil {
t.Errorf("%s: %v", tt.desc, err)
continue
}
// For easier diffs, compare text strings of the protos.
exp := proto.MarshalTextString(tt.pb)
act := proto.MarshalTextString(p)
if string(exp) != string(act) {
t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
}
}
}
func TestUnmarshalNext(t *testing.T) {
// We only need to check against a few, not all of them.
tests := unmarshalingTests[:5]
// Create a buffer with many concatenated JSON objects.
var b bytes.Buffer
for _, tt := range tests {
b.WriteString(tt.json)
}
dec := json.NewDecoder(&b)
for _, tt := range tests {
// Make a new instance of the type of our expected object.
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
err := tt.unmarshaler.UnmarshalNext(dec, p)
if err != nil {
t.Errorf("%s: %v", tt.desc, err)
continue
}
// For easier diffs, compare text strings of the protos.
exp := proto.MarshalTextString(tt.pb)
act := proto.MarshalTextString(p)
if string(exp) != string(act) {
t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
}
}
p := &pb.Simple{}
err := new(Unmarshaler).UnmarshalNext(dec, p)
if err != io.EOF {
t.Errorf("eof: got %v, expected io.EOF", err)
}
}
var unmarshalingShouldError = []struct {
desc string
in string
pb proto.Message
}{
{"a value", "666", new(pb.Simple)},
{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
}
func TestUnmarshalingBadInput(t *testing.T) {
for _, tt := range unmarshalingShouldError {
err := UnmarshalString(tt.in, tt.pb)
if err == nil {
t.Errorf("an error was expected when parsing %q instead of an object", tt.desc)
}
}
}

View File

@@ -1,33 +0,0 @@
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2015 The Go Authors. All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
regenerate:
protoc-min-version --version="3.0.0" --gogo_out=Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types:. *.proto -I . -I ../../ -I ../../protobuf/

View File

@@ -1,7 +0,0 @@
package jsonpb
// Byte is used to test that []byte type aliases are serialized to base64.
type Byte byte
// Bytes is used to test that []byte type aliases are serialized to base64.
type Bytes []Byte

Some files were not shown because too many files have changed in this diff Show More