ran go mod vendor on the whole project

This commit is contained in:
Pradyumna Kaushik 2019-10-24 19:55:06 -04:00
parent 26f96f361f
commit 28d10d9d39
346 changed files with 12917 additions and 66931 deletions

View file

@ -1,7 +1,8 @@
Copyright (c) 2013, The GoGo Authors. All rights reserved.
Protocol Buffers for Go with Gadgets
Copyright (c) 2013, The GoGo Authors. All rights reserved.
http://github.com/gogo/protobuf
Go support for Protocol Buffers - Google's data interchange format
Copyright 2010 The Go Authors. All rights reserved.

View file

@ -186,6 +186,7 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
if b&0x80 == 0 {
goto done
}
// x -= 0x80 << 63 // Always zero.
return 0, errOverflow

View file

@ -1,63 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2018 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 proto
import "errors"
// Deprecated: do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
// Deprecated: do not use.
func GetStats() Stats { return Stats{} }
// Deprecated: do not use.
func MarshalMessageSet(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSet([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSetJSON([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func RegisterMessageSetType(Message, int32, string) {}

View file

@ -37,9 +37,27 @@ package proto
import (
"errors"
"fmt"
"reflect"
)
// RequiredNotSetError is the error returned if Marshal is called with
// a protocol buffer struct whose required fields have not
// all been initialized. It is also the error returned if Unmarshal is
// called with an encoded protocol buffer that does not include all the
// required fields.
//
// When printed, RequiredNotSetError reports the first unset required field in a
// message. If the field cannot be precisely determined, it is reported as
// "{Unknown}".
type RequiredNotSetError struct {
field string
}
func (e *RequiredNotSetError) Error() string {
return fmt.Sprintf("proto: required field %q not set", e.field)
}
var (
// errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element.

View file

@ -527,7 +527,6 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
if epb, ok := pb.(extensionsBytes); ok {
ClearExtension(pb, extension)
newb, err := encodeExtension(extension, value)
if err != nil {
return err
@ -545,7 +544,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
}
typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) {
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
return errors.New("proto: bad extension value type")
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension

View file

@ -154,10 +154,6 @@ func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error)
return EncodeExtensionMap(m.extensionsWrite(), data)
}
func EncodeInternalExtensionBackwards(m extendableProto, data []byte) (n int, err error) {
return EncodeExtensionMapBackwards(m.extensionsWrite(), data)
}
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
o := 0
for _, e := range m {
@ -173,23 +169,6 @@ func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
return o, nil
}
func EncodeExtensionMapBackwards(m map[int32]Extension, data []byte) (n int, err error) {
o := 0
end := len(data)
for _, e := range m {
if err := e.Encode(); err != nil {
return 0, err
}
n := copy(data[end-len(e.enc):], e.enc)
if n != len(e.enc) {
return 0, io.ErrShortBuffer
}
end -= n
o += n
}
return o, nil
}
func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
e := m[id]
if err := e.Encode(); err != nil {

View file

@ -265,6 +265,7 @@ package proto
import (
"encoding/json"
"errors"
"fmt"
"log"
"reflect"
@ -273,66 +274,7 @@ import (
"sync"
)
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
// Marshal reports this when a required field is not initialized.
// Unmarshal reports this when a required field is missing from the wire data.
type RequiredNotSetError struct{ field string }
func (e *RequiredNotSetError) Error() string {
if e.field == "" {
return fmt.Sprintf("proto: required field not set")
}
return fmt.Sprintf("proto: required field %q not set", e.field)
}
func (e *RequiredNotSetError) RequiredNotSet() bool {
return true
}
type invalidUTF8Error struct{ field string }
func (e *invalidUTF8Error) Error() string {
if e.field == "" {
return "proto: invalid UTF-8 detected"
}
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
}
func (e *invalidUTF8Error) InvalidUTF8() bool {
return true
}
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
// This error should not be exposed to the external API as such errors should
// be recreated with the field information.
var errInvalidUTF8 = &invalidUTF8Error{}
// isNonFatal reports whether the error is either a RequiredNotSet error
// or a InvalidUTF8 error.
func isNonFatal(err error) bool {
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
return true
}
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
return true
}
return false
}
type nonFatal struct{ E error }
// Merge merges err into nf and reports whether it was successful.
// Otherwise it returns false for any fatal non-nil errors.
func (nf *nonFatal) Merge(err error) (ok bool) {
if err == nil {
return true // not an error
}
if !isNonFatal(err) {
return false // fatal error
}
if nf.E == nil {
nf.E = err // store first instance of non-fatal error
}
return true
}
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
// Message is implemented by generated protocol buffer messages.
type Message interface {
@ -341,6 +283,26 @@ type Message interface {
ProtoMessage()
}
// Stats records allocation details about the protocol buffer encoders
// and decoders. Useful for tuning the library itself.
type Stats struct {
Emalloc uint64 // mallocs in encode
Dmalloc uint64 // mallocs in decode
Encode uint64 // number of encodes
Decode uint64 // number of decodes
Chit uint64 // number of cache hits
Cmiss uint64 // number of cache misses
Size uint64 // number of sizes
}
// Set to true to enable stats collection.
const collectStats = false
var stats Stats
// GetStats returns a copy of the global Stats structure.
func GetStats() Stats { return stats }
// A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to
// reduce memory usage. It is not necessary to use a Buffer;
@ -608,11 +570,9 @@ func SetDefaults(pb Message) {
setDefaults(reflect.ValueOf(pb), true, false)
}
// v is a struct.
// v is a pointer to a struct.
func setDefaults(v reflect.Value, recur, zeros bool) {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
v = v.Elem()
defaultMu.RLock()
dm, ok := defaults[v.Type()]
@ -714,11 +674,8 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
for _, ni := range dm.nested {
f := v.Field(ni)
// f is *T or T or []*T or []T
// f is *T or []*T or map[T]*T
switch f.Kind() {
case reflect.Struct:
setDefaults(f, recur, zeros)
case reflect.Ptr:
if f.IsNil() {
continue
@ -728,7 +685,7 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
case reflect.Slice:
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
if e.Kind() == reflect.Ptr && e.IsNil() {
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
@ -800,9 +757,6 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
var canHaveDefault bool
switch ft.Kind() {
case reflect.Struct:
nestedMessage = true // non-nullable
case reflect.Ptr:
if ft.Elem().Kind() == reflect.Struct {
nestedMessage = true
@ -812,7 +766,7 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
case reflect.Slice:
switch ft.Elem().Kind() {
case reflect.Ptr, reflect.Struct:
case reflect.Ptr:
nestedMessage = true // repeated message
case reflect.Uint8:
canHaveDefault = true // bytes field
@ -948,19 +902,13 @@ func isProto3Zero(v reflect.Value) bool {
return false
}
const (
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
GoGoProtoPackageIsVersion3 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const GoGoProtoPackageIsVersion2 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
GoGoProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
GoGoProtoPackageIsVersion1 = true
)
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const GoGoProtoPackageIsVersion1 = true
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.

View file

@ -36,7 +36,13 @@ package proto
*/
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"sort"
"sync"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@ -139,9 +145,46 @@ func skipVarint(buf []byte) []byte {
return buf[i+1:]
}
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSet(exts interface{}) ([]byte, error) {
return marshalMessageSet(exts, false)
}
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var u marshalInfo
siz := u.sizeMessageSet(exts)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, exts, deterministic)
case map[int32]Extension:
// This is an old-style extension map.
// Wrap it in a new-style XXX_InternalExtensions.
ie := XXX_InternalExtensions{
p: &struct {
mu sync.Mutex
extensionMap map[int32]Extension
}{
extensionMap: exts,
},
}
var u marshalInfo
siz := u.sizeMessageSet(&ie)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, &ie, deterministic)
default:
return nil, errors.New("proto: not an extension map")
}
}
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func unmarshalMessageSet(buf []byte, exts interface{}) error {
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
@ -179,3 +222,93 @@ func unmarshalMessageSet(buf []byte, exts interface{}) error {
}
return nil
}
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var mu sync.Locker
m, mu = exts.extensionsRead()
if m != nil {
// Keep the extensions map locked until we're done marshaling to prevent
// races between marshaling and unmarshaling the lazily-{en,de}coded
// values.
mu.Lock()
defer mu.Unlock()
}
case map[int32]Extension:
m = exts
default:
return nil, errors.New("proto: not an extension map")
}
var b bytes.Buffer
b.WriteByte('{')
// Process the map in key order for deterministic output.
ids := make([]int32, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
for i, id := range ids {
ext := m[id]
msd, ok := messageSetMap[id]
if !ok {
// Unknown type; we can't render it, so skip it.
continue
}
if i > 0 && b.Len() > 1 {
b.WriteByte(',')
}
fmt.Fprintf(&b, `"[%s]":`, msd.name)
x := ext.value
if x == nil {
x = reflect.New(msd.t.Elem()).Interface()
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
return nil, err
}
}
d, err := json.Marshal(x)
if err != nil {
return nil, err
}
b.Write(d)
}
b.WriteByte('}')
return b.Bytes(), nil
}
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
// Common-case fast path.
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
return nil
}
// This is fairly tricky, and it's not clear that it is needed.
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
}
// A global registry of types that can be used in a MessageSet.
var messageSetMap = make(map[int32]messageSetDesc)
type messageSetDesc struct {
t reflect.Type // pointer to struct
name string
}
// RegisterMessageSetType is called from the generated code.
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
messageSetMap[fieldNum] = messageSetDesc{
t: reflect.TypeOf(m),
name: name,
}
}

View file

@ -26,7 +26,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !purego,!appengine,!js
// +build !purego !appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe.

View file

@ -144,7 +144,7 @@ type Properties struct {
Repeated bool
Packed bool // relevant for repeated primitives only
Enum string // set for enum types only
proto3 bool // whether this is known to be a proto3 field
proto3 bool // whether this is known to be a proto3 field; set for []byte only
oneof bool // whether this is a oneof field
Default string // default value
@ -153,15 +153,14 @@ type Properties struct {
CastType string
StdTime bool
StdDuration bool
WktPointer bool
stype reflect.Type // set for struct types only
ctype reflect.Type // set for custom types only
sprop *StructProperties // set for struct types only
mtype reflect.Type // set for map types only
MapKeyProp *Properties // set for map types only
MapValProp *Properties // set for map types only
mtype reflect.Type // set for map types only
mkeyprop *Properties // set for map types only
mvalprop *Properties // set for map types only
}
// String formats the properties in the protobuf struct field tag style.
@ -275,8 +274,6 @@ outer:
p.StdTime = true
case f == "stdduration":
p.StdDuration = true
case f == "wktptr":
p.WktPointer = true
}
}
}
@ -299,10 +296,6 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
p.setTag(lockGetProp)
return
}
if p.WktPointer && !isMap {
p.setTag(lockGetProp)
return
}
switch t1 := typ; t1.Kind() {
case reflect.Struct:
p.stype = typ
@ -324,9 +317,9 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
case reflect.Map:
p.mtype = t1
p.MapKeyProp = &Properties{}
p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
p.MapValProp = &Properties{}
p.mkeyprop = &Properties{}
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
p.mvalprop = &Properties{}
vtype := p.mtype.Elem()
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
// The value type is not a message (*T) or bytes ([]byte),
@ -334,11 +327,10 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
vtype = reflect.PtrTo(vtype)
}
p.MapValProp.CustomType = p.CustomType
p.MapValProp.StdDuration = p.StdDuration
p.MapValProp.StdTime = p.StdTime
p.MapValProp.WktPointer = p.WktPointer
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
p.mvalprop.CustomType = p.CustomType
p.mvalprop.StdDuration = p.StdDuration
p.mvalprop.StdTime = p.StdTime
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
}
p.setTag(lockGetProp)
}
@ -391,6 +383,9 @@ func GetProperties(t reflect.Type) *StructProperties {
sprop, ok := propertiesMap[t]
propertiesMu.RUnlock()
if ok {
if collectStats {
stats.Chit++
}
return sprop
}
@ -400,20 +395,17 @@ func GetProperties(t reflect.Type) *StructProperties {
return sprop
}
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
if collectStats {
stats.Chit++
}
return prop
}
if collectStats {
stats.Cmiss++
}
prop := new(StructProperties)
// in case of recursive protos, fill this in now.
@ -450,40 +442,37 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
// Re-order prop.order.
sort.Sort(prop)
if isOneofMessage {
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok {
var oots []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oots = m.XXX_OneofFuncs()
case oneofWrappersIface:
oots = m.XXX_OneofWrappers()
}
if len(oots) > 0 {
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
oop := &OneofProperties{
Type: reflect.ValueOf(oot).Type(), // *T
Prop: new(Properties),
}
sft := oop.Type.Elem().Field(0)
oop.Prop.Name = sft.Name
oop.Prop.Parse(sft.Tag.Get("protobuf"))
// There will be exactly one interface field that
// this new value is assignable to.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Type.Kind() != reflect.Interface {
continue
}
if !oop.Type.AssignableTo(f.Type) {
continue
}
oop.Field = i
break
}
prop.OneofTypes[oop.Prop.OrigName] = oop
_, _, _, oots = om.XXX_OneofFuncs()
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
oop := &OneofProperties{
Type: reflect.ValueOf(oot).Type(), // *T
Prop: new(Properties),
}
sft := oop.Type.Elem().Field(0)
oop.Prop.Name = sft.Name
oop.Prop.Parse(sft.Tag.Get("protobuf"))
// There will be exactly one interface field that
// this new value is assignable to.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Type.Kind() != reflect.Interface {
continue
}
if !oop.Type.AssignableTo(f.Type) {
continue
}
oop.Field = i
break
}
prop.OneofTypes[oop.Prop.OrigName] = oop
}
}

View file

@ -97,8 +97,6 @@ type marshalElemInfo struct {
var (
marshalInfoMap = map[reflect.Type]*marshalInfo{}
marshalInfoLock sync.Mutex
uint8SliceType = reflect.TypeOf(([]uint8)(nil)).Kind()
)
// getMarshalInfo returns the information to marshal a given type of message.
@ -248,13 +246,16 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
// If the message can marshal itself, let it do it, for compatibility.
// NOTE: This is not efficient.
if u.hasmarshaler {
if deterministic {
return nil, errors.New("proto: deterministic not supported by the Marshal method of " + u.typ.String())
}
m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
b1, err := m.Marshal()
b = append(b, b1...)
return b, err
}
var err, errLater error
var err, errreq error
// The old marshaler encodes extensions at beginning.
if u.extensions.IsValid() {
e := ptr.offset(u.extensions).toExtensions()
@ -279,13 +280,11 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
b = append(b, s...)
}
for _, f := range u.fields {
if f.required {
if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
if f.required && errreq == nil {
if ptr.offset(f.field).getPointer().isNil() {
// Required field is not set.
// We record the error but keep going, to give a complete marshaling.
if errLater == nil {
errLater = &RequiredNotSetError{f.name}
}
errreq = &RequiredNotSetError{f.name}
continue
}
}
@ -298,21 +297,14 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
if err1, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errLater == nil {
errLater = &RequiredNotSetError{f.name + "." + err1.field}
if errreq == nil {
errreq = &RequiredNotSetError{f.name + "." + err1.field}
}
continue
}
if err == errRepeatedHasNil {
err = errors.New("proto: repeated field " + f.name + " has nil element")
}
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return b, err
}
}
@ -320,7 +312,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
s := *ptr.offset(u.unrecognized).toBytes()
b = append(b, s...)
}
return b, errLater
return b, errreq
}
// computeMarshalInfo initializes the marshal info.
@ -389,13 +381,8 @@ func (u *marshalInfo) computeMarshalInfo() {
// get oneof implementers
var oneofImplementers []interface{}
// gogo: isOneofMessage is needed for embedded oneof messages, without a marshaler and unmarshaler
if isOneofMessage {
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok && isOneofMessage {
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
}
// normal fields
@ -496,7 +483,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
fi.field = toField(f)
fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
fi.isPointer = true
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
@ -524,6 +511,10 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
}
}
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
// wiretype returns the wire encoding of the type.
func wiretype(encoding string) uint64 {
switch encoding {
@ -586,8 +577,6 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
ctype := false
isTime := false
isDuration := false
isWktPointer := false
validateUTF8 := true
for i := 2; i < len(tags); i++ {
if tags[i] == "packed" {
packed = true
@ -604,11 +593,7 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
if tags[i] == "stdduration" {
isDuration = true
}
if tags[i] == "wktptr" {
isWktPointer = true
}
}
validateUTF8 = validateUTF8 && proto3
if !proto3 && !pointer && !slice {
nozero = false
}
@ -653,112 +638,6 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
return makeDurationMarshaler(getMarshalInfo(t))
}
if isWktPointer {
switch t.Kind() {
case reflect.Float64:
if pointer {
if slice {
return makeStdDoubleValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdDoubleValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdDoubleValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdDoubleValueMarshaler(getMarshalInfo(t))
case reflect.Float32:
if pointer {
if slice {
return makeStdFloatValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdFloatValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdFloatValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdFloatValueMarshaler(getMarshalInfo(t))
case reflect.Int64:
if pointer {
if slice {
return makeStdInt64ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt64ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdInt64ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt64ValueMarshaler(getMarshalInfo(t))
case reflect.Uint64:
if pointer {
if slice {
return makeStdUInt64ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt64ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdUInt64ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt64ValueMarshaler(getMarshalInfo(t))
case reflect.Int32:
if pointer {
if slice {
return makeStdInt32ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt32ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdInt32ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdInt32ValueMarshaler(getMarshalInfo(t))
case reflect.Uint32:
if pointer {
if slice {
return makeStdUInt32ValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt32ValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdUInt32ValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdUInt32ValueMarshaler(getMarshalInfo(t))
case reflect.Bool:
if pointer {
if slice {
return makeStdBoolValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdBoolValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdBoolValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdBoolValueMarshaler(getMarshalInfo(t))
case reflect.String:
if pointer {
if slice {
return makeStdStringValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdStringValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdStringValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdStringValueMarshaler(getMarshalInfo(t))
case uint8SliceType:
if pointer {
if slice {
return makeStdBytesValuePtrSliceMarshaler(getMarshalInfo(t))
}
return makeStdBytesValuePtrMarshaler(getMarshalInfo(t))
}
if slice {
return makeStdBytesValueSliceMarshaler(getMarshalInfo(t))
}
return makeStdBytesValueMarshaler(getMarshalInfo(t))
default:
panic(fmt.Sprintf("unknown wktpointer type %#v", t))
}
}
switch t.Kind() {
case reflect.Bool:
if pointer {
@ -955,18 +834,6 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
}
return sizeFloat64Value, appendFloat64Value
case reflect.String:
if validateUTF8 {
if pointer {
return sizeStringPtr, appendUTF8StringPtr
}
if slice {
return sizeStringSlice, appendUTF8StringSlice
}
if nozero {
return sizeStringValueNoZero, appendUTF8StringValueNoZero
}
return sizeStringValue, appendUTF8StringValue
}
if pointer {
return sizeStringPtr, appendStringPtr
}
@ -2223,6 +2090,9 @@ func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byt
}
func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
v := *ptr.toString()
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
@ -2233,6 +2103,9 @@ func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]b
if v == "" {
return b, nil
}
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
@ -2244,83 +2117,24 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
return b, nil
}
v := *p
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
return b, nil
}
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
s := *ptr.toStringSlice()
for _, v := range s {
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
}
return b, nil
}
func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if v == "" {
return b, nil
}
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
p := *ptr.toStringPtr()
if p == nil {
return b, nil
}
v := *p
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
s := *ptr.toStringSlice()
for _, v := range s {
if !utf8.ValidString(v) {
invalidUTF8 = true
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
}
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
@ -2399,8 +2213,7 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice()
var err error
var nerr nonFatal
var err, errreq error
for _, v := range s {
if v.isNil() {
return b, errRepeatedHasNil
@ -2408,14 +2221,22 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
b = appendVarint(b, wiretag) // start group
b, err = u.marshal(b, v, deterministic)
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
if !nerr.Merge(err) {
if err != nil {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil {
err = errRepeatedHasNil
}
return b, err
}
}
return b, nerr.E
return b, errreq
}
}
@ -2459,8 +2280,7 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
},
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice()
var err error
var nerr nonFatal
var err, errreq error
for _, v := range s {
if v.isNil() {
return b, errRepeatedHasNil
@ -2469,15 +2289,22 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
siz := u.cachedsize(v)
b = appendVarint(b, uint64(siz))
b, err = u.marshal(b, v, deterministic)
if !nerr.Merge(err) {
if err != nil {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil {
err = errRepeatedHasNil
}
return b, err
}
}
return b, nerr.E
return b, errreq
}
}
@ -2491,21 +2318,15 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
tags := strings.Split(f.Tag.Get("protobuf"), ",")
keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
stdOptions := false
for _, t := range tags {
if strings.HasPrefix(t, "customtype=") {
valTags = append(valTags, t)
}
if t == "stdtime" {
valTags = append(valTags, t)
stdOptions = true
}
if t == "stdduration" {
valTags = append(valTags, t)
stdOptions = true
}
if t == "wktptr" {
valTags = append(valTags, t)
}
}
keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
@ -2519,25 +2340,6 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
// value.
// Key cannot be pointer-typed.
valIsPtr := valType.Kind() == reflect.Ptr
// If value is a message with nested maps, calling
// valSizer in marshal may be quadratic. We should use
// cached version in marshal (but not in size).
// If value is not message type, we don't have size cache,
// but it cannot be nested either. Just use valSizer.
valCachedSizer := valSizer
if valIsPtr && !stdOptions && valType.Elem().Kind() == reflect.Struct {
u := getMarshalInfo(valType.Elem())
valCachedSizer = func(ptr pointer, tagsize int) int {
// Same as message sizer, but use cache.
p := ptr.getPointer()
if p.isNil() {
return 0
}
siz := u.cachedsize(p)
return siz + SizeVarint(uint64(siz)) + tagsize
}
}
return func(ptr pointer, tagsize int) int {
m := ptr.asPointerTo(t).Elem() // the map
n := 0
@ -2558,26 +2360,24 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
if len(keys) > 1 && deterministic {
sort.Sort(mapKeys(keys))
}
var nerr nonFatal
for _, k := range keys {
ki := k.Interface()
vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
b = appendVarint(b, tag)
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
b = appendVarint(b, uint64(siz))
b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
if err != nil && err != ErrNil { // allow nil value in map
return b, err
}
}
return b, nerr.E
return b, nil
}
}
@ -2650,7 +2450,6 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock()
var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys.
@ -2670,11 +2469,11 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
v := e.value
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
}
return b, nerr.E
return b, nil
}
// Sort the keys to provide a deterministic encoding.
@ -2701,11 +2500,11 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
v := e.value
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
}
return b, nerr.E
return b, nil
}
// message set format is:
@ -2762,7 +2561,6 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock()
var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys.
@ -2789,12 +2587,12 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
v := e.value
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
b = append(b, 1<<3|WireEndGroup)
}
return b, nerr.E
return b, nil
}
// Sort the keys to provide a deterministic encoding.
@ -2828,11 +2626,11 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
b = append(b, 1<<3|WireEndGroup)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
}
return b, nerr.E
return b, nil
}
// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
@ -2875,7 +2673,6 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
sort.Ints(keys)
var err error
var nerr nonFatal
for _, k := range keys {
e := m[int32(k)]
if e.value == nil || e.desc == nil {
@ -2892,11 +2689,11 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
v := e.value
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
if err != nil {
return b, err
}
}
return b, nerr.E
return b, nil
}
// newMarshaler is the interface representing objects that can marshal themselves.
@ -2961,11 +2758,6 @@ func Marshal(pb Message) ([]byte, error) {
// a Buffer for most applications.
func (p *Buffer) Marshal(pb Message) error {
var err error
if p.deterministic {
if _, ok := pb.(Marshaler); ok {
return fmt.Errorf("proto: deterministic not supported by the Marshal method of %T", pb)
}
}
if m, ok := pb.(newMarshaler); ok {
siz := m.XXX_Size()
p.grow(siz) // make sure buf has enough capacity

View file

@ -530,25 +530,6 @@ func (mi *mergeInfo) computeMergeInfo() {
}
case reflect.Struct:
switch {
case isSlice && !isPointer: // E.g. []pb.T
mergeInfo := getMergeInfo(tf)
zero := reflect.Zero(tf)
mfi.merge = func(dst, src pointer) {
// TODO: Make this faster?
dstsp := dst.asPointerTo(f.Type)
dsts := dstsp.Elem()
srcs := src.asPointerTo(f.Type).Elem()
for i := 0; i < srcs.Len(); i++ {
dsts = reflect.Append(dsts, zero)
srcElement := srcs.Index(i).Addr()
dstElement := dsts.Index(dsts.Len() - 1).Addr()
mergeInfo.merge(valToPointer(dstElement), valToPointer(srcElement))
}
if dsts.IsNil() {
dsts = reflect.MakeSlice(f.Type, 0, 0)
}
dstsp.Elem().Set(dsts)
}
case !isPointer:
mergeInfo := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {

View file

@ -99,8 +99,6 @@ type unmarshalFieldInfo struct {
// if a required field, contains a single set bit at this field's index in the required field list.
reqMask uint64
name string // name of the field, for error reporting
}
var (
@ -138,10 +136,10 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
u.computeUnmarshalInfo()
}
if u.isMessageSet {
return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
}
var reqMask uint64 // bitmask of required fields we've seen.
var errLater error
var reqMask uint64 // bitmask of required fields we've seen.
var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage.
for len(b) > 0 {
// Read tag and wire type.
// Special case 1 and 2 byte varints.
@ -180,20 +178,11 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
if r, ok := err.(*RequiredNotSetError); ok {
// Remember this error, but keep parsing. We need to produce
// a full parse even if a required field is missing.
if errLater == nil {
errLater = r
}
rnse = r
reqMask |= f.reqMask
continue
}
if err != errInternalBadWireType {
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return err
}
// Fragments with bad wire type are treated as unknown fields.
@ -255,16 +244,20 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
emap[int32(tag)] = e
}
}
if reqMask != u.reqMask && errLater == nil {
if rnse != nil {
// A required field of a submessage/group is missing. Return that error.
return rnse
}
if reqMask != u.reqMask {
// A required field of this message is missing.
for _, n := range u.reqFields {
if reqMask&1 == 0 {
errLater = &RequiredNotSetError{n}
return &RequiredNotSetError{n}
}
reqMask >>= 1
}
}
return errLater
return nil
}
// computeUnmarshalInfo fills in u with information for use
@ -367,36 +360,26 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
}
// Store the info in the correct slot in the message.
u.setTag(tag, toField(&f), unmarshal, reqMask, name)
u.setTag(tag, toField(&f), unmarshal, reqMask)
}
// Find any types associated with oneof fields.
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
// gogo: len(oneofFields) > 0 is needed for embedded oneof messages, without a marshaler and unmarshaler
if len(oneofFields) > 0 {
var oneofImplementers []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
for _, v := range oneofImplementers {
tptr := reflect.TypeOf(v) // *Msg_X
typ := tptr.Elem() // Msg_X
if fn.IsValid() && len(oneofFields) > 0 {
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
for i := res.Len() - 1; i >= 0; i-- {
v := res.Index(i) // interface{}
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
typ := tptr.Elem() // Msg_X
f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f)
tags := strings.Split(f.Tag.Get("protobuf"), ",")
fieldNum, err := strconv.Atoi(tags[1])
tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1]
tag, err := strconv.Atoi(tagstr)
if err != nil {
panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
}
panic("protobuf tag field not an integer: " + tagstr)
}
// Find the oneof field that this struct implements.
@ -407,15 +390,14 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
u.setTag(tag, of.field, unmarshal, 0)
}
}
}
}
// Get extension ranges, if any.
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
if fn.IsValid() {
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() && !u.bytesExtensions.IsValid() {
panic("a message with extensions, but no extensions field in " + t.Name())
@ -429,7 +411,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// [0 0] is [tag=0/wiretype=varint varint-encoded-0].
u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
}, 0, "")
}, 0)
// Set mask for required field check.
u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
@ -441,9 +423,8 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// tag = tag # for field
// field/unmarshal = unmarshal info for that field.
// reqMask = if required, bitmask for field position in required field list. 0 otherwise.
// name = short name of the field.
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64) {
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask}
n := u.typ.NumField()
if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
for len(u.dense) <= tag {
@ -474,16 +455,10 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
ctype := false
isTime := false
isDuration := false
isWktPointer := false
proto3 := false
validateUTF8 := true
for _, tag := range tagArray[3:] {
if strings.HasPrefix(tag, "name=") {
name = tag[5:]
}
if tag == "proto3" {
proto3 = true
}
if strings.HasPrefix(tag, "customtype=") {
ctype = true
}
@ -493,11 +468,7 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
if tag == "stdduration" {
isDuration = true
}
if tag == "wktptr" {
isWktPointer = true
}
}
validateUTF8 = validateUTF8 && proto3
// Figure out packaging (pointer, slice, or both)
slice := false
@ -551,112 +522,6 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
return makeUnmarshalDuration(getUnmarshalInfo(t), name)
}
if isWktPointer {
switch t.Kind() {
case reflect.Float64:
if pointer {
if slice {
return makeStdDoubleValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdDoubleValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdDoubleValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdDoubleValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Float32:
if pointer {
if slice {
return makeStdFloatValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdFloatValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdFloatValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdFloatValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Int64:
if pointer {
if slice {
return makeStdInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt64ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Uint64:
if pointer {
if slice {
return makeStdUInt64ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt64ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdUInt64ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt64ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Int32:
if pointer {
if slice {
return makeStdInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdInt32ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Uint32:
if pointer {
if slice {
return makeStdUInt32ValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt32ValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdUInt32ValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdUInt32ValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.Bool:
if pointer {
if slice {
return makeStdBoolValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBoolValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdBoolValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBoolValueUnmarshaler(getUnmarshalInfo(t), name)
case reflect.String:
if pointer {
if slice {
return makeStdStringValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdStringValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdStringValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdStringValueUnmarshaler(getUnmarshalInfo(t), name)
case uint8SliceType:
if pointer {
if slice {
return makeStdBytesValuePtrSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBytesValuePtrUnmarshaler(getUnmarshalInfo(t), name)
}
if slice {
return makeStdBytesValueSliceUnmarshaler(getUnmarshalInfo(t), name)
}
return makeStdBytesValueUnmarshaler(getUnmarshalInfo(t), name)
default:
panic(fmt.Sprintf("unknown wktpointer type %#v", t))
}
}
// We'll never have both pointer and slice for basic types.
if pointer && slice && t.Kind() != reflect.Struct {
panic("both pointer and slice for basic type in " + t.Name())
@ -791,15 +656,6 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
}
return unmarshalBytesValue
case reflect.String:
if validateUTF8 {
if pointer {
return unmarshalUTF8StringPtr
}
if slice {
return unmarshalUTF8StringSlice
}
return unmarshalUTF8StringValue
}
if pointer {
return unmarshalStringPtr
}
@ -1660,6 +1516,9 @@ func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toString() = v
return b[x:], nil
}
@ -1677,6 +1536,9 @@ func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toStringPtr() = &v
return b[x:], nil
}
@ -1694,72 +1556,14 @@ func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
s := f.toStringSlice()
*s = append(*s, v)
return b[x:], nil
}
func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toString() = v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toStringPtr() = &v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
s := f.toStringSlice()
*s = append(*s, v)
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
var emptyBuf [0]byte
func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
@ -1927,9 +1731,6 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
if t == "stdduration" {
valTags = append(valTags, t)
}
if t == "wktptr" {
valTags = append(valTags, t)
}
}
unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
unmarshalVal := typeUnmarshaler(vt, strings.Join(valTags, ","))
@ -1954,7 +1755,6 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Maps will be somewhat slow. Oh well.
// Read key and value from data.
var nerr nonFatal
k := reflect.New(kt)
v := reflect.New(vt)
for len(b) > 0 {
@ -1975,7 +1775,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
err = errInternalBadWireType // skip unknown tag
}
if nerr.Merge(err) {
if err == nil {
continue
}
if err != errInternalBadWireType {
@ -1998,7 +1798,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Insert into map.
m.SetMapIndex(k.Elem(), v.Elem())
return r, nerr.E
return r, nil
}
}
@ -2024,16 +1824,15 @@ func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshal
// Unmarshal data into holder.
// We unmarshal into the first field of the holder object.
var err error
var nerr nonFatal
b, err = unmarshal(b, valToPointer(v).offset(field0), w)
if !nerr.Merge(err) {
if err != nil {
return nil, err
}
// Write pointer to holder into target field.
f.asPointerTo(ityp).Elem().Set(v)
return b, nerr.E
return b, nil
}
}
@ -2146,7 +1945,7 @@ func encodeVarint(b []byte, x uint64) []byte {
// If there is an error, it returns 0,0.
func decodeVarint(b []byte) (uint64, int) {
var x, y uint64
if len(b) == 0 {
if len(b) <= 0 {
goto bad
}
x = uint64(b[0])

View file

@ -364,7 +364,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err
}
}
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
@ -381,7 +381,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err
}
}
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
if err := tm.writeAny(w, val, props.mvalprop); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {

View file

@ -636,17 +636,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
if err := p.consumeToken(":"); err != nil {
return err
}
if err := p.readAny(key, props.MapKeyProp); err != nil {
if err := p.readAny(key, props.mkeyprop); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
case "value":
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
return err
}
if err := p.readAny(val, props.MapValProp); err != nil {
if err := p.readAny(val, props.mvalprop); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
@ -923,16 +923,6 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
fv.SetFloat(f)
return nil
}
case reflect.Int8:
if x, err := strconv.ParseInt(tok.value, 0, 8); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Int16:
if x, err := strconv.ParseInt(tok.value, 0, 16); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Int32:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
fv.SetInt(x)
@ -980,16 +970,6 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
}
// TODO: Handle nested messages which implement encoding.TextUnmarshaler.
return p.readStruct(fv, terminator)
case reflect.Uint8:
if x, err := strconv.ParseUint(tok.value, 0, 8); err == nil {
fv.SetUint(x)
return nil
}
case reflect.Uint16:
if x, err := strconv.ParseUint(tok.value, 0, 16); err == nil {
fv.SetUint(x)
return nil
}
case reflect.Uint32:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
fv.SetUint(uint64(x))

File diff suppressed because it is too large Load diff

View file

@ -1,113 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2018, 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 proto
type float64Value struct {
Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *float64Value) Reset() { *m = float64Value{} }
func (*float64Value) ProtoMessage() {}
func (*float64Value) String() string { return "float64<string>" }
type float32Value struct {
Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *float32Value) Reset() { *m = float32Value{} }
func (*float32Value) ProtoMessage() {}
func (*float32Value) String() string { return "float32<string>" }
type int64Value struct {
Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *int64Value) Reset() { *m = int64Value{} }
func (*int64Value) ProtoMessage() {}
func (*int64Value) String() string { return "int64<string>" }
type uint64Value struct {
Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *uint64Value) Reset() { *m = uint64Value{} }
func (*uint64Value) ProtoMessage() {}
func (*uint64Value) String() string { return "uint64<string>" }
type int32Value struct {
Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *int32Value) Reset() { *m = int32Value{} }
func (*int32Value) ProtoMessage() {}
func (*int32Value) String() string { return "int32<string>" }
type uint32Value struct {
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *uint32Value) Reset() { *m = uint32Value{} }
func (*uint32Value) ProtoMessage() {}
func (*uint32Value) String() string { return "uint32<string>" }
type boolValue struct {
Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *boolValue) Reset() { *m = boolValue{} }
func (*boolValue) ProtoMessage() {}
func (*boolValue) String() string { return "bool<string>" }
type stringValue struct {
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *stringValue) Reset() { *m = stringValue{} }
func (*stringValue) ProtoMessage() {}
func (*stringValue) String() string { return "string<string>" }
type bytesValue struct {
Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *bytesValue) Reset() { *m = bytesValue{} }
func (*bytesValue) ProtoMessage() {}
func (*bytesValue) String() string { return "[]byte<string>" }
func init() {
RegisterType((*float64Value)(nil), "gogo.protobuf.proto.DoubleValue")
RegisterType((*float32Value)(nil), "gogo.protobuf.proto.FloatValue")
RegisterType((*int64Value)(nil), "gogo.protobuf.proto.Int64Value")
RegisterType((*uint64Value)(nil), "gogo.protobuf.proto.UInt64Value")
RegisterType((*int32Value)(nil), "gogo.protobuf.proto.Int32Value")
RegisterType((*uint32Value)(nil), "gogo.protobuf.proto.UInt32Value")
RegisterType((*boolValue)(nil), "gogo.protobuf.proto.BoolValue")
RegisterType((*stringValue)(nil), "gogo.protobuf.proto.StringValue")
RegisterType((*bytesValue)(nil), "gogo.protobuf.proto.BytesValue")
}

View file

@ -186,6 +186,7 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
if b&0x80 == 0 {
goto done
}
// x -= 0x80 << 63 // Always zero.
return 0, errOverflow

View file

@ -1,63 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2018 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 proto
import "errors"
// Deprecated: do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
// Deprecated: do not use.
func GetStats() Stats { return Stats{} }
// Deprecated: do not use.
func MarshalMessageSet(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSet([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSetJSON([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func RegisterMessageSetType(Message, int32, string) {}

View file

@ -246,8 +246,7 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
return false
}
m1 := extensionAsLegacyType(e1.value)
m2 := extensionAsLegacyType(e2.value)
m1, m2 := e1.value, e2.value
if m1 == nil && m2 == nil {
// Both have only encoded form.

View file

@ -185,25 +185,9 @@ type Extension struct {
// extension will have only enc set. When such an extension is
// accessed using GetExtension (or GetExtensions) desc and value
// will be set.
desc *ExtensionDesc
// value is a concrete value for the extension field. Let the type of
// desc.ExtensionType be the "API type" and the type of Extension.value
// be the "storage type". The API type and storage type are the same except:
// * For scalars (except []byte), the API type uses *T,
// while the storage type uses T.
// * For repeated fields, the API type uses []T, while the storage type
// uses *[]T.
//
// The reason for the divergence is so that the storage type more naturally
// matches what is expected of when retrieving the values through the
// protobuf reflection APIs.
//
// The value may only be populated if desc is also populated.
desc *ExtensionDesc
value interface{}
// enc is the raw bytes for the extension field.
enc []byte
enc []byte
}
// SetRawExtension is for testing only.
@ -350,7 +334,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict")
}
return extensionAsLegacyType(e.value), nil
return e.value, nil
}
if extension.ExtensionType == nil {
@ -365,11 +349,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return.
e.value = extensionAsStorageType(v)
e.value = v
e.desc = extension
e.enc = nil
emap[extension.Field] = e
return extensionAsLegacyType(e.value), nil
return e.value, nil
}
// defaultExtensionValue returns the default value for extension.
@ -504,7 +488,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
}
typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) {
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
return errors.New("proto: bad extension value type")
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension
@ -516,7 +500,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
}
extmap := epb.extensionsWrite()
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
extmap[extension.Field] = Extension{desc: extension, value: value}
return nil
}
@ -557,51 +541,3 @@ func RegisterExtension(desc *ExtensionDesc) {
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
return extensionMaps[reflect.TypeOf(pb).Elem()]
}
// extensionAsLegacyType converts an value in the storage type as the API type.
// See Extension.value.
func extensionAsLegacyType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
// Represent primitive types as a pointer to the value.
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Slice:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
}
return v
}
// extensionAsStorageType converts an value in the API type as the storage type.
// See Extension.value.
func extensionAsStorageType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
case reflect.Slice:
// Represent slice types as a pointer to the value.
if rv.Type().Elem().Kind() != reflect.Uint8 {
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
}
}
return v
}

View file

@ -341,6 +341,26 @@ type Message interface {
ProtoMessage()
}
// Stats records allocation details about the protocol buffer encoders
// and decoders. Useful for tuning the library itself.
type Stats struct {
Emalloc uint64 // mallocs in encode
Dmalloc uint64 // mallocs in decode
Encode uint64 // number of encodes
Decode uint64 // number of decodes
Chit uint64 // number of cache hits
Cmiss uint64 // number of cache misses
Size uint64 // number of sizes
}
// Set to true to enable stats collection.
const collectStats = false
var stats Stats
// GetStats returns a copy of the global Stats structure.
func GetStats() Stats { return stats }
// A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to
// reduce memory usage. It is not necessary to use a Buffer;
@ -940,19 +960,13 @@ func isProto3Zero(v reflect.Value) bool {
return false
}
const (
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion3 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion1 = true
)
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion1 = true
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.

View file

@ -36,7 +36,13 @@ package proto
*/
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"sort"
"sync"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@ -139,9 +145,46 @@ func skipVarint(buf []byte) []byte {
return buf[i+1:]
}
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSet(exts interface{}) ([]byte, error) {
return marshalMessageSet(exts, false)
}
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var u marshalInfo
siz := u.sizeMessageSet(exts)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, exts, deterministic)
case map[int32]Extension:
// This is an old-style extension map.
// Wrap it in a new-style XXX_InternalExtensions.
ie := XXX_InternalExtensions{
p: &struct {
mu sync.Mutex
extensionMap map[int32]Extension
}{
extensionMap: exts,
},
}
var u marshalInfo
siz := u.sizeMessageSet(&ie)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, &ie, deterministic)
default:
return nil, errors.New("proto: not an extension map")
}
}
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func unmarshalMessageSet(buf []byte, exts interface{}) error {
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
@ -179,3 +222,93 @@ func unmarshalMessageSet(buf []byte, exts interface{}) error {
}
return nil
}
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var mu sync.Locker
m, mu = exts.extensionsRead()
if m != nil {
// Keep the extensions map locked until we're done marshaling to prevent
// races between marshaling and unmarshaling the lazily-{en,de}coded
// values.
mu.Lock()
defer mu.Unlock()
}
case map[int32]Extension:
m = exts
default:
return nil, errors.New("proto: not an extension map")
}
var b bytes.Buffer
b.WriteByte('{')
// Process the map in key order for deterministic output.
ids := make([]int32, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
for i, id := range ids {
ext := m[id]
msd, ok := messageSetMap[id]
if !ok {
// Unknown type; we can't render it, so skip it.
continue
}
if i > 0 && b.Len() > 1 {
b.WriteByte(',')
}
fmt.Fprintf(&b, `"[%s]":`, msd.name)
x := ext.value
if x == nil {
x = reflect.New(msd.t.Elem()).Interface()
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
return nil, err
}
}
d, err := json.Marshal(x)
if err != nil {
return nil, err
}
b.Write(d)
}
b.WriteByte('}')
return b.Bytes(), nil
}
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
// Common-case fast path.
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
return nil
}
// This is fairly tricky, and it's not clear that it is needed.
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
}
// A global registry of types that can be used in a MessageSet.
var messageSetMap = make(map[int32]messageSetDesc)
type messageSetDesc struct {
t reflect.Type // pointer to struct
name string
}
// RegisterMessageSetType is called from the generated code.
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
messageSetMap[fieldNum] = messageSetDesc{
t: reflect.TypeOf(m),
name: name,
}
}

View file

@ -79,13 +79,10 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
func toAddrPointer(i *interface{}, isptr bool) pointer {
v := reflect.ValueOf(*i)
u := reflect.New(v.Type())
u.Elem().Set(v)
if deref {
u = u.Elem()
}
return pointer{v: u}
}

View file

@ -85,21 +85,16 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
func toAddrPointer(i *interface{}, isptr bool) pointer {
// Super-tricky - read or get the address of data word of interface value.
if isptr {
// The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address.
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
} else {
// The interface is not of pointer type. The data word is the pointer
// to the data.
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
}
if deref {
p.p = *(*unsafe.Pointer)(p.p)
}
return p
// The interface is not of pointer type. The data word is the pointer
// to the data.
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// valToPointer converts v to a pointer. v must be of pointer type.

View file

@ -38,6 +38,7 @@ package proto
import (
"fmt"
"log"
"os"
"reflect"
"sort"
"strconv"
@ -193,7 +194,7 @@ func (p *Properties) Parse(s string) {
// "bytes,49,opt,name=foo,def=hello!"
fields := strings.Split(s, ",") // breaks def=, but handled below.
if len(fields) < 2 {
log.Printf("proto: tag has too few fields: %q", s)
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
return
}
@ -213,7 +214,7 @@ func (p *Properties) Parse(s string) {
p.WireType = WireBytes
// no numeric converter for non-numeric types
default:
log.Printf("proto: tag has unknown wire type: %q", s)
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
return
}
@ -333,6 +334,9 @@ func GetProperties(t reflect.Type) *StructProperties {
sprop, ok := propertiesMap[t]
propertiesMu.RUnlock()
if ok {
if collectStats {
stats.Chit++
}
return sprop
}
@ -342,20 +346,17 @@ func GetProperties(t reflect.Type) *StructProperties {
return sprop
}
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
if collectStats {
stats.Chit++
}
return prop
}
if collectStats {
stats.Cmiss++
}
prop := new(StructProperties)
// in case of recursive protos, fill this in now.
@ -390,14 +391,13 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
// Re-order prop.order.
sort.Sort(prop)
var oots []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oots = m.XXX_OneofFuncs()
case oneofWrappersIface:
oots = m.XXX_OneofWrappers()
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
if len(oots) > 0 {
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
var oots []interface{}
_, _, _, oots = om.XXX_OneofFuncs()
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {

View file

@ -87,7 +87,6 @@ type marshalElemInfo struct {
sizer sizer
marshaler marshaler
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
deref bool // dereference the pointer before operating on it; implies isptr
}
var (
@ -321,11 +320,8 @@ func (u *marshalInfo) computeMarshalInfo() {
// get oneof implementers
var oneofImplementers []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
n := t.NumField()
@ -411,22 +407,13 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
panic("tag is not an integer")
}
wt := wiretype(tags[0])
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
t = t.Elem()
}
sizer, marshaler := typeMarshaler(t, tags, false, false)
var deref bool
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
t = reflect.PtrTo(t)
deref = true
}
e = &marshalElemInfo{
wiretag: uint64(tag)<<3 | wt,
tagsize: SizeVarint(uint64(tag) << 3),
sizer: sizer,
marshaler: marshaler,
isptr: t.Kind() == reflect.Ptr,
deref: deref,
}
// update cache
@ -461,7 +448,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
fi.field = toField(f)
fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
fi.isPointer = true
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
@ -489,6 +476,10 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
}
}
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
// wiretype returns the wire encoding of the type.
func wiretype(encoding string) uint64 {
switch encoding {
@ -2319,8 +2310,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
for _, k := range m.MapKeys() {
ki := k.Interface()
vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
n += siz + SizeVarint(uint64(siz)) + tagsize
}
@ -2338,8 +2329,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
for _, k := range keys {
ki := k.Interface()
vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
kaddr := toAddrPointer(&ki, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
b = appendVarint(b, tag)
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
b = appendVarint(b, uint64(siz))
@ -2408,7 +2399,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
// the last time this function was called.
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
n += ei.sizer(p, ei.tagsize)
}
mu.Unlock()
@ -2443,7 +2434,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err
@ -2474,7 +2465,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err
@ -2519,7 +2510,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
n += ei.sizer(p, 1) // message, tag = 3 (size=1)
}
mu.Unlock()
@ -2562,7 +2553,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
if !nerr.Merge(err) {
return b, err
@ -2600,7 +2591,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
b = append(b, 1<<3|WireEndGroup)
if !nerr.Merge(err) {
@ -2630,7 +2621,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
n += ei.sizer(p, ei.tagsize)
}
return n
@ -2665,7 +2656,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
ei := u.getExtElemInfo(e.desc)
v := e.value
p := toAddrPointer(&v, ei.isptr, ei.deref)
p := toAddrPointer(&v, ei.isptr)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if !nerr.Merge(err) {
return b, err

View file

@ -136,7 +136,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
u.computeUnmarshalInfo()
}
if u.isMessageSet {
return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
}
var reqMask uint64 // bitmask of required fields we've seen.
var errLater error
@ -362,48 +362,46 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
}
// Find any types associated with oneof fields.
var oneofImplementers []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
}
for _, v := range oneofImplementers {
tptr := reflect.TypeOf(v) // *Msg_X
typ := tptr.Elem() // Msg_X
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
if fn.IsValid() {
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
for i := res.Len() - 1; i >= 0; i-- {
v := res.Index(i) // interface{}
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
typ := tptr.Elem() // Msg_X
f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f)
tags := strings.Split(f.Tag.Get("protobuf"), ",")
fieldNum, err := strconv.Atoi(tags[1])
if err != nil {
panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f)
tags := strings.Split(f.Tag.Get("protobuf"), ",")
fieldNum, err := strconv.Atoi(tags[1])
if err != nil {
panic("protobuf tag field not an integer: " + tags[1])
}
var name string
for _, tag := range tags {
if strings.HasPrefix(tag, "name=") {
name = strings.TrimPrefix(tag, "name=")
break
}
}
// Find the oneof field that this struct implements.
// Might take O(n^2) to process all of the oneofs, but who cares.
for _, of := range oneofFields {
if tptr.Implements(of.ityp) {
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
}
}
}
// Find the oneof field that this struct implements.
// Might take O(n^2) to process all of the oneofs, but who cares.
for _, of := range oneofFields {
if tptr.Implements(of.ityp) {
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
}
}
}
// Get extension ranges, if any.
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
if fn.IsValid() {
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
panic("a message with extensions, but no extensions field in " + t.Name())
@ -1950,7 +1948,7 @@ func encodeVarint(b []byte, x uint64) []byte {
// If there is an error, it returns 0,0.
func decodeVarint(b []byte) (uint64, int) {
var x, y uint64
if len(b) == 0 {
if len(b) <= 0 {
goto bad
}
x = uint64(b[0])

View file

@ -1,41 +1,3 @@
/*
Gokmeans is a simple k-means clusterer that determines centroids with the Train function,
and then classifies additional observations with the Nearest function.
package main
import (
"fmt"
"github.com/mdesenfants/gokmeans"
)
var observations []gokmeans.Node = []gokmeans.Node {
gokmeans.Node{20.0, 20.0, 20.0, 20.0},
gokmeans.Node{21.0, 21.0, 21.0, 21.0},
gokmeans.Node{100.5, 100.5, 100.5, 100.5},
gokmeans.Node{50.1, 50.1, 50.1, 50.1},
gokmeans.Node{64.2, 64.2, 64.2, 64.2},
}
func main() {
// Get a list of centroids and output the values
if success, centroids := gokmeans.Train(observations, 2, 50); success {
// Show the centroids
fmt.Println("The centroids are")
for _, centroid := range centroids {
fmt.Println(centroid)
}
// Output the clusters
fmt.Println("...")
for _, observation := range observations {
index := gokmeans.Nearest(observation, centroids)
fmt.Println(observation, "belongs in cluster", index+1, ".")
}
}
}
*/
package gokmeans
import (
@ -43,12 +5,8 @@ import (
"time"
)
// Node represents an observation of floating point values
type Node []float64
// Train takes an array of Nodes (observations), and produces as many centroids as specified by
// clusterCount. It will stop adjusting centroids after maxRounds is reached. If there are less
// observations than the number of centroids requested, then Train will return (false, nil).
func Train(Nodes []Node, clusterCount int, maxRounds int) (bool, []Node) {
if int(len(Nodes)) < clusterCount {
return false, nil
@ -78,11 +36,6 @@ func Train(Nodes []Node, clusterCount int, maxRounds int) (bool, []Node) {
copy(centroids[i], Nodes[r.Intn(len(Nodes))])
}
return Train2(Nodes, clusterCount, maxRounds, centroids)
}
// Provide initial centroids
func Train2(Nodes []Node, clusterCount int, maxRounds int, centroids []Node) (bool, []Node) {
// Train centroids
movement := true
for i := 0; i < maxRounds && movement; i++ {
@ -108,7 +61,6 @@ func Train2(Nodes []Node, clusterCount int, maxRounds int, centroids []Node) (bo
return true, centroids
}
// equal determines if two nodes have the same values.
func equal(node1, node2 Node) bool {
if len(node1) != len(node2) {
return false
@ -123,7 +75,6 @@ func equal(node1, node2 Node) bool {
return true
}
// Nearest return the index of the closest centroid from nodes
func Nearest(in Node, nodes []Node) int {
count := len(nodes)
@ -151,7 +102,6 @@ func Nearest(in Node, nodes []Node) int {
return mindex
}
// Distance determines the square Euclidean distance between two nodes
func distance(node1 Node, node2 Node) float64 {
length := len(node1)
squares := make(Node, length, length)
@ -176,8 +126,6 @@ func distance(node1 Node, node2 Node) float64 {
return sum
}
// meanNode takes an array of Nodes and returns a node which represents the average
// value for the provided nodes. This is used to center the centroids within their cluster.
func meanNode(values []Node) Node {
newNode := make(Node, len(values[0]))
@ -194,8 +142,6 @@ func meanNode(values []Node) Node {
return newNode
}
// wait stops a function from continuing until the provided channel has processed as
// many items as there are dimensions in the provided Node.
func wait(c chan int, values Node) {
count := len(values)

View file

@ -29,15 +29,6 @@ const (
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
)
const (
genericRead = 0x80000000
genericWrite = 0x40000000
)
const (
consoleTextmodeBuffer = 0x1
)
type wchar uint16
type short int16
type dword uint32
@ -78,17 +69,14 @@ var (
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
)
// Writer provide colorable Writer to the console
type Writer struct {
out io.Writer
handle syscall.Handle
althandle syscall.Handle
oldattr word
oldpos coord
rest bytes.Buffer
out io.Writer
handle syscall.Handle
oldattr word
oldpos coord
}
// NewColorable return new instance of Writer which handle escape sequence from File.
@ -419,18 +407,7 @@ func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
handle := w.handle
var er *bytes.Reader
if w.rest.Len() > 0 {
var rest bytes.Buffer
w.rest.WriteTo(&rest)
w.rest.Reset()
rest.Write(data)
er = bytes.NewReader(rest.Bytes())
} else {
er = bytes.NewReader(data)
}
er := bytes.NewReader(data)
var bw [1]byte
loop:
for {
@ -448,55 +425,29 @@ loop:
break loop
}
switch c2 {
case '>':
continue
case ']':
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
if c2 == ']' {
if err := doTitleSequence(er); err != nil {
break loop
}
er = bytes.NewReader(w.rest.Bytes()[2:])
err := doTitleSequence(er)
if err != nil {
break loop
}
w.rest.Reset()
continue
// https://github.com/mattn/go-colorable/issues/27
case '7':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition
continue
case '8':
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
continue
case 0x5b:
// execute part after switch
default:
continue
}
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
if c2 != 0x5b {
continue
}
var buf bytes.Buffer
var m byte
for i, c := range w.rest.Bytes()[2:] {
for {
c, err := er.ReadByte()
if err != nil {
break loop
}
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
m = c
er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
w.rest.Reset()
break
}
buf.Write([]byte(string(c)))
}
if m == 0 {
break loop
}
switch m {
case 'A':
@ -504,64 +455,61 @@ loop:
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'B':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'C':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x += short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'D':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x -= short(n)
if csbi.cursorPosition.x < 0 {
csbi.cursorPosition.x = 0
}
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'E':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0
csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'F':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0
csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'G':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = short(n - 1)
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'H', 'f':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
if buf.Len() > 0 {
token := strings.Split(buf.String(), ";")
switch len(token) {
@ -586,7 +534,7 @@ loop:
} else {
csbi.cursorPosition.y = 0
}
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'J':
n := 0
if buf.Len() > 0 {
@ -597,20 +545,20 @@ loop:
}
var count, written dword
var cursor coord
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
switch n {
case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x)
case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
}
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'K':
n := 0
if buf.Len() > 0 {
@ -619,28 +567,28 @@ loop:
continue
}
}
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
var cursor coord
var count, written dword
switch n {
case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x)
cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x - 1)
case 1:
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x)
case 2:
cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
count = dword(csbi.size.x)
}
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
attr := csbi.attributes
cs := buf.String()
if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
continue
}
token := strings.Split(cs, ";")
@ -679,21 +627,6 @@ loop:
attr |= n256foreAttr[n256]
i += 2
}
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= foregroundRed
}
if g > 127 {
attr |= foregroundGreen
}
if b > 127 {
attr |= foregroundBlue
}
} else {
attr = attr & (w.oldattr & backgroundMask)
}
@ -721,21 +654,6 @@ loop:
attr |= n256backAttr[n256]
i += 2
}
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= backgroundRed
}
if g > 127 {
attr |= backgroundGreen
}
if b > 127 {
attr |= backgroundBlue
}
} else {
attr = attr & (w.oldattr & foregroundMask)
}
@ -767,52 +685,38 @@ loop:
attr |= backgroundBlue
}
}
procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
}
}
case 'h':
var ci consoleCursorInfo
cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle == 0 {
h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
w.althandle = syscall.Handle(h)
if w.althandle != 0 {
handle = w.althandle
}
}
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
}
case 'l':
var ci consoleCursorInfo
cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle != 0 {
syscall.CloseHandle(w.althandle)
w.althandle = 0
handle = w.handle
}
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
}
case 's':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition
case 'u':
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
}
}

View file

@ -1,3 +0,0 @@
module github.com/mattn/go-colorable
require github.com/mattn/go-isatty v0.0.8

View file

@ -1,4 +0,0 @@
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View file

@ -1,3 +0,0 @@
module github.com/mattn/go-isatty
require golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a

View file

@ -1,2 +0,0 @@
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

15
vendor/github.com/mattn/go-isatty/isatty_appengine.go generated vendored Normal file
View file

@ -0,0 +1,15 @@
// +build appengine
package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on on appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -16,9 +16,3 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -1,4 +1,5 @@
// +build android
// +build linux
// +build !appengine,!ppc64,!ppc64le
package isatty
@ -15,9 +16,3 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -0,0 +1,19 @@
// +build linux
// +build ppc64 ppc64le
package isatty
import (
"unsafe"
syscall "golang.org/x/sys/unix"
)
const ioctlReadTermios = syscall.TCGETS
// IsTerminal return true if the file descriptor is terminal.
func IsTerminal(fd uintptr) bool {
var termios syscall.Termios
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0
}

View file

@ -1,14 +1,9 @@
// +build appengine js nacl
// +build !windows
// +build !appengine
package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on js and appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false

View file

@ -14,9 +14,3 @@ func IsTerminal(fd uintptr) bool {
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
return err == nil
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -1,19 +0,0 @@
// +build linux aix
// +build !appengine
// +build !android
package isatty
import "golang.org/x/sys/unix"
// IsTerminal return true if the file descriptor is terminal.
func IsTerminal(fd uintptr) bool {
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
return err == nil
}
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View file

@ -760,7 +760,7 @@ func (driver *MesosSchedulerDriver) exitedExecutor(_ context.Context, from *upid
return
}
status := msg.GetStatus()
log.V(2).Infof("Lost executor %q from slave %q for framework %q with status %d",
log.V(2).Infoln("Lost executor %q from slave %q for framework %q with status %d",
msg.GetExecutorId().GetValue(),
msg.GetSlaveId().GetValue(),
msg.GetFrameworkId().GetValue(),

View file

@ -1,13 +1,17 @@
language: go
go:
- stable
- master
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
- tip
before_install:
- go get github.com/mattn/goveralls
- sudo pip install codecov
script:
- go test -v -covermode=count -coverprofile=coverage.out
- go test
after_success:
- $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis-ci
- codecov
notifications:
email:
recipients:

View file

@ -1,9 +1,8 @@
# Stats [![][travis-svg]][travis-url] [![][coveralls-svg]][coveralls-url] [![][goreport-svg]][goreport-url] [![][godoc-svg]][godoc-url] [![][license-svg]][license-url]
# Stats [![][travis-svg]][travis-url] [![][coveralls-svg]][coveralls-url] [![][godoc-svg]][godoc-url] [![][license-svg]][license-url]
A well tested and comprehensive Golang statistics library package with no dependencies.
If you have any suggestions, problems or bug reports please [create an issue](https://github.com/montanaflynn/stats/issues) and I'll do my best to accommodate you. In addition simply starring the repo would show your support for the project and be very much appreciated!
A statistics package with many functions missing from the Golang standard library. See the [CHANGELOG.md](https://github.com/montanaflynn/stats/blob/master/CHANGELOG.md) for API changes and tagged releases you can vendor into your projects.
> Statistics are used much like a drunk uses a lamppost: for support, not illumination. **- Vin Scully**
## Installation
@ -11,130 +10,55 @@ If you have any suggestions, problems or bug reports please [create an issue](ht
go get github.com/montanaflynn/stats
```
## Example Usage
**Protip:** `go get -u github.com/montanaflynn/stats` updates stats to the latest version.
All the functions can be seen in [examples/main.go](https://github.com/montanaflynn/stats/blob/master/examples/main.go) but here's a little taste:
```go
// start with some source data to use
data := []float64{1.0, 2.1, 3.2, 4.823, 4.1, 5.8}
// you could also use different types like this
// data := stats.LoadRawData([]int{1, 2, 3, 4, 5})
// data := stats.LoadRawData([]interface{}{1.1, "2", 3})
// etc...
median, _ := stats.Median(data)
fmt.Println(median) // 3.65
roundedMedian, _ := stats.Round(median, 0)
fmt.Println(roundedMedian) // 4
```
## Documentation
## Usage
The [entire API documentation](http://godoc.org/github.com/montanaflynn/stats) is available on GoDoc.org
You can view docs offline with the following commands:
```
# Command line
godoc ./
godoc ./ Median
godoc ./ Float64Data
# Local website
godoc -http=:4444
open http://localhost:4444/pkg/github.com/montanaflynn/stats/
```
The exported API is as follows:
**Protip:** Generate HTML docs with `godoc -http=:4444`
## Example
All the functions can be seen in [examples/main.go](https://github.com/montanaflynn/stats/blob/master/examples/main.go) but here's a little taste:
```go
var (
EmptyInputErr = statsErr{"Input must not be empty."}
NaNErr = statsErr{"Not a number."}
NegativeErr = statsErr{"Must not contain negative values."}
ZeroErr = statsErr{"Must not contain zero values."}
BoundsErr = statsErr{"Input is outside of range."}
SizeErr = statsErr{"Must be the same length."}
InfValue = statsErr{"Value is infinite."}
YCoordErr = statsErr{"Y Value must be greater than zero."}
)
// start with the some source data to use
var data = []float64{1, 2, 3, 4, 4, 5}
type Float64Data []float64
median, _ := stats.Median(data)
fmt.Println(median) // 3.5
func LoadRawData(raw interface{}) (f Float64Data) {}
func AutoCorrelation(data Float64Data, lags int) (float64, error) {}
func ChebyshevDistance(dataPointX, dataPointY []float64) (distance float64, err error) {}
func Correlation(data1, data2 Float64Data) (float64, error) {}
func Covariance(data1, data2 Float64Data) (float64, error) {}
func CovariancePopulation(data1, data2 Float64Data) (float64, error) {}
func CumulativeSum(input Float64Data) ([]float64, error) {}
func EuclideanDistance(dataPointX, dataPointY []float64) (distance float64, err error) {}
func GeometricMean(input Float64Data) (float64, error) {}
func HarmonicMean(input Float64Data) (float64, error) {}
func InterQuartileRange(input Float64Data) (float64, error) {}
func ManhattanDistance(dataPointX, dataPointY []float64) (distance float64, err error) {}
func Max(input Float64Data) (max float64, err error) {}
func Mean(input Float64Data) (float64, error) {}
func Median(input Float64Data) (median float64, err error) {}
func MedianAbsoluteDeviation(input Float64Data) (mad float64, err error) {}
func MedianAbsoluteDeviationPopulation(input Float64Data) (mad float64, err error) {}
func Midhinge(input Float64Data) (float64, error) {}
func Min(input Float64Data) (min float64, err error) {}
func MinkowskiDistance(dataPointX, dataPointY []float64, lambda float64) (distance float64, err error) {}
func Mode(input Float64Data) (mode []float64, err error) {}
func Pearson(data1, data2 Float64Data) (float64, error) {}
func Percentile(input Float64Data, percent float64) (percentile float64, err error) {}
func PercentileNearestRank(input Float64Data, percent float64) (percentile float64, err error) {}
func PopulationVariance(input Float64Data) (pvar float64, err error) {}
func Round(input float64, places int) (rounded float64, err error) {}
func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) {}
func SampleVariance(input Float64Data) (svar float64, err error) {}
func Sigmoid(input Float64Data) ([]float64, error) {}
func SoftMax(input Float64Data) ([]float64, error) {}
func StandardDeviation(input Float64Data) (sdev float64, err error) {}
func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) {}
func StandardDeviationSample(input Float64Data) (sdev float64, err error) {}
func StdDevP(input Float64Data) (sdev float64, err error) {}
func StdDevS(input Float64Data) (sdev float64, err error) {}
func Sum(input Float64Data) (sum float64, err error) {}
func Trimean(input Float64Data) (float64, error) {}
func VarP(input Float64Data) (sdev float64, err error) {}
func VarS(input Float64Data) (sdev float64, err error) {}
func Variance(input Float64Data) (sdev float64, err error) {}
roundedMedian, _ := stats.Round(median, 0)
fmt.Println(roundedMedian) // 4
```
type Coordinate struct {
X, Y float64
}
**Protip:** You can [call methods](https://github.com/montanaflynn/stats/blob/master/examples/methods.go) on the data if using the Float64Data type:
type Series []Coordinate
```
var d stats.Float64Data = data
func ExponentialRegression(s Series) (regressions Series, err error) {}
func LinearRegression(s Series) (regressions Series, err error) {}
func LogarithmicRegression(s Series) (regressions Series, err error) {}
type Outliers struct {
Mild Float64Data
Extreme Float64Data
}
type Quartiles struct {
Q1 float64
Q2 float64
Q3 float64
}
func Quartile(input Float64Data) (Quartiles, error) {}
func QuartileOutliers(input Float64Data) (Outliers, error) {}
max, _ := d.Max()
fmt.Println(max) // 5
```
## Contributing
Pull request are always welcome no matter how big or small. I've included a [Makefile](https://github.com/montanaflynn/stats/blob/master/Makefile) that has a lot of helper targets for common actions such as linting, testing, code coverage reporting and more.
If you have any suggestions, criticism or bug reports please [create an issue](https://github.com/montanaflynn/stats/issues) and I'll do my best to accommodate you. In addition simply starring the repo would show your support for the project and be very much appreciated!
1. Fork the repo and clone your fork
### Pull Requests
Pull request are always welcome no matter how big or small. Here's an easy way to do it:
1. Fork it and clone your fork
2. Create new branch (`git checkout -b some-thing`)
3. Make the desired changes
4. Ensure tests pass (`go test -cover` or `make test`)
@ -144,14 +68,21 @@ Pull request are always welcome no matter how big or small. I've included a [Mak
To make things as seamless as possible please also consider the following steps:
- Update `examples/main.go` with a simple example of the new feature
- Update `README.md` documentation section with any new exported API
- Keep 100% code coverage (you can check with `make coverage`)
- Squash commits into single units of work with `git rebase -i new-feature`
- Update `README.md` to include new public types or functions in the documentation section.
- Update `examples/main.go` with a simple example of the new feature.
- Keep 100% code coverage (you can check with `make coverage`).
- Run [`gometalinter`](https://github.com/alecthomas/gometalinter) and make your code pass.
- Squash needless commits into single units of work with `git rebase -i new-feature`.
#### Makefile
I've included a [Makefile](https://github.com/montanaflynn/stats/blob/master/Makefile) that has a lot of helper targets for common actions such as linting, testing, code coverage reporting and more.
**Protip:** `watch -n 1 make check` will continuously format and test your code.
## MIT License
Copyright (c) 2014-2019 Montana Flynn <http://anonfunction.com>
Copyright (c) 2014-2015 Montana Flynn <http://anonfunction.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@ -165,9 +96,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
[coveralls-url]: https://coveralls.io/r/montanaflynn/stats?branch=master
[coveralls-svg]: https://img.shields.io/coveralls/montanaflynn/stats.svg
[goreport-url]: https://goreportcard.com/report/github.com/montanaflynn/stats
[goreport-svg]: https://goreportcard.com/badge/github.com/montanaflynn/stats
[godoc-url]: https://godoc.org/github.com/montanaflynn/stats
[godoc-svg]: https://godoc.org/github.com/montanaflynn/stats?status.svg

View file

@ -1,8 +1,6 @@
package stats
import (
"math"
)
import "math"
// Correlation describes the degree of relationship between two sets of data
func Correlation(data1, data2 Float64Data) (float64, error) {
@ -11,7 +9,7 @@ func Correlation(data1, data2 Float64Data) (float64, error) {
l2 := data2.Len()
if l1 == 0 || l2 == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
if l1 != l2 {
@ -29,32 +27,7 @@ func Correlation(data1, data2 Float64Data) (float64, error) {
return covp / (sdev1 * sdev2), nil
}
// Pearson calculates the Pearson product-moment correlation coefficient between two variables
// Pearson calculates the Pearson product-moment correlation coefficient between two variables.
func Pearson(data1, data2 Float64Data) (float64, error) {
return Correlation(data1, data2)
}
// Autocorrelation is the correlation of a signal with a delayed copy of itself as a function of delay
func AutoCorrelation(data Float64Data, lags int) (float64, error) {
if len(data) < 1 {
return 0, EmptyInputErr
}
mean, _ := Mean(data)
var result, q float64
for i := 0; i < lags; i++ {
v := (data[0] - mean) * (data[0] - mean)
for i := 1; i < len(data); i++ {
delta0 := data[i-1] - mean
delta1 := data[i] - mean
q += (delta0*delta1 - q) / float64(i+1)
v += (delta1*delta1 - v) / float64(i+1)
}
result = q / v
}
return result, nil
}

View file

@ -1,21 +0,0 @@
package stats
// CumulativeSum calculates the cumulative sum of the input slice
func CumulativeSum(input Float64Data) ([]float64, error) {
if input.Len() == 0 {
return Float64Data{}, EmptyInput
}
cumSum := make([]float64, input.Len())
for i, val := range input {
if i == 0 {
cumSum[i] = val
} else {
cumSum[i] = cumSum[i-1] + val
}
}
return cumSum, nil
}

View file

@ -24,9 +24,6 @@ func (f Float64Data) Max() (float64, error) { return Max(f) }
// Sum returns the total of all the numbers in the data
func (f Float64Data) Sum() (float64, error) { return Sum(f) }
// CumulativeSum returns the cumulative sum of the data
func (f Float64Data) CumulativeSum() ([]float64, error) { return CumulativeSum(f) }
// Mean returns the mean of the data
func (f Float64Data) Mean() (float64, error) { return Mean(f) }
@ -87,11 +84,6 @@ func (f Float64Data) Correlation(d Float64Data) (float64, error) {
return Correlation(f, d)
}
// Autocorrelation is the correlation of a signal with a delayed copy of itself as a function of delay
func (f Float64Data) AutoCorrelation(lags int) (float64, error) {
return AutoCorrelation(f, lags)
}
// Pearson calculates the Pearson product-moment correlation coefficient between two variables.
func (f Float64Data) Pearson(d Float64Data) (float64, error) {
return Pearson(f, d)

View file

@ -7,7 +7,7 @@ import (
// Validate data for distance calculation
func validateData(dataPointX, dataPointY []float64) error {
if len(dataPointX) == 0 || len(dataPointY) == 0 {
return EmptyInputErr
return EmptyInput
}
if len(dataPointX) != len(dataPointY) {
@ -16,7 +16,7 @@ func validateData(dataPointX, dataPointY []float64) error {
return nil
}
// ChebyshevDistance computes the Chebyshev distance between two data sets
// Computes Chebyshev distance between two data sets
func ChebyshevDistance(dataPointX, dataPointY []float64) (distance float64, err error) {
err = validateData(dataPointX, dataPointY)
if err != nil {
@ -32,7 +32,9 @@ func ChebyshevDistance(dataPointX, dataPointY []float64) (distance float64, err
return distance, nil
}
// EuclideanDistance computes the Euclidean distance between two data sets
//
// Computes Euclidean distance between two data sets
//
func EuclideanDistance(dataPointX, dataPointY []float64) (distance float64, err error) {
err = validateData(dataPointX, dataPointY)
@ -46,7 +48,9 @@ func EuclideanDistance(dataPointX, dataPointY []float64) (distance float64, err
return math.Sqrt(distance), nil
}
// ManhattanDistance computes the Manhattan distance between two data sets
//
// Computes Manhattan distance between two data sets
//
func ManhattanDistance(dataPointX, dataPointY []float64) (distance float64, err error) {
err = validateData(dataPointX, dataPointY)
if err != nil {
@ -59,9 +63,10 @@ func ManhattanDistance(dataPointX, dataPointY []float64) (distance float64, err
return distance, nil
}
// MinkowskiDistance computes the Minkowski distance between two data sets
//
// Arguments:
// Computes minkowski distance between two data sets.
//
// Input:
// dataPointX: First set of data points
// dataPointY: Second set of data points. Length of both data
// sets must be equal.
@ -70,8 +75,9 @@ func ManhattanDistance(dataPointX, dataPointY []float64) (distance float64, err
// lambda = 2; it is euclidean distance. Lambda
// reaching to infinite - distance would be chebysev
// distance.
// Return:
// Output:
// Distance or error
//
func MinkowskiDistance(dataPointX, dataPointY []float64, lambda float64) (distance float64, err error) {
err = validateData(dataPointX, dataPointY)
if err != nil {
@ -80,8 +86,8 @@ func MinkowskiDistance(dataPointX, dataPointY []float64, lambda float64) (distan
for i := 0; i < len(dataPointY); i++ {
distance = distance + math.Pow(math.Abs(dataPointX[i]-dataPointY[i]), lambda)
}
distance = math.Pow(distance, 1/lambda)
if math.IsInf(distance, 1) {
distance = math.Pow(distance, float64(1/lambda))
if math.IsInf(distance, 1) == true {
return math.NaN(), InfValue
}
return distance, nil

View file

@ -10,7 +10,7 @@ func MedianAbsoluteDeviation(input Float64Data) (mad float64, err error) {
// MedianAbsoluteDeviationPopulation finds the median of the absolute deviations from the population median
func MedianAbsoluteDeviationPopulation(input Float64Data) (mad float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
i := copyslice(input)
@ -32,7 +32,7 @@ func StandardDeviation(input Float64Data) (sdev float64, err error) {
func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the population variance
@ -46,7 +46,7 @@ func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) {
func StandardDeviationSample(input Float64Data) (sdev float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the sample variance

View file

@ -8,19 +8,15 @@ func (s statsErr) Error() string {
return s.err
}
func (s statsErr) String() string {
return s.err
}
// These are the package-wide error values.
// All error identification should use these values.
var (
EmptyInputErr = statsErr{"Input must not be empty."}
NaNErr = statsErr{"Not a number."}
NegativeErr = statsErr{"Must not contain negative values."}
ZeroErr = statsErr{"Must not contain zero values."}
BoundsErr = statsErr{"Input is outside of range."}
SizeErr = statsErr{"Must be the same length."}
InfValue = statsErr{"Value is infinite."}
YCoordErr = statsErr{"Y Value must be greater than zero."}
EmptyInput = statsErr{"Input must not be empty."}
SampleSize = statsErr{"Samples number must be less than input length."}
NaNErr = statsErr{"Not a number"}
NegativeErr = statsErr{"Slice must not contain negative values."}
ZeroErr = statsErr{"Slice must not contain zero values."}
BoundsErr = statsErr{"Input is outside of range."}
SizeErr = statsErr{"Slices must be the same length."}
InfValue = statsErr{"Value is infinite."}
)

View file

@ -34,6 +34,3 @@ func ExpReg(s []Coordinate) (regressions []Coordinate, err error) {
func LogReg(s []Coordinate) (regressions []Coordinate, err error) {
return LogarithmicRegression(s)
}
// EmptyInput legacy error name didn't end with Err
var EmptyInput = EmptyInputErr

View file

@ -40,7 +40,7 @@ func LoadRawData(raw interface{}) (f Float64Data) {
return s
case []bool:
for _, v := range t {
if v {
if v == true {
s = append(s, 1.0)
} else {
s = append(s, 0.0)
@ -138,7 +138,7 @@ func LoadRawData(raw interface{}) (f Float64Data) {
return s
case map[int]bool:
for i := 0; i < len(t); i++ {
if t[i] {
if t[i] == true {
s = append(s, 1.0)
} else {
s = append(s, 0.0)
@ -171,7 +171,7 @@ func LoadRawData(raw interface{}) (f Float64Data) {
f = append(f, fl)
}
case bool:
if t {
if t == true {
f = append(f, 1.0)
} else {
f = append(f, 0.0)

View file

@ -1,15 +1,13 @@
package stats
import (
"math"
)
import "math"
// Max finds the highest number in a slice
func Max(input Float64Data) (max float64, err error) {
// Return an error if there are no numbers
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the first value as the starting point

View file

@ -6,7 +6,7 @@ import "math"
func Mean(input Float64Data) (float64, error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
sum, _ := input.Sum()
@ -19,7 +19,7 @@ func GeometricMean(input Float64Data) (float64, error) {
l := input.Len()
if l == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the product of all the numbers
@ -41,7 +41,7 @@ func HarmonicMean(input Float64Data) (float64, error) {
l := input.Len()
if l == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the sum of all the numbers reciprocals and return an

View file

@ -14,11 +14,11 @@ func Median(input Float64Data) (median float64, err error) {
// For odd numbers we just use the middle number
l := len(c)
if l == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
} else if l%2 == 0 {
median, _ = Mean(c[l/2-1 : l/2+1])
} else {
median = c[l/2]
median = float64(c[l/2])
}
return median, nil

View file

@ -10,7 +10,7 @@ func Min(input Float64Data) (min float64, err error) {
// Return an error if there are no numbers
if l == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Get the first value as the starting point

View file

@ -7,7 +7,7 @@ func Mode(input Float64Data) (mode []float64, err error) {
if l == 1 {
return input, nil
} else if l == 0 {
return nil, EmptyInputErr
return nil, EmptyInput
}
c := sortedCopyDif(input)

View file

@ -9,7 +9,7 @@ type Outliers struct {
// QuartileOutliers finds the mild and extreme outliers
func QuartileOutliers(input Float64Data) (Outliers, error) {
if input.Len() == 0 {
return Outliers{}, EmptyInputErr
return Outliers{}, EmptyInput
}
// Start by sorting a copy of the slice

View file

@ -1,14 +1,12 @@
package stats
import (
"math"
)
import "math"
// Percentile finds the relative standing in a slice of floats
func Percentile(input Float64Data, percent float64) (percentile float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
if percent <= 0 || percent > 100 {
@ -54,7 +52,7 @@ func PercentileNearestRank(input Float64Data, percent float64) (percentile float
// Return an error for empty slices
if il == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Return error for less than 0 or greater than 100 percentages

View file

@ -14,7 +14,7 @@ func Quartile(input Float64Data) (Quartiles, error) {
il := input.Len()
if il == 0 {
return Quartiles{}, EmptyInputErr
return Quartiles{}, EmptyInput
}
// Start by sorting a copy of the slice
@ -44,7 +44,7 @@ func Quartile(input Float64Data) (Quartiles, error) {
// InterQuartileRange finds the range between Q1 and Q3
func InterQuartileRange(input Float64Data) (float64, error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
qs, _ := Quartile(input)
iqr := qs.Q3 - qs.Q1
@ -54,7 +54,7 @@ func InterQuartileRange(input Float64Data) (float64, error) {
// Midhinge finds the average of the first and third quartiles
func Midhinge(input Float64Data) (float64, error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
qs, _ := Quartile(input)
mh := (qs.Q1 + qs.Q3) / 2
@ -64,7 +64,7 @@ func Midhinge(input Float64Data) (float64, error) {
// Trimean finds the average of the median and the midhinge
func Trimean(input Float64Data) (float64, error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
c := sortedCopy(input)

View file

@ -14,7 +14,7 @@ type Coordinate struct {
func LinearRegression(s Series) (regressions Series, err error) {
if len(s) == 0 {
return nil, EmptyInputErr
return nil, EmptyInput
}
// Placeholder for the math to be done
@ -44,21 +44,19 @@ func LinearRegression(s Series) (regressions Series, err error) {
}
return regressions, nil
}
// ExponentialRegression returns an exponential regression on data series
func ExponentialRegression(s Series) (regressions Series, err error) {
if len(s) == 0 {
return nil, EmptyInputErr
return nil, EmptyInput
}
var sum [6]float64
for i := 0; i < len(s); i++ {
if s[i].Y < 0 {
return nil, YCoordErr
}
sum[0] += s[i].X
sum[1] += s[i].Y
sum[2] += s[i].X * s[i].X * s[i].Y
@ -79,13 +77,14 @@ func ExponentialRegression(s Series) (regressions Series, err error) {
}
return regressions, nil
}
// LogarithmicRegression returns an logarithmic regression on data series
func LogarithmicRegression(s Series) (regressions Series, err error) {
if len(s) == 0 {
return nil, EmptyInputErr
return nil, EmptyInput
}
var sum [4]float64
@ -110,4 +109,5 @@ func LogarithmicRegression(s Series) (regressions Series, err error) {
}
return regressions, nil
}

View file

@ -6,7 +6,7 @@ import "math/rand"
func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) {
if input.Len() == 0 {
return nil, EmptyInputErr
return nil, EmptyInput
}
length := input.Len()

View file

@ -1,18 +0,0 @@
package stats
import "math"
// Sigmoid returns the input values in the range of -1 to 1
// along the sigmoid or s-shaped curve, commonly used in
// machine learning while training neural networks as an
// activation function.
func Sigmoid(input Float64Data) ([]float64, error) {
if input.Len() == 0 {
return Float64Data{}, EmptyInput
}
s := make([]float64, len(input))
for i, v := range input {
s[i] = 1 / (1 + math.Exp(-v))
}
return s, nil
}

View file

@ -1,25 +0,0 @@
package stats
import "math"
// SoftMax returns the input values in the range of 0 to 1
// with sum of all the probabilities being equal to one. It
// is commonly used in machine learning neural networks.
func SoftMax(input Float64Data) ([]float64, error) {
if input.Len() == 0 {
return Float64Data{}, EmptyInput
}
s := 0.0
c, _ := Max(input)
for _, e := range input {
s += math.Exp(e - c)
}
sm := make([]float64, len(input))
for i, v := range input {
sm[i] = math.Exp(v-c) / s
}
return sm, nil
}

View file

@ -6,7 +6,7 @@ import "math"
func Sum(input Float64Data) (sum float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Add em up

View file

@ -6,14 +6,14 @@ import "math"
func _variance(input Float64Data, sample int) (variance float64, err error) {
if input.Len() == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
// Sum the square of the mean subtracted from each number
m, _ := Mean(input)
for _, n := range input {
variance += (n - m) * (n - m)
variance += (float64(n) - m) * (float64(n) - m)
}
// When getting the mean of the squared differences
@ -56,7 +56,7 @@ func Covariance(data1, data2 Float64Data) (float64, error) {
l2 := data2.Len()
if l1 == 0 || l2 == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
if l1 != l2 {
@ -84,7 +84,7 @@ func CovariancePopulation(data1, data2 Float64Data) (float64, error) {
l2 := data2.Len()
if l1 == 0 || l2 == 0 {
return math.NaN(), EmptyInputErr
return math.NaN(), EmptyInput
}
if l1 != l2 {

View file

@ -1,3 +0,0 @@
module github.com/pborman/uuid
require github.com/google/uuid v1.0.0

View file

@ -1,2 +0,0 @@
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

View file

@ -54,8 +54,9 @@ func New() string {
return NewRandom().String()
}
// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for
// the formats parsed.
// Parse decodes s into a UUID or returns nil. Both the UUID form of
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
func Parse(s string) UUID {
gu, err := guuid.Parse(s)
if err == nil {

View file

@ -1,14 +1,10 @@
language: go
go_import_path: github.com/pkg/errors
go:
- 1.4.x
- 1.5.x
- 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.4.3
- 1.5.4
- 1.6.2
- 1.7.1
- tip
script:

View file

@ -1,4 +1,4 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
Package errors provides simple error handling primitives.
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
Before proposing a change, please discuss your change by raising an issue.
## License
## Licence
BSD-2-Clause

View file

@ -6,7 +6,7 @@
// return err
// }
//
// which when applied recursively up the call stack results in error reports
// which applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error.
@ -15,17 +15,16 @@
//
// The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called,
// together with the supplied message. For example
// and the supplied message. For example
//
// _, err := ioutil.ReadAll(r)
// if err != nil {
// return errors.Wrap(err, "read failed")
// }
//
// If additional control is required, the errors.WithStack and
// errors.WithMessage functions destructure errors.Wrap into its component
// operations: annotating an error with a stack trace and with a message,
// respectively.
// If additional control is required the errors.WithStack and errors.WithMessage
// functions destructure errors.Wrap into its component operations of annotating
// an error with a stack trace and an a message, respectively.
//
// Retrieving the cause of an error
//
@ -39,7 +38,7 @@
// }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error that does not implement causer, which is assumed to be
// the topmost error which does not implement causer, which is assumed to be
// the original cause. For example:
//
// switch err := errors.Cause(err).(type) {
@ -49,16 +48,16 @@
// // unknown error
// }
//
// Although the causer interface is not exported by this package, it is
// considered a part of its stable public interface.
// causer interface is not exported by this package, but is considered a part
// of stable public API.
//
// Formatted printing of errors
//
// All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported:
// be formatted by the fmt package. The following verbs are supported
//
// %s print the error. If the error has a Cause it will be
// printed recursively.
// printed recursively
// %v see %s
// %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail.
@ -66,13 +65,13 @@
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface:
// invoked. This information can be retrieved with the following interface.
//
// type stackTracer interface {
// StackTrace() errors.StackTrace
// }
//
// The returned errors.StackTrace type is defined as
// Where errors.StackTrace is defined as
//
// type StackTrace []Frame
//
@ -86,8 +85,8 @@
// }
// }
//
// Although the stackTracer interface is not exported by this package, it is
// considered a part of its stable public interface.
// stackTracer interface is not exported by this package, but is considered a part
// of stable public API.
//
// See the documentation for Frame.Format for more details.
package errors
@ -193,7 +192,7 @@ func Wrap(err error, message string) error {
}
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// at the point Wrapf is call, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
@ -221,18 +220,6 @@ func WithMessage(err error, message string) error {
}
}
// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}
type withMessage struct {
cause error
msg string

View file

@ -46,8 +46,7 @@ func (f Frame) line() int {
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+s path of source file relative to the compile time GOPATH
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
@ -80,14 +79,6 @@ func (f Frame) Format(s fmt.State, verb rune) {
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
@ -145,3 +136,43 @@ func funcname(name string) string {
i = strings.Index(name, ".")
return name[i+1:]
}
func trimGOPATH(name, file string) string {
// Here we want to get the source file path relative to the compile time
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
// GOPATH at runtime, but we can infer the number of path segments in the
// GOPATH. We note that fn.Name() returns the function name qualified by
// the import path, which does not include the GOPATH. Thus we can trim
// segments from the beginning of the file path until the number of path
// separators remaining is one more than the number of path separators in
// the function name. For example, given:
//
// GOPATH /home/user
// file /home/user/src/pkg/sub/file.go
// fn.Name() pkg/sub.Type.Method
//
// We want to produce:
//
// pkg/sub/file.go
//
// From this we can easily see that fn.Name() has one less path separator
// than our desired output. We count separators from the end of the file
// path until it finds two more than in the function name and then move
// one character forward to preserve the initial path segment without a
// leading separator.
const sep = "/"
goal := strings.Count(name, sep) + 2
i := len(file)
for n := 0; n < goal; n++ {
i = strings.LastIndex(file[:i], sep)
if i == -1 {
// not enough separators found, set i so that the slice expression
// below leaves file unmodified
i = -len(sep)
break
}
}
// get back to 0 or trim the leading separator
file = file[i+len(sep):]
return file
}

View file

@ -409,11 +409,13 @@ func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
defer close(reauthReadyChan)
if c.logInfo {
c.logger.Printf("re-submitting `%d` credentials after reconnect", len(c.creds))
c.logger.Printf("Re-submitting `%d` credentials after reconnect",
len(c.creds))
}
for _, cred := range c.creds {
if shouldCancel() {
c.logger.Printf("Cancel rer-submitting credentials")
return
}
resChan, err := c.sendRequest(
@ -426,7 +428,7 @@ func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
nil)
if err != nil {
c.logger.Printf("call to sendRequest failed during credential resubmit: %s", err)
c.logger.Printf("Call to sendRequest failed during credential resubmit: %s", err)
// FIXME(prozlach): lets ignore errors for now
continue
}
@ -435,14 +437,14 @@ func (c *Conn) resendZkAuth(reauthReadyChan chan struct{}) {
select {
case res = <-resChan:
case <-c.closeChan:
c.logger.Printf("recv closed, cancel re-submitting credentials")
c.logger.Printf("Recv closed, cancel re-submitting credentials")
return
case <-c.shouldQuit:
c.logger.Printf("should quit, cancel re-submitting credentials")
c.logger.Printf("Should quit, cancel re-submitting credentials")
return
}
if res.err != nil {
c.logger.Printf("credential re-submit failed: %s", res.err)
c.logger.Printf("Credential re-submit failed: %s", res.err)
// FIXME(prozlach): lets ignore errors for now
continue
}
@ -484,14 +486,14 @@ func (c *Conn) loop() {
err := c.authenticate()
switch {
case err == ErrSessionExpired:
c.logger.Printf("authentication failed: %s", err)
c.logger.Printf("Authentication failed: %s", err)
c.invalidateWatches(err)
case err != nil && c.conn != nil:
c.logger.Printf("authentication failed: %s", err)
c.logger.Printf("Authentication failed: %s", err)
c.conn.Close()
case err == nil:
if c.logInfo {
c.logger.Printf("authenticated: id=%d, timeout=%d", c.SessionID(), c.sessionTimeoutMs)
c.logger.Printf("Authenticated: id=%d, timeout=%d", c.SessionID(), c.sessionTimeoutMs)
}
c.hostProvider.Connected() // mark success
c.closeChan = make(chan struct{}) // channel to tell send loop stop
@ -506,7 +508,7 @@ func (c *Conn) loop() {
}
err := c.sendLoop()
if err != nil || c.logInfo {
c.logger.Printf("send loop terminated: err=%v", err)
c.logger.Printf("Send loop terminated: err=%v", err)
}
c.conn.Close() // causes recv loop to EOF/exit
wg.Done()
@ -521,7 +523,7 @@ func (c *Conn) loop() {
err = c.recvLoop(c.conn)
}
if err != io.EOF || c.logInfo {
c.logger.Printf("recv loop terminated: err=%v", err)
c.logger.Printf("Recv loop terminated: err=%v", err)
}
if err == nil {
panic("zk: recvLoop should never return nil error")
@ -695,28 +697,20 @@ func (c *Conn) authenticate() error {
binary.BigEndian.PutUint32(buf[:4], uint32(n))
if err := c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout * 10)); err != nil {
return err
}
c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout * 10))
_, err = c.conn.Write(buf[:n+4])
c.conn.SetWriteDeadline(time.Time{})
if err != nil {
return err
}
if err := c.conn.SetWriteDeadline(time.Time{}); err != nil {
return err
}
// Receive and decode a connect response.
if err := c.conn.SetReadDeadline(time.Now().Add(c.recvTimeout * 10)); err != nil {
return err
}
c.conn.SetReadDeadline(time.Now().Add(c.recvTimeout * 10))
_, err = io.ReadFull(c.conn, buf[:4])
c.conn.SetReadDeadline(time.Time{})
if err != nil {
return err
}
if err := c.conn.SetReadDeadline(time.Time{}); err != nil {
return err
}
blen := int(binary.BigEndian.Uint32(buf[:4]))
if cap(buf) < blen {
@ -778,18 +772,14 @@ func (c *Conn) sendData(req *request) error {
c.requests[req.xid] = req
c.requestsLock.Unlock()
if err := c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout)); err != nil {
return err
}
c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
_, err = c.conn.Write(c.buf[:n+4])
c.conn.SetWriteDeadline(time.Time{})
if err != nil {
req.recvChan <- response{-1, err}
c.conn.Close()
return err
}
if err := c.conn.SetWriteDeadline(time.Time{}); err != nil {
return err
}
return nil
}
@ -812,17 +802,13 @@ func (c *Conn) sendLoop() error {
binary.BigEndian.PutUint32(c.buf[:4], uint32(n))
if err := c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout)); err != nil {
return err
}
c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
_, err = c.conn.Write(c.buf[:n+4])
c.conn.SetWriteDeadline(time.Time{})
if err != nil {
c.conn.Close()
return err
}
if err := c.conn.SetWriteDeadline(time.Time{}); err != nil {
return err
}
case <-c.closeChan:
return nil
}
@ -837,12 +823,10 @@ func (c *Conn) recvLoop(conn net.Conn) error {
buf := make([]byte, sz)
for {
// package length
if err := conn.SetReadDeadline(time.Now().Add(c.recvTimeout)); err != nil {
c.logger.Printf("failed to set connection deadline: %v", err)
}
conn.SetReadDeadline(time.Now().Add(c.recvTimeout))
_, err := io.ReadFull(conn, buf[:4])
if err != nil {
return fmt.Errorf("failed to read from connection: %v", err)
return err
}
blen := int(binary.BigEndian.Uint32(buf[:4]))
@ -854,12 +838,10 @@ func (c *Conn) recvLoop(conn net.Conn) error {
}
_, err = io.ReadFull(conn, buf[:blen])
conn.SetReadDeadline(time.Time{})
if err != nil {
return err
}
if err := conn.SetReadDeadline(time.Time{}); err != nil {
return err
}
res := responseHeader{}
_, err = decodePacket(buf[:16], &res)
@ -892,7 +874,7 @@ func (c *Conn) recvLoop(conn net.Conn) error {
c.watchersLock.Lock()
for _, t := range wTypes {
wpt := watchPathType{res.Path, t}
if watchers, ok := c.watchers[wpt]; ok {
if watchers := c.watchers[wpt]; watchers != nil && len(watchers) > 0 {
for _, ch := range watchers {
ch <- ev
close(ch)
@ -1238,38 +1220,6 @@ func (c *Conn) Multi(ops ...interface{}) ([]MultiResponse, error) {
return mr, err
}
// IncrementalReconfig is the zookeeper reconfiguration api that allows adding and removing servers
// by lists of members.
// Return the new configuration stats.
func (c *Conn) IncrementalReconfig(joining, leaving []string, version int64) (*Stat, error) {
// TODO: validate the shape of the member string to give early feedback.
request := &reconfigRequest{
JoiningServers: []byte(strings.Join(joining, ",")),
LeavingServers: []byte(strings.Join(leaving, ",")),
CurConfigId: version,
}
return c.internalReconfig(request)
}
// Reconfig is the non-incremental update functionality for Zookeeper where the list preovided
// is the entire new member list.
// the optional version allows for conditional reconfigurations, -1 ignores the condition.
func (c *Conn) Reconfig(members []string, version int64) (*Stat, error) {
request := &reconfigRequest{
NewMembers: []byte(strings.Join(members, ",")),
CurConfigId: version,
}
return c.internalReconfig(request)
}
func (c *Conn) internalReconfig(request *reconfigRequest) (*Stat, error) {
response := &reconfigReponse{}
_, err := c.request(opReconfig, request, response, nil)
return &response.Stat, err
}
// Server returns the current or last-connected server name.
func (c *Conn) Server() string {
c.serverMu.Lock()

View file

@ -2,7 +2,6 @@ package zk
import (
"errors"
"fmt"
)
const (
@ -26,7 +25,6 @@ const (
opGetChildren2 = 12
opCheck = 13
opMulti = 14
opReconfig = 16
opClose = -11
opSetAuth = 100
opSetWatches = 101
@ -94,7 +92,7 @@ func (s State) String() string {
if name := stateNames[s]; name != "" {
return name
}
return "unknown state"
return "Unknown"
}
type ErrCode int32
@ -115,10 +113,8 @@ var (
ErrClosing = errors.New("zk: zookeeper is closing")
ErrNothing = errors.New("zk: no server responsees to process")
ErrSessionMoved = errors.New("zk: session moved to another server, so operation is ignored")
ErrReconfigDisabled = errors.New("attempts to perform a reconfiguration operation when reconfiguration feature is disabled")
ErrBadArguments = errors.New("invalid arguments")
// ErrInvalidCallback = errors.New("zk: invalid callback specified")
// ErrInvalidCallback = errors.New("zk: invalid callback specified")
errCodeToError = map[ErrCode]error{
0: nil,
errAPIError: ErrAPIError,
@ -130,13 +126,11 @@ var (
errNotEmpty: ErrNotEmpty,
errSessionExpired: ErrSessionExpired,
// errInvalidCallback: ErrInvalidCallback,
errInvalidAcl: ErrInvalidACL,
errAuthFailed: ErrAuthFailed,
errClosing: ErrClosing,
errNothing: ErrNothing,
errSessionMoved: ErrSessionMoved,
errZReconfigDisabled: ErrReconfigDisabled,
errBadArguments: ErrBadArguments,
errInvalidAcl: ErrInvalidACL,
errAuthFailed: ErrAuthFailed,
errClosing: ErrClosing,
errNothing: ErrNothing,
errSessionMoved: ErrSessionMoved,
}
)
@ -144,7 +138,7 @@ func (e ErrCode) toError() error {
if err, ok := errCodeToError[e]; ok {
return err
}
return fmt.Errorf("unknown error: %v", e)
return ErrUnknown
}
const (
@ -174,8 +168,6 @@ const (
errClosing ErrCode = -116
errNothing ErrCode = -117
errSessionMoved ErrCode = -118
// Attempts to perform a reconfiguration operation when reconfiguration feature is disabled
errZReconfigDisabled ErrCode = -123
)
// Constants for ACL permissions
@ -205,7 +197,6 @@ var (
opGetChildren2: "getChildren2",
opCheck: "check",
opMulti: "multi",
opReconfig: "reconfig",
opClose: "close",
opSetAuth: "setAuth",
opSetWatches: "setWatches",

View file

@ -255,16 +255,12 @@ func fourLetterWord(server, command string, timeout time.Duration) ([]byte, erro
// once the command has been processed, but better safe than sorry
defer conn.Close()
if err := conn.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
return nil, err
}
conn.SetWriteDeadline(time.Now().Add(timeout))
_, err = conn.Write([]byte(command))
if err != nil {
return nil, err
}
if err := conn.SetReadDeadline(time.Now().Add(timeout)); err != nil {
return nil, err
}
conn.SetReadDeadline(time.Now().Add(timeout))
return ioutil.ReadAll(conn)
}

216
vendor/github.com/samuel/go-zookeeper/zk/server_help.go generated vendored Normal file
View file

@ -0,0 +1,216 @@
package zk
import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"strings"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type TestServer struct {
Port int
Path string
Srv *Server
}
type TestCluster struct {
Path string
Servers []TestServer
}
func StartTestCluster(size int, stdout, stderr io.Writer) (*TestCluster, error) {
tmpPath, err := ioutil.TempDir("", "gozk")
if err != nil {
return nil, err
}
success := false
startPort := int(rand.Int31n(6000) + 10000)
cluster := &TestCluster{Path: tmpPath}
defer func() {
if !success {
cluster.Stop()
}
}()
for serverN := 0; serverN < size; serverN++ {
srvPath := filepath.Join(tmpPath, fmt.Sprintf("srv%d", serverN))
if err := os.Mkdir(srvPath, 0700); err != nil {
return nil, err
}
port := startPort + serverN*3
cfg := ServerConfig{
ClientPort: port,
DataDir: srvPath,
}
for i := 0; i < size; i++ {
cfg.Servers = append(cfg.Servers, ServerConfigServer{
ID: i + 1,
Host: "127.0.0.1",
PeerPort: startPort + i*3 + 1,
LeaderElectionPort: startPort + i*3 + 2,
})
}
cfgPath := filepath.Join(srvPath, "zoo.cfg")
fi, err := os.Create(cfgPath)
if err != nil {
return nil, err
}
err = cfg.Marshall(fi)
fi.Close()
if err != nil {
return nil, err
}
fi, err = os.Create(filepath.Join(srvPath, "myid"))
if err != nil {
return nil, err
}
_, err = fmt.Fprintf(fi, "%d\n", serverN+1)
fi.Close()
if err != nil {
return nil, err
}
srv := &Server{
ConfigPath: cfgPath,
Stdout: stdout,
Stderr: stderr,
}
if err := srv.Start(); err != nil {
return nil, err
}
cluster.Servers = append(cluster.Servers, TestServer{
Path: srvPath,
Port: cfg.ClientPort,
Srv: srv,
})
}
if err := cluster.waitForStart(10, time.Second); err != nil {
return nil, err
}
success = true
return cluster, nil
}
func (tc *TestCluster) Connect(idx int) (*Conn, error) {
zk, _, err := Connect([]string{fmt.Sprintf("127.0.0.1:%d", tc.Servers[idx].Port)}, time.Second*15)
return zk, err
}
func (tc *TestCluster) ConnectAll() (*Conn, <-chan Event, error) {
return tc.ConnectAllTimeout(time.Second * 15)
}
func (tc *TestCluster) ConnectAllTimeout(sessionTimeout time.Duration) (*Conn, <-chan Event, error) {
return tc.ConnectWithOptions(sessionTimeout)
}
func (tc *TestCluster) ConnectWithOptions(sessionTimeout time.Duration, options ...connOption) (*Conn, <-chan Event, error) {
hosts := make([]string, len(tc.Servers))
for i, srv := range tc.Servers {
hosts[i] = fmt.Sprintf("127.0.0.1:%d", srv.Port)
}
zk, ch, err := Connect(hosts, sessionTimeout, options...)
return zk, ch, err
}
func (tc *TestCluster) Stop() error {
for _, srv := range tc.Servers {
srv.Srv.Stop()
}
defer os.RemoveAll(tc.Path)
return tc.waitForStop(5, time.Second)
}
// waitForStart blocks until the cluster is up
func (tc *TestCluster) waitForStart(maxRetry int, interval time.Duration) error {
// verify that the servers are up with SRVR
serverAddrs := make([]string, len(tc.Servers))
for i, s := range tc.Servers {
serverAddrs[i] = fmt.Sprintf("127.0.0.1:%d", s.Port)
}
for i := 0; i < maxRetry; i++ {
_, ok := FLWSrvr(serverAddrs, time.Second)
if ok {
return nil
}
time.Sleep(interval)
}
return fmt.Errorf("unable to verify health of servers")
}
// waitForStop blocks until the cluster is down
func (tc *TestCluster) waitForStop(maxRetry int, interval time.Duration) error {
// verify that the servers are up with RUOK
serverAddrs := make([]string, len(tc.Servers))
for i, s := range tc.Servers {
serverAddrs[i] = fmt.Sprintf("127.0.0.1:%d", s.Port)
}
var success bool
for i := 0; i < maxRetry && !success; i++ {
success = true
for _, ok := range FLWRuok(serverAddrs, time.Second) {
if ok {
success = false
}
}
if !success {
time.Sleep(interval)
}
}
if !success {
return fmt.Errorf("unable to verify servers are down")
}
return nil
}
func (tc *TestCluster) StartServer(server string) {
for _, s := range tc.Servers {
if strings.HasSuffix(server, fmt.Sprintf(":%d", s.Port)) {
s.Srv.Start()
return
}
}
panic(fmt.Sprintf("Unknown server: %s", server))
}
func (tc *TestCluster) StopServer(server string) {
for _, s := range tc.Servers {
if strings.HasSuffix(server, fmt.Sprintf(":%d", s.Port)) {
s.Srv.Stop()
return
}
}
panic(fmt.Sprintf("Unknown server: %s", server))
}
func (tc *TestCluster) StartAllServers() error {
for _, s := range tc.Servers {
if err := s.Srv.Start(); err != nil {
return fmt.Errorf(
"Failed to start server listening on port `%d` : %+v", s.Port, err)
}
}
return nil
}
func (tc *TestCluster) StopAllServers() error {
for _, s := range tc.Servers {
if err := s.Srv.Stop(); err != nil {
return fmt.Errorf(
"Failed to stop server listening on port `%d` : %+v", s.Port, err)
}
}
return nil
}

136
vendor/github.com/samuel/go-zookeeper/zk/server_java.go generated vendored Normal file
View file

@ -0,0 +1,136 @@
package zk
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
)
type ErrMissingServerConfigField string
func (e ErrMissingServerConfigField) Error() string {
return fmt.Sprintf("zk: missing server config field '%s'", string(e))
}
const (
DefaultServerTickTime = 2000
DefaultServerInitLimit = 10
DefaultServerSyncLimit = 5
DefaultServerAutoPurgeSnapRetainCount = 3
DefaultPeerPort = 2888
DefaultLeaderElectionPort = 3888
)
type ServerConfigServer struct {
ID int
Host string
PeerPort int
LeaderElectionPort int
}
type ServerConfig struct {
TickTime int // Number of milliseconds of each tick
InitLimit int // Number of ticks that the initial synchronization phase can take
SyncLimit int // Number of ticks that can pass between sending a request and getting an acknowledgement
DataDir string // Direcrory where the snapshot is stored
ClientPort int // Port at which clients will connect
AutoPurgeSnapRetainCount int // Number of snapshots to retain in dataDir
AutoPurgePurgeInterval int // Purge task internal in hours (0 to disable auto purge)
Servers []ServerConfigServer
}
func (sc ServerConfig) Marshall(w io.Writer) error {
if sc.DataDir == "" {
return ErrMissingServerConfigField("dataDir")
}
fmt.Fprintf(w, "dataDir=%s\n", sc.DataDir)
if sc.TickTime <= 0 {
sc.TickTime = DefaultServerTickTime
}
fmt.Fprintf(w, "tickTime=%d\n", sc.TickTime)
if sc.InitLimit <= 0 {
sc.InitLimit = DefaultServerInitLimit
}
fmt.Fprintf(w, "initLimit=%d\n", sc.InitLimit)
if sc.SyncLimit <= 0 {
sc.SyncLimit = DefaultServerSyncLimit
}
fmt.Fprintf(w, "syncLimit=%d\n", sc.SyncLimit)
if sc.ClientPort <= 0 {
sc.ClientPort = DefaultPort
}
fmt.Fprintf(w, "clientPort=%d\n", sc.ClientPort)
if sc.AutoPurgePurgeInterval > 0 {
if sc.AutoPurgeSnapRetainCount <= 0 {
sc.AutoPurgeSnapRetainCount = DefaultServerAutoPurgeSnapRetainCount
}
fmt.Fprintf(w, "autopurge.snapRetainCount=%d\n", sc.AutoPurgeSnapRetainCount)
fmt.Fprintf(w, "autopurge.purgeInterval=%d\n", sc.AutoPurgePurgeInterval)
}
if len(sc.Servers) > 0 {
for _, srv := range sc.Servers {
if srv.PeerPort <= 0 {
srv.PeerPort = DefaultPeerPort
}
if srv.LeaderElectionPort <= 0 {
srv.LeaderElectionPort = DefaultLeaderElectionPort
}
fmt.Fprintf(w, "server.%d=%s:%d:%d\n", srv.ID, srv.Host, srv.PeerPort, srv.LeaderElectionPort)
}
}
return nil
}
var jarSearchPaths = []string{
"zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
"../zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
"/usr/share/java/zookeeper-*.jar",
"/usr/local/zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
"/usr/local/Cellar/zookeeper/*/libexec/contrib/fatjar/zookeeper-*-fatjar.jar",
}
func findZookeeperFatJar() string {
var paths []string
zkPath := os.Getenv("ZOOKEEPER_PATH")
if zkPath == "" {
paths = jarSearchPaths
} else {
paths = []string{filepath.Join(zkPath, "contrib/fatjar/zookeeper-*-fatjar.jar")}
}
for _, path := range paths {
matches, _ := filepath.Glob(path)
// TODO: could sort by version and pick latest
if len(matches) > 0 {
return matches[0]
}
}
return ""
}
type Server struct {
JarPath string
ConfigPath string
Stdout, Stderr io.Writer
cmd *exec.Cmd
}
func (srv *Server) Start() error {
if srv.JarPath == "" {
srv.JarPath = findZookeeperFatJar()
if srv.JarPath == "" {
return fmt.Errorf("zk: unable to find server jar")
}
}
srv.cmd = exec.Command("java", "-jar", srv.JarPath, "server", srv.ConfigPath)
srv.cmd.Stdout = srv.Stdout
srv.cmd.Stderr = srv.Stderr
return srv.cmd.Start()
}
func (srv *Server) Stop() error {
srv.cmd.Process.Signal(os.Kill)
return srv.cmd.Wait()
}

View file

@ -6,7 +6,6 @@ import (
"log"
"reflect"
"runtime"
"strings"
"time"
)
@ -278,18 +277,6 @@ type multiResponse struct {
DoneHeader multiHeader
}
// zk version 3.5 reconfig API
type reconfigRequest struct {
JoiningServers []byte
LeavingServers []byte
NewMembers []byte
// curConfigId version of the current configuration
// optional - causes reconfiguration to return an error if configuration is no longer current
CurConfigId int64
}
type reconfigReponse getDataResponse
func (r *multiRequest) Encode(buf []byte) (int, error) {
total := 0
for _, op := range r.Ops {
@ -405,7 +392,7 @@ type encoder interface {
func decodePacket(buf []byte, st interface{}) (n int, err error) {
defer func() {
if r := recover(); r != nil {
if e, ok := r.(runtime.Error); ok && strings.HasPrefix(e.Error(), "runtime error: slice bounds out of range") {
if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
err = ErrShortBuffer
} else {
panic(r)
@ -496,7 +483,7 @@ func decodePacketValue(buf []byte, v reflect.Value) (int, error) {
func encodePacket(buf []byte, st interface{}) (n int, err error) {
defer func() {
if r := recover(); r != nil {
if e, ok := r.(runtime.Error); ok && strings.HasPrefix(e.Error(), "runtime error: slice bounds out of range") {
if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
err = ErrShortBuffer
} else {
panic(r)
@ -617,8 +604,6 @@ func requestStructForOp(op int32) interface{} {
return &CheckVersionRequest{}
case opMulti:
return &multiRequest{}
case opReconfig:
return &reconfigRequest{}
}
return nil
}

View file

@ -86,7 +86,7 @@ func feFromBytes(dst *fieldElement, src *[32]byte) {
h6 := load3(src[20:]) << 7
h7 := load3(src[23:]) << 5
h8 := load3(src[26:]) << 4
h9 := (load3(src[29:]) & 0x7fffff) << 2
h9 := load3(src[29:]) << 2
var carry [10]int64
carry[9] = (h9 + 1<<24) >> 25

View file

@ -121,18 +121,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -236,18 +236,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -441,18 +441,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -591,18 +591,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -731,18 +731,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -846,18 +846,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -996,18 +996,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -1146,18 +1146,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX
@ -1332,18 +1332,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12
ADCQ DX,R13
MOVQ $REDMASK51,DX
SHLQ $13,SI,CX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ DX,R8
ADDQ CX,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ DX,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ DX,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ DX,R14
ADDQ R13,R14
IMUL3Q $19,R15,CX

View file

@ -124,18 +124,18 @@ TEXT ·mul(SB),0,$16-24
ADDQ AX,R14
ADCQ DX,R15
MOVQ $REDMASK51,SI
SHLQ $13,R8,R9
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R10,R11
SHLQ $13,R11:R10
ANDQ SI,R10
ADDQ R9,R10
SHLQ $13,R12,R13
SHLQ $13,R13:R12
ANDQ SI,R12
ADDQ R11,R12
SHLQ $13,R14,R15
SHLQ $13,R15:R14
ANDQ SI,R14
ADDQ R13,R14
SHLQ $13,BX,BP
SHLQ $13,BP:BX
ANDQ SI,BX
ADDQ R15,BX
IMUL3Q $19,BP,DX

View file

@ -87,18 +87,18 @@ TEXT ·square(SB),7,$0-16
ADDQ AX,R13
ADCQ DX,R14
MOVQ $REDMASK51,SI
SHLQ $13,CX,R8
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R9,R10
SHLQ $13,R10:R9
ANDQ SI,R9
ADDQ R8,R9
SHLQ $13,R11,R12
SHLQ $13,R12:R11
ANDQ SI,R11
ADDQ R10,R11
SHLQ $13,R13,R14
SHLQ $13,R14:R13
ANDQ SI,R13
ADDQ R12,R13
SHLQ $13,R15,BX
SHLQ $13,BX:R15
ANDQ SI,R15
ADDQ R14,R15
IMUL3Q $19,BX,DX

View file

@ -2,11 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// In Go 1.13, the ed25519 package was promoted to the standard library as
// crypto/ed25519, and this package became a wrapper for the standard library one.
//
// +build !go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//

View file

@ -1,73 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
// Beginning with Go 1.13, the functionality of this package was moved to the
// standard library as crypto/ed25519. This package only acts as a compatibility
// wrapper.
package ed25519
import (
"crypto/ed25519"
"io"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
//
// This type is an alias for crypto/ed25519's PublicKey type.
// See the crypto/ed25519 package for the methods on this type.
type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
//
// This type is an alias for crypto/ed25519's PrivateKey type.
// See the crypto/ed25519 package for the methods on this type.
type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}

View file

@ -1,308 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.11
// +build !gccgo,!appengine
#include "textflag.h"
#define NUM_ROUNDS 10
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD dst+0(FP), R1
MOVD src+24(FP), R2
MOVD src_len+32(FP), R3
MOVD key+48(FP), R4
MOVD nonce+56(FP), R6
MOVD counter+64(FP), R7
MOVD $·constants(SB), R10
MOVD $·incRotMatrix(SB), R11
MOVW (R7), R20
AND $~255, R3, R13
ADD R2, R13, R12 // R12 for block end
AND $255, R3, R13
loop:
MOVD $NUM_ROUNDS, R21
VLD1 (R11), [V30.S4, V31.S4]
// load contants
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
WORD $0x4D60E940
// load keys
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
WORD $0x4DFFE884
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
WORD $0x4DFFE888
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V12.S4]
WORD $0x4D40C8EC
// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
WORD $0x4D40E8CD
// update counter
VADD V30.S4, V12.S4, V12.S4
chacha:
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
VADD V8.S4, V12.S4, V8.S4
VADD V9.S4, V13.S4, V9.S4
VADD V10.S4, V14.S4, V10.S4
VADD V11.S4, V15.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $12, V16.S4, V4.S4
VSHL $12, V17.S4, V5.S4
VSHL $12, V18.S4, V6.S4
VSHL $12, V19.S4, V7.S4
VSRI $20, V16.S4, V4.S4
VSRI $20, V17.S4, V5.S4
VSRI $20, V18.S4, V6.S4
VSRI $20, V19.S4, V7.S4
// V0..V3 += V4..V7
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
VADD V0.S4, V4.S4, V0.S4
VADD V1.S4, V5.S4, V1.S4
VADD V2.S4, V6.S4, V2.S4
VADD V3.S4, V7.S4, V3.S4
VEOR V12.B16, V0.B16, V12.B16
VEOR V13.B16, V1.B16, V13.B16
VEOR V14.B16, V2.B16, V14.B16
VEOR V15.B16, V3.B16, V15.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V8..V11 += V12..V15
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
VADD V12.S4, V8.S4, V8.S4
VADD V13.S4, V9.S4, V9.S4
VADD V14.S4, V10.S4, V10.S4
VADD V15.S4, V11.S4, V11.S4
VEOR V8.B16, V4.B16, V16.B16
VEOR V9.B16, V5.B16, V17.B16
VEOR V10.B16, V6.B16, V18.B16
VEOR V11.B16, V7.B16, V19.B16
VSHL $7, V16.S4, V4.S4
VSHL $7, V17.S4, V5.S4
VSHL $7, V18.S4, V6.S4
VSHL $7, V19.S4, V7.S4
VSRI $25, V16.S4, V4.S4
VSRI $25, V17.S4, V5.S4
VSRI $25, V18.S4, V6.S4
VSRI $25, V19.S4, V7.S4
// V0..V3 += V5..V7, V4
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
VADD V0.S4, V5.S4, V0.S4
VADD V1.S4, V6.S4, V1.S4
VADD V2.S4, V7.S4, V2.S4
VADD V3.S4, V4.S4, V3.S4
VEOR V15.B16, V0.B16, V15.B16
VEOR V12.B16, V1.B16, V12.B16
VEOR V13.B16, V2.B16, V13.B16
VEOR V14.B16, V3.B16, V14.B16
VREV32 V12.H8, V12.H8
VREV32 V13.H8, V13.H8
VREV32 V14.H8, V14.H8
VREV32 V15.H8, V15.H8
// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $12, V16.S4, V5.S4
VSHL $12, V17.S4, V6.S4
VSHL $12, V18.S4, V7.S4
VSHL $12, V19.S4, V4.S4
VSRI $20, V16.S4, V5.S4
VSRI $20, V17.S4, V6.S4
VSRI $20, V18.S4, V7.S4
VSRI $20, V19.S4, V4.S4
// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
// ...
VADD V5.S4, V0.S4, V0.S4
VADD V6.S4, V1.S4, V1.S4
VADD V7.S4, V2.S4, V2.S4
VADD V4.S4, V3.S4, V3.S4
VEOR V0.B16, V15.B16, V15.B16
VEOR V1.B16, V12.B16, V12.B16
VEOR V2.B16, V13.B16, V13.B16
VEOR V3.B16, V14.B16, V14.B16
VTBL V31.B16, [V12.B16], V12.B16
VTBL V31.B16, [V13.B16], V13.B16
VTBL V31.B16, [V14.B16], V14.B16
VTBL V31.B16, [V15.B16], V15.B16
// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
// ...
VADD V15.S4, V10.S4, V10.S4
VADD V12.S4, V11.S4, V11.S4
VADD V13.S4, V8.S4, V8.S4
VADD V14.S4, V9.S4, V9.S4
VEOR V10.B16, V5.B16, V16.B16
VEOR V11.B16, V6.B16, V17.B16
VEOR V8.B16, V7.B16, V18.B16
VEOR V9.B16, V4.B16, V19.B16
VSHL $7, V16.S4, V5.S4
VSHL $7, V17.S4, V6.S4
VSHL $7, V18.S4, V7.S4
VSHL $7, V19.S4, V4.S4
VSRI $25, V16.S4, V5.S4
VSRI $25, V17.S4, V6.S4
VSRI $25, V18.S4, V7.S4
VSRI $25, V19.S4, V4.S4
SUB $1, R21
CBNZ R21, chacha
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
WORD $0x4D60E950
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
WORD $0x4DFFE894
VADD V30.S4, V12.S4, V12.S4
VADD V16.S4, V0.S4, V0.S4
VADD V17.S4, V1.S4, V1.S4
VADD V18.S4, V2.S4, V2.S4
VADD V19.S4, V3.S4, V3.S4
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
WORD $0x4DFFE898
// restore R4
SUB $32, R4
// load counter + nonce
// VLD1R (R7), [V28.S4]
WORD $0x4D40C8FC
// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
WORD $0x4D40E8DD
VADD V20.S4, V4.S4, V4.S4
VADD V21.S4, V5.S4, V5.S4
VADD V22.S4, V6.S4, V6.S4
VADD V23.S4, V7.S4, V7.S4
VADD V24.S4, V8.S4, V8.S4
VADD V25.S4, V9.S4, V9.S4
VADD V26.S4, V10.S4, V10.S4
VADD V27.S4, V11.S4, V11.S4
VADD V28.S4, V12.S4, V12.S4
VADD V29.S4, V13.S4, V13.S4
VADD V30.S4, V14.S4, V14.S4
VADD V31.S4, V15.S4, V15.S4
VZIP1 V1.S4, V0.S4, V16.S4
VZIP2 V1.S4, V0.S4, V17.S4
VZIP1 V3.S4, V2.S4, V18.S4
VZIP2 V3.S4, V2.S4, V19.S4
VZIP1 V5.S4, V4.S4, V20.S4
VZIP2 V5.S4, V4.S4, V21.S4
VZIP1 V7.S4, V6.S4, V22.S4
VZIP2 V7.S4, V6.S4, V23.S4
VZIP1 V9.S4, V8.S4, V24.S4
VZIP2 V9.S4, V8.S4, V25.S4
VZIP1 V11.S4, V10.S4, V26.S4
VZIP2 V11.S4, V10.S4, V27.S4
VZIP1 V13.S4, V12.S4, V28.S4
VZIP2 V13.S4, V12.S4, V29.S4
VZIP1 V15.S4, V14.S4, V30.S4
VZIP2 V15.S4, V14.S4, V31.S4
VZIP1 V18.D2, V16.D2, V0.D2
VZIP2 V18.D2, V16.D2, V4.D2
VZIP1 V19.D2, V17.D2, V8.D2
VZIP2 V19.D2, V17.D2, V12.D2
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
VZIP1 V22.D2, V20.D2, V1.D2
VZIP2 V22.D2, V20.D2, V5.D2
VZIP1 V23.D2, V21.D2, V9.D2
VZIP2 V23.D2, V21.D2, V13.D2
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
VZIP1 V26.D2, V24.D2, V2.D2
VZIP2 V26.D2, V24.D2, V6.D2
VZIP1 V27.D2, V25.D2, V10.D2
VZIP2 V27.D2, V25.D2, V14.D2
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
VZIP1 V30.D2, V28.D2, V3.D2
VZIP2 V30.D2, V28.D2, V7.D2
VZIP1 V31.D2, V29.D2, V11.D2
VZIP2 V31.D2, V29.D2, V15.D2
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
VEOR V0.B16, V16.B16, V16.B16
VEOR V1.B16, V17.B16, V17.B16
VEOR V2.B16, V18.B16, V18.B16
VEOR V3.B16, V19.B16, V19.B16
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
VEOR V4.B16, V20.B16, V20.B16
VEOR V5.B16, V21.B16, V21.B16
VEOR V6.B16, V22.B16, V22.B16
VEOR V7.B16, V23.B16, V23.B16
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
VEOR V8.B16, V24.B16, V24.B16
VEOR V9.B16, V25.B16, V25.B16
VEOR V10.B16, V26.B16, V26.B16
VEOR V11.B16, V27.B16, V27.B16
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
VEOR V12.B16, V28.B16, V28.B16
VEOR V13.B16, V29.B16, V29.B16
VEOR V14.B16, V30.B16, V30.B16
VEOR V15.B16, V31.B16, V31.B16
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
ADD $4, R20
MOVW R20, (R7) // update counter
CMP R2, R12
BGT loop
RET
DATA ·constants+0x00(SB)/4, $0x61707865
DATA ·constants+0x04(SB)/4, $0x3320646e
DATA ·constants+0x08(SB)/4, $0x79622d32
DATA ·constants+0x0c(SB)/4, $0x6b206574
GLOBL ·constants(SB), NOPTR|RODATA, $32
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32

View file

@ -1,668 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on CRYPTOGAMS code with the following comment:
// # ====================================================================
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
// # project. The module is, however, dual licensed under OpenSSL and
// # CRYPTOGAMS licenses depending on where you obtain it. For further
// # details see http://www.openssl.org/~appro/cryptogams/.
// # ====================================================================
// Original code can be found at the link below:
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91e5c39ca79126a4a876d5d8ff
// There are some differences between CRYPTOGAMS code and this one. The round
// loop for "_int" isn't the same as the original. Some adjustments were
// necessary because there are less vector registers available. For example, some
// X variables (r12, r13, r14, and r15) share the same register used by the
// counter. The original code uses ctr to name the counter. Here we use CNT
// because golang uses CTR as the counter register name.
// +build ppc64le,!gccgo,!appengine
#include "textflag.h"
#define OUT R3
#define INP R4
#define LEN R5
#define KEY R6
#define CNT R7
#define TEMP R8
#define X0 R11
#define X1 R12
#define X2 R14
#define X3 R15
#define X4 R16
#define X5 R17
#define X6 R18
#define X7 R19
#define X8 R20
#define X9 R21
#define X10 R22
#define X11 R23
#define X12 R24
#define X13 R25
#define X14 R26
#define X15 R27
#define CON0 X0
#define CON1 X1
#define CON2 X2
#define CON3 X3
#define KEY0 X4
#define KEY1 X5
#define KEY2 X6
#define KEY3 X7
#define KEY4 X8
#define KEY5 X9
#define KEY6 X10
#define KEY7 X11
#define CNT0 X12
#define CNT1 X13
#define CNT2 X14
#define CNT3 X15
#define TMP0 R9
#define TMP1 R10
#define TMP2 R28
#define TMP3 R29
#define CONSTS R8
#define A0 V0
#define B0 V1
#define C0 V2
#define D0 V3
#define A1 V4
#define B1 V5
#define C1 V6
#define D1 V7
#define A2 V8
#define B2 V9
#define C2 V10
#define D2 V11
#define T0 V12
#define T1 V13
#define T2 V14
#define K0 V15
#define K1 V16
#define K2 V17
#define K3 V18
#define K4 V19
#define K5 V20
#define FOUR V21
#define SIXTEEN V22
#define TWENTY4 V23
#define TWENTY V24
#define TWELVE V25
#define TWENTY5 V26
#define SEVEN V27
#define INPPERM V28
#define OUTPERM V29
#define OUTMASK V30
#define DD0 V31
#define DD1 SEVEN
#define DD2 T0
#define DD3 T1
#define DD4 T2
DATA ·consts+0x00(SB)/8, $0x3320646e61707865
DATA ·consts+0x08(SB)/8, $0x6b20657479622d32
DATA ·consts+0x10(SB)/8, $0x0000000000000001
DATA ·consts+0x18(SB)/8, $0x0000000000000000
DATA ·consts+0x20(SB)/8, $0x0000000000000004
DATA ·consts+0x28(SB)/8, $0x0000000000000000
DATA ·consts+0x30(SB)/8, $0x0a0b08090e0f0c0d
DATA ·consts+0x38(SB)/8, $0x0203000106070405
DATA ·consts+0x40(SB)/8, $0x090a0b080d0e0f0c
DATA ·consts+0x48(SB)/8, $0x0102030005060704
GLOBL ·consts(SB), RODATA, $80
//func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[32]byte, counter *[16]byte)
TEXT ·chaCha20_ctr32_vmx(SB),NOSPLIT|NOFRAME,$0
// Load the arguments inside the registers
MOVD out+0(FP), OUT
MOVD inp+8(FP), INP
MOVD len+16(FP), LEN
MOVD key+24(FP), KEY
MOVD counter+32(FP), CNT
MOVD $·consts(SB), CONSTS // point to consts addr
MOVD $16, X0
MOVD $32, X1
MOVD $48, X2
MOVD $64, X3
MOVD $31, X4
MOVD $15, X5
// Load key
LVX (KEY)(R0), K1
LVSR (KEY)(R0), T0
LVX (KEY)(X0), K2
LVX (KEY)(X4), DD0
// Load counter
LVX (CNT)(R0), K3
LVSR (CNT)(R0), T1
LVX (CNT)(X5), DD1
// Load constants
LVX (CONSTS)(R0), K0
LVX (CONSTS)(X0), K5
LVX (CONSTS)(X1), FOUR
LVX (CONSTS)(X2), SIXTEEN
LVX (CONSTS)(X3), TWENTY4
// Align key and counter
VPERM K2, K1, T0, K1
VPERM DD0, K2, T0, K2
VPERM DD1, K3, T1, K3
// Load counter to GPR
MOVWZ 0(CNT), CNT0
MOVWZ 4(CNT), CNT1
MOVWZ 8(CNT), CNT2
MOVWZ 12(CNT), CNT3
// Adjust vectors for the initial state
VADDUWM K3, K5, K3
VADDUWM K3, K5, K4
VADDUWM K4, K5, K5
// Synthesized constants
VSPLTISW $-12, TWENTY
VSPLTISW $12, TWELVE
VSPLTISW $-7, TWENTY5
VXOR T0, T0, T0
VSPLTISW $-1, OUTMASK
LVSR (INP)(R0), INPPERM
LVSL (OUT)(R0), OUTPERM
VPERM OUTMASK, T0, OUTPERM, OUTMASK
loop_outer_vmx:
// Load constant
MOVD $0x61707865, CON0
MOVD $0x3320646e, CON1
MOVD $0x79622d32, CON2
MOVD $0x6b206574, CON3
VOR K0, K0, A0
VOR K0, K0, A1
VOR K0, K0, A2
VOR K1, K1, B0
MOVD $10, TEMP
// Load key to GPR
MOVWZ 0(KEY), X4
MOVWZ 4(KEY), X5
MOVWZ 8(KEY), X6
MOVWZ 12(KEY), X7
VOR K1, K1, B1
VOR K1, K1, B2
MOVWZ 16(KEY), X8
MOVWZ 0(CNT), X12
MOVWZ 20(KEY), X9
MOVWZ 4(CNT), X13
VOR K2, K2, C0
VOR K2, K2, C1
MOVWZ 24(KEY), X10
MOVWZ 8(CNT), X14
VOR K2, K2, C2
VOR K3, K3, D0
MOVWZ 28(KEY), X11
MOVWZ 12(CNT), X15
VOR K4, K4, D1
VOR K5, K5, D2
MOVD X4, TMP0
MOVD X5, TMP1
MOVD X6, TMP2
MOVD X7, TMP3
VSPLTISW $7, SEVEN
MOVD TEMP, CTR
loop_vmx:
// CRYPTOGAMS uses a macro to create a loop using perl. This isn't possible
// using assembly macros. Therefore, the macro expansion result was used
// in order to maintain the algorithm efficiency.
// This loop generates three keystream blocks using VMX instructions and,
// in parallel, one keystream block using scalar instructions.
ADD X4, X0, X0
ADD X5, X1, X1
VADDUWM A0, B0, A0
VADDUWM A1, B1, A1
ADD X6, X2, X2
ADD X7, X3, X3
VADDUWM A2, B2, A2
VXOR D0, A0, D0
XOR X0, X12, X12
XOR X1, X13, X13
VXOR D1, A1, D1
VXOR D2, A2, D2
XOR X2, X14, X14
XOR X3, X15, X15
VPERM D0, D0, SIXTEEN, D0
VPERM D1, D1, SIXTEEN, D1
ROTLW $16, X12, X12
ROTLW $16, X13, X13
VPERM D2, D2, SIXTEEN, D2
VADDUWM C0, D0, C0
ROTLW $16, X14, X14
ROTLW $16, X15, X15
VADDUWM C1, D1, C1
VADDUWM C2, D2, C2
ADD X12, X8, X8
ADD X13, X9, X9
VXOR B0, C0, T0
VXOR B1, C1, T1
ADD X14, X10, X10
ADD X15, X11, X11
VXOR B2, C2, T2
VRLW T0, TWELVE, B0
XOR X8, X4, X4
XOR X9, X5, X5
VRLW T1, TWELVE, B1
VRLW T2, TWELVE, B2
XOR X10, X6, X6
XOR X11, X7, X7
VADDUWM A0, B0, A0
VADDUWM A1, B1, A1
ROTLW $12, X4, X4
ROTLW $12, X5, X5
VADDUWM A2, B2, A2
VXOR D0, A0, D0
ROTLW $12, X6, X6
ROTLW $12, X7, X7
VXOR D1, A1, D1
VXOR D2, A2, D2
ADD X4, X0, X0
ADD X5, X1, X1
VPERM D0, D0, TWENTY4, D0
VPERM D1, D1, TWENTY4, D1
ADD X6, X2, X2
ADD X7, X3, X3
VPERM D2, D2, TWENTY4, D2
VADDUWM C0, D0, C0
XOR X0, X12, X12
XOR X1, X13, X13
VADDUWM C1, D1, C1
VADDUWM C2, D2, C2
XOR X2, X14, X14
XOR X3, X15, X15
VXOR B0, C0, T0
VXOR B1, C1, T1
ROTLW $8, X12, X12
ROTLW $8, X13, X13
VXOR B2, C2, T2
VRLW T0, SEVEN, B0
ROTLW $8, X14, X14
ROTLW $8, X15, X15
VRLW T1, SEVEN, B1
VRLW T2, SEVEN, B2
ADD X12, X8, X8
ADD X13, X9, X9
VSLDOI $8, C0, C0, C0
VSLDOI $8, C1, C1, C1
ADD X14, X10, X10
ADD X15, X11, X11
VSLDOI $8, C2, C2, C2
VSLDOI $12, B0, B0, B0
XOR X8, X4, X4
XOR X9, X5, X5
VSLDOI $12, B1, B1, B1
VSLDOI $12, B2, B2, B2
XOR X10, X6, X6
XOR X11, X7, X7
VSLDOI $4, D0, D0, D0
VSLDOI $4, D1, D1, D1
ROTLW $7, X4, X4
ROTLW $7, X5, X5
VSLDOI $4, D2, D2, D2
VADDUWM A0, B0, A0
ROTLW $7, X6, X6
ROTLW $7, X7, X7
VADDUWM A1, B1, A1
VADDUWM A2, B2, A2
ADD X5, X0, X0
ADD X6, X1, X1
VXOR D0, A0, D0
VXOR D1, A1, D1
ADD X7, X2, X2
ADD X4, X3, X3
VXOR D2, A2, D2
VPERM D0, D0, SIXTEEN, D0
XOR X0, X15, X15
XOR X1, X12, X12
VPERM D1, D1, SIXTEEN, D1
VPERM D2, D2, SIXTEEN, D2
XOR X2, X13, X13
XOR X3, X14, X14
VADDUWM C0, D0, C0
VADDUWM C1, D1, C1
ROTLW $16, X15, X15
ROTLW $16, X12, X12
VADDUWM C2, D2, C2
VXOR B0, C0, T0
ROTLW $16, X13, X13
ROTLW $16, X14, X14
VXOR B1, C1, T1
VXOR B2, C2, T2
ADD X15, X10, X10
ADD X12, X11, X11
VRLW T0, TWELVE, B0
VRLW T1, TWELVE, B1
ADD X13, X8, X8
ADD X14, X9, X9
VRLW T2, TWELVE, B2
VADDUWM A0, B0, A0
XOR X10, X5, X5
XOR X11, X6, X6
VADDUWM A1, B1, A1
VADDUWM A2, B2, A2
XOR X8, X7, X7
XOR X9, X4, X4
VXOR D0, A0, D0
VXOR D1, A1, D1
ROTLW $12, X5, X5
ROTLW $12, X6, X6
VXOR D2, A2, D2
VPERM D0, D0, TWENTY4, D0
ROTLW $12, X7, X7
ROTLW $12, X4, X4
VPERM D1, D1, TWENTY4, D1
VPERM D2, D2, TWENTY4, D2
ADD X5, X0, X0
ADD X6, X1, X1
VADDUWM C0, D0, C0
VADDUWM C1, D1, C1
ADD X7, X2, X2
ADD X4, X3, X3
VADDUWM C2, D2, C2
VXOR B0, C0, T0
XOR X0, X15, X15
XOR X1, X12, X12
VXOR B1, C1, T1
VXOR B2, C2, T2
XOR X2, X13, X13
XOR X3, X14, X14
VRLW T0, SEVEN, B0
VRLW T1, SEVEN, B1
ROTLW $8, X15, X15
ROTLW $8, X12, X12
VRLW T2, SEVEN, B2
VSLDOI $8, C0, C0, C0
ROTLW $8, X13, X13
ROTLW $8, X14, X14
VSLDOI $8, C1, C1, C1
VSLDOI $8, C2, C2, C2
ADD X15, X10, X10
ADD X12, X11, X11
VSLDOI $4, B0, B0, B0
VSLDOI $4, B1, B1, B1
ADD X13, X8, X8
ADD X14, X9, X9
VSLDOI $4, B2, B2, B2
VSLDOI $12, D0, D0, D0
XOR X10, X5, X5
XOR X11, X6, X6
VSLDOI $12, D1, D1, D1
VSLDOI $12, D2, D2, D2
XOR X8, X7, X7
XOR X9, X4, X4
ROTLW $7, X5, X5
ROTLW $7, X6, X6
ROTLW $7, X7, X7
ROTLW $7, X4, X4
BC 0x10, 0, loop_vmx
SUB $256, LEN, LEN
// Accumulate key block
ADD $0x61707865, X0, X0
ADD $0x3320646e, X1, X1
ADD $0x79622d32, X2, X2
ADD $0x6b206574, X3, X3
ADD TMP0, X4, X4
ADD TMP1, X5, X5
ADD TMP2, X6, X6
ADD TMP3, X7, X7
MOVWZ 16(KEY), TMP0
MOVWZ 20(KEY), TMP1
MOVWZ 24(KEY), TMP2
MOVWZ 28(KEY), TMP3
ADD TMP0, X8, X8
ADD TMP1, X9, X9
ADD TMP2, X10, X10
ADD TMP3, X11, X11
MOVWZ 12(CNT), TMP0
MOVWZ 8(CNT), TMP1
MOVWZ 4(CNT), TMP2
MOVWZ 0(CNT), TEMP
ADD TMP0, X15, X15
ADD TMP1, X14, X14
ADD TMP2, X13, X13
ADD TEMP, X12, X12
// Accumulate key block
VADDUWM A0, K0, A0
VADDUWM A1, K0, A1
VADDUWM A2, K0, A2
VADDUWM B0, K1, B0
VADDUWM B1, K1, B1
VADDUWM B2, K1, B2
VADDUWM C0, K2, C0
VADDUWM C1, K2, C1
VADDUWM C2, K2, C2
VADDUWM D0, K3, D0
VADDUWM D1, K4, D1
VADDUWM D2, K5, D2
// Increment counter
ADD $4, TEMP, TEMP
MOVW TEMP, 0(CNT)
VADDUWM K3, FOUR, K3
VADDUWM K4, FOUR, K4
VADDUWM K5, FOUR, K5
// XOR the input slice (INP) with the keystream, which is stored in GPRs (X0-X3).
// Load input (aligned or not)
MOVWZ 0(INP), TMP0
MOVWZ 4(INP), TMP1
MOVWZ 8(INP), TMP2
MOVWZ 12(INP), TMP3
// XOR with input
XOR TMP0, X0, X0
XOR TMP1, X1, X1
XOR TMP2, X2, X2
XOR TMP3, X3, X3
MOVWZ 16(INP), TMP0
MOVWZ 20(INP), TMP1
MOVWZ 24(INP), TMP2
MOVWZ 28(INP), TMP3
XOR TMP0, X4, X4
XOR TMP1, X5, X5
XOR TMP2, X6, X6
XOR TMP3, X7, X7
MOVWZ 32(INP), TMP0
MOVWZ 36(INP), TMP1
MOVWZ 40(INP), TMP2
MOVWZ 44(INP), TMP3
XOR TMP0, X8, X8
XOR TMP1, X9, X9
XOR TMP2, X10, X10
XOR TMP3, X11, X11
MOVWZ 48(INP), TMP0
MOVWZ 52(INP), TMP1
MOVWZ 56(INP), TMP2
MOVWZ 60(INP), TMP3
XOR TMP0, X12, X12
XOR TMP1, X13, X13
XOR TMP2, X14, X14
XOR TMP3, X15, X15
// Store output (aligned or not)
MOVW X0, 0(OUT)
MOVW X1, 4(OUT)
MOVW X2, 8(OUT)
MOVW X3, 12(OUT)
ADD $64, INP, INP // INP points to the end of the slice for the alignment code below
MOVW X4, 16(OUT)
MOVD $16, TMP0
MOVW X5, 20(OUT)
MOVD $32, TMP1
MOVW X6, 24(OUT)
MOVD $48, TMP2
MOVW X7, 28(OUT)
MOVD $64, TMP3
MOVW X8, 32(OUT)
MOVW X9, 36(OUT)
MOVW X10, 40(OUT)
MOVW X11, 44(OUT)
MOVW X12, 48(OUT)
MOVW X13, 52(OUT)
MOVW X14, 56(OUT)
MOVW X15, 60(OUT)
ADD $64, OUT, OUT
// Load input
LVX (INP)(R0), DD0
LVX (INP)(TMP0), DD1
LVX (INP)(TMP1), DD2
LVX (INP)(TMP2), DD3
LVX (INP)(TMP3), DD4
ADD $64, INP, INP
VPERM DD1, DD0, INPPERM, DD0 // Align input
VPERM DD2, DD1, INPPERM, DD1
VPERM DD3, DD2, INPPERM, DD2
VPERM DD4, DD3, INPPERM, DD3
VXOR A0, DD0, A0 // XOR with input
VXOR B0, DD1, B0
LVX (INP)(TMP0), DD1 // Keep loading input
VXOR C0, DD2, C0
LVX (INP)(TMP1), DD2
VXOR D0, DD3, D0
LVX (INP)(TMP2), DD3
LVX (INP)(TMP3), DD0
ADD $64, INP, INP
MOVD $63, TMP3 // 63 is not a typo
VPERM A0, A0, OUTPERM, A0
VPERM B0, B0, OUTPERM, B0
VPERM C0, C0, OUTPERM, C0
VPERM D0, D0, OUTPERM, D0
VPERM DD1, DD4, INPPERM, DD4 // Align input
VPERM DD2, DD1, INPPERM, DD1
VPERM DD3, DD2, INPPERM, DD2
VPERM DD0, DD3, INPPERM, DD3
VXOR A1, DD4, A1
VXOR B1, DD1, B1
LVX (INP)(TMP0), DD1 // Keep loading
VXOR C1, DD2, C1
LVX (INP)(TMP1), DD2
VXOR D1, DD3, D1
LVX (INP)(TMP2), DD3
// Note that the LVX address is always rounded down to the nearest 16-byte
// boundary, and that it always points to at most 15 bytes beyond the end of
// the slice, so we cannot cross a page boundary.
LVX (INP)(TMP3), DD4 // Redundant in aligned case.
ADD $64, INP, INP
VPERM A1, A1, OUTPERM, A1 // Pre-misalign output
VPERM B1, B1, OUTPERM, B1
VPERM C1, C1, OUTPERM, C1
VPERM D1, D1, OUTPERM, D1
VPERM DD1, DD0, INPPERM, DD0 // Align Input
VPERM DD2, DD1, INPPERM, DD1
VPERM DD3, DD2, INPPERM, DD2
VPERM DD4, DD3, INPPERM, DD3
VXOR A2, DD0, A2
VXOR B2, DD1, B2
VXOR C2, DD2, C2
VXOR D2, DD3, D2
VPERM A2, A2, OUTPERM, A2
VPERM B2, B2, OUTPERM, B2
VPERM C2, C2, OUTPERM, C2
VPERM D2, D2, OUTPERM, D2
ANDCC $15, OUT, X1 // Is out aligned?
MOVD OUT, X0
VSEL A0, B0, OUTMASK, DD0 // Collect pre-misaligned output
VSEL B0, C0, OUTMASK, DD1
VSEL C0, D0, OUTMASK, DD2
VSEL D0, A1, OUTMASK, DD3
VSEL A1, B1, OUTMASK, B0
VSEL B1, C1, OUTMASK, C0
VSEL C1, D1, OUTMASK, D0
VSEL D1, A2, OUTMASK, A1
VSEL A2, B2, OUTMASK, B1
VSEL B2, C2, OUTMASK, C1
VSEL C2, D2, OUTMASK, D1
STVX DD0, (OUT+TMP0)
STVX DD1, (OUT+TMP1)
STVX DD2, (OUT+TMP2)
ADD $64, OUT, OUT
STVX DD3, (OUT+R0)
STVX B0, (OUT+TMP0)
STVX C0, (OUT+TMP1)
STVX D0, (OUT+TMP2)
ADD $64, OUT, OUT
STVX A1, (OUT+R0)
STVX B1, (OUT+TMP0)
STVX C1, (OUT+TMP1)
STVX D1, (OUT+TMP2)
ADD $64, OUT, OUT
BEQ aligned_vmx
SUB X1, OUT, X2 // in misaligned case edges
MOVD $0, X3 // are written byte-by-byte
unaligned_tail_vmx:
STVEBX D2, (X2+X3)
ADD $1, X3, X3
CMPW X3, X1
BNE unaligned_tail_vmx
SUB X1, X0, X2
unaligned_head_vmx:
STVEBX A0, (X2+X1)
CMPW X1, $15
ADD $1, X1, X1
BNE unaligned_head_vmx
CMPU LEN, $255 // done with 256-byte block yet?
BGT loop_outer_vmx
JMP done_vmx
aligned_vmx:
STVX A0, (X0+R0)
CMPU LEN, $255 // done with 256-byte block yet?
BGT loop_outer_vmx
done_vmx:
RET

View file

@ -1,31 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.11
// +build !gccgo
package chacha20
const (
haveAsm = true
bufSize = 256
)
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
if len(src) >= bufSize {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
}
if len(src)%bufSize != 0 {
i := len(src) - len(src)%bufSize
c.buf = [bufSize]byte{}
copy(c.buf[:], src[i:])
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter)
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize])
}
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !ppc64le,!arm64,!s390x arm64,!go1.11 gccgo appengine
// +build !s390x gccgo appengine
package chacha20

View file

@ -1,52 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ppc64le,!gccgo,!appengine
package chacha20
import "encoding/binary"
const (
bufSize = 256
haveAsm = true
)
//go:noescape
func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
if len(src) >= bufSize {
chaCha20_ctr32_vmx(&dst[0], &src[0], len(src)-len(src)%bufSize, &c.key, &c.counter)
}
if len(src)%bufSize != 0 {
chaCha20_ctr32_vmx(&c.buf[0], &c.buf[0], bufSize, &c.key, &c.counter)
start := len(src) - len(src)%bufSize
ts, td, tb := src[start:], dst[start:], c.buf[:]
// Unroll loop to XOR 32 bytes per iteration.
for i := 0; i < len(ts)-32; i += 32 {
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
s0 := binary.LittleEndian.Uint64(ts[0:8])
s1 := binary.LittleEndian.Uint64(ts[8:16])
s2 := binary.LittleEndian.Uint64(ts[16:24])
s3 := binary.LittleEndian.Uint64(ts[24:32])
b0 := binary.LittleEndian.Uint64(tb[0:8])
b1 := binary.LittleEndian.Uint64(tb[8:16])
b2 := binary.LittleEndian.Uint64(tb[16:24])
b3 := binary.LittleEndian.Uint64(tb[24:32])
binary.LittleEndian.PutUint64(td[0:8], s0^b0)
binary.LittleEndian.PutUint64(td[8:16], s1^b1)
binary.LittleEndian.PutUint64(td[16:24], s2^b2)
binary.LittleEndian.PutUint64(td[24:32], s3^b3)
ts, td, tb = ts[32:], td[32:], tb[32:]
}
td, tb = td[:len(ts)], tb[:len(ts)] // bounds check elimination
for i, v := range ts {
td[i] = tb[i] ^ v
}
c.len = bufSize - (len(src) % bufSize)
}
}

View file

@ -6,14 +6,15 @@
package chacha20
import (
"golang.org/x/sys/cpu"
)
var haveAsm = cpu.S390X.HasVX
var haveAsm = hasVectorFacility()
const bufSize = 256
// hasVectorFacility reports whether the machine supports the vector
// facility (vx).
// Implementation in asm_s390x.s.
func hasVectorFacility() bool
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
// be called when the vector facility is available.
// Implementation in asm_s390x.s.

View file

@ -258,3 +258,26 @@ tail:
MOVD R8, R3
MOVD $0, R4
JMP continue
// func hasVectorFacility() bool
TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
MOVD $x-24(SP), R1
XC $24, 0(R1), 0(R1) // clear the storage
MOVD $2, R0 // R0 is the number of double words stored -1
WORD $0xB2B01000 // STFLE 0(R1)
XOR R0, R0 // reset the value of R0
MOVBZ z-8(SP), R1
AND $0x40, R1
BEQ novector
vectorinstalled:
// check if the vector instruction has been enabled
VLEIB $0, $0xF, V16
VLGVB $0, V16, R1
CMPBNE R1, $0xF, novector
MOVB $1, ret+0(FP) // have vx
RET
novector:
MOVB $0, ret+0(FP) // no vx
RET

View file

@ -1,11 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !amd64,!ppc64le gccgo appengine
package poly1305
type mac struct{ macGeneric }
func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} }

View file

@ -2,19 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package poly1305 implements Poly1305 one-time message authentication code as
// specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
//
// Poly1305 is a fast, one-time authentication function. It is infeasible for an
// attacker to generate an authenticator for a message without the key. However, a
// key must only be used for a single message. Authenticating two different
// messages with the same key allows an attacker to forge authenticators for other
// messages with the same key.
//
// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
// used with a fixed key in order to generate one-time keys from an nonce.
// However, in this package AES isn't used and the one-time key is specified
// directly.
/*
Package poly1305 implements Poly1305 one-time message authentication code as
specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
Poly1305 is a fast, one-time authentication function. It is infeasible for an
attacker to generate an authenticator for a message without the key. However, a
key must only be used for a single message. Authenticating two different
messages with the same key allows an attacker to forge authenticators for other
messages with the same key.
Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
used with a fixed key in order to generate one-time keys from an nonce.
However, in this package AES isn't used and the one-time key is specified
directly.
*/
package poly1305 // import "golang.org/x/crypto/poly1305"
import "crypto/subtle"
@ -29,55 +31,3 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
Sum(&tmp, m, key)
return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
}
// New returns a new MAC computing an authentication
// tag of all data written to it with the given key.
// This allows writing the message progressively instead
// of passing it as a single slice. Common users should use
// the Sum function instead.
//
// The key must be unique for each message, as authenticating
// two different messages with the same key allows an attacker
// to forge messages at will.
func New(key *[32]byte) *MAC {
return &MAC{
mac: newMAC(key),
finalized: false,
}
}
// MAC is an io.Writer computing an authentication tag
// of the data written to it.
//
// MAC cannot be used like common hash.Hash implementations,
// because using a poly1305 key twice breaks its security.
// Therefore writing data to a running MAC after calling
// Sum causes it to panic.
type MAC struct {
mac // platform-dependent implementation
finalized bool
}
// Size returns the number of bytes Sum will return.
func (h *MAC) Size() int { return TagSize }
// Write adds more data to the running message authentication code.
// It never returns an error.
//
// It must not be called after the first call of Sum.
func (h *MAC) Write(p []byte) (n int, err error) {
if h.finalized {
panic("poly1305: write to MAC after Sum")
}
return h.mac.Write(p)
}
// Sum computes the authenticator of all data written to the
// message authentication code.
func (h *MAC) Sum(b []byte) []byte {
var mac [TagSize]byte
h.mac.Sum(&mac)
h.finalized = true
return append(b, mac[:]...)
}

View file

@ -6,63 +6,17 @@
package poly1305
// This function is implemented in sum_amd64.s
//go:noescape
func initialize(state *[7]uint64, key *[32]byte)
//go:noescape
func update(state *[7]uint64, msg []byte)
//go:noescape
func finalize(tag *[TagSize]byte, state *[7]uint64)
func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
// Sum generates an authenticator for m using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
h := newMAC(key)
h.Write(m)
h.Sum(out)
}
func newMAC(key *[32]byte) (h mac) {
initialize(&h.state, key)
return
}
type mac struct {
state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 }
buffer [TagSize]byte
offset int
}
func (h *mac) Write(p []byte) (n int, err error) {
n = len(p)
if h.offset > 0 {
remaining := TagSize - h.offset
if n < remaining {
h.offset += copy(h.buffer[h.offset:], p)
return n, nil
}
copy(h.buffer[h.offset:], p[:remaining])
p = p[remaining:]
h.offset = 0
update(&h.state, h.buffer[:])
var mPtr *byte
if len(m) > 0 {
mPtr = &m[0]
}
if nn := len(p) - (len(p) % TagSize); nn > 0 {
update(&h.state, p[:nn])
p = p[nn:]
}
if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p)
}
return n, nil
}
func (h *mac) Sum(out *[16]byte) {
state := h.state
if h.offset > 0 {
update(&state, h.buffer[:h.offset])
}
finalize(out, &state)
poly1305(out, mPtr, uint64(len(m)), key)
}

View file

@ -58,17 +58,20 @@ DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func update(state *[7]uint64, msg []byte)
TEXT ·update(SB), $0-32
MOVQ state+0(FP), DI
MOVQ msg_base+8(FP), SI
MOVQ msg_len+16(FP), R15
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
TEXT ·poly1305(SB), $0-32
MOVQ out+0(FP), DI
MOVQ m+8(FP), SI
MOVQ mlen+16(FP), R15
MOVQ key+24(FP), AX
MOVQ 0(DI), R8 // h0
MOVQ 8(DI), R9 // h1
MOVQ 16(DI), R10 // h2
MOVQ 24(DI), R11 // r0
MOVQ 32(DI), R12 // r1
MOVQ 0(AX), R11
MOVQ 8(AX), R12
ANDQ ·poly1305Mask<>(SB), R11 // r0
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
XORQ R8, R8 // h0
XORQ R9, R9 // h1
XORQ R10, R10 // h2
CMPQ R15, $16
JB bytes_between_0_and_15
@ -106,42 +109,16 @@ flush_buffer:
JMP multiply
done:
MOVQ R8, 0(DI)
MOVQ R9, 8(DI)
MOVQ R10, 16(DI)
RET
// func initialize(state *[7]uint64, key *[32]byte)
TEXT ·initialize(SB), $0-16
MOVQ state+0(FP), DI
MOVQ key+8(FP), SI
// state[0...7] is initialized with zero
MOVOU 0(SI), X0
MOVOU 16(SI), X1
MOVOU ·poly1305Mask<>(SB), X2
PAND X2, X0
MOVOU X0, 24(DI)
MOVOU X1, 40(DI)
RET
// func finalize(tag *[TagSize]byte, state *[7]uint64)
TEXT ·finalize(SB), $0-16
MOVQ tag+0(FP), DI
MOVQ state+8(FP), SI
MOVQ 0(SI), AX
MOVQ 8(SI), BX
MOVQ 16(SI), CX
MOVQ AX, R8
MOVQ BX, R9
MOVQ R8, AX
MOVQ R9, BX
SUBQ $0xFFFFFFFFFFFFFFFB, AX
SBBQ $0xFFFFFFFFFFFFFFFF, BX
SBBQ $3, CX
SBBQ $3, R10
CMOVQCS R8, AX
CMOVQCS R9, BX
ADDQ 40(SI), AX
ADCQ 48(SI), BX
MOVQ key+24(FP), R8
ADDQ 16(R8), AX
ADCQ 24(R8), BX
MOVQ AX, 0(DI)
MOVQ BX, 8(DI)

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build s390x,!go1.11 !arm,!amd64,!s390x,!ppc64le gccgo appengine nacl
// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
package poly1305
@ -10,7 +10,5 @@ package poly1305
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
h := newMAC(key)
h.Write(msg)
h.Sum(out)
sumGeneric(out, msg, key)
}

View file

@ -1,68 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ppc64le,!gccgo,!appengine
package poly1305
//go:noescape
func initialize(state *[7]uint64, key *[32]byte)
//go:noescape
func update(state *[7]uint64, msg []byte)
//go:noescape
func finalize(tag *[TagSize]byte, state *[7]uint64)
// Sum generates an authenticator for m using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
h := newMAC(key)
h.Write(m)
h.Sum(out)
}
func newMAC(key *[32]byte) (h mac) {
initialize(&h.state, key)
return
}
type mac struct {
state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 }
buffer [TagSize]byte
offset int
}
func (h *mac) Write(p []byte) (n int, err error) {
n = len(p)
if h.offset > 0 {
remaining := TagSize - h.offset
if n < remaining {
h.offset += copy(h.buffer[h.offset:], p)
return n, nil
}
copy(h.buffer[h.offset:], p[:remaining])
p = p[remaining:]
h.offset = 0
update(&h.state, h.buffer[:])
}
if nn := len(p) - (len(p) % TagSize); nn > 0 {
update(&h.state, p[:nn])
p = p[nn:]
}
if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p)
}
return n, nil
}
func (h *mac) Sum(out *[16]byte) {
state := h.state
if h.offset > 0 {
update(&state, h.buffer[:h.offset])
}
finalize(out, &state)
}

View file

@ -1,247 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ppc64le,!gccgo,!appengine
#include "textflag.h"
// This was ported from the amd64 implementation.
#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \
MOVD (msg), t0; \
MOVD 8(msg), t1; \
MOVD $1, t2; \
ADDC t0, h0, h0; \
ADDE t1, h1, h1; \
ADDE t2, h2; \
ADD $16, msg
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
MULLD r0, h0, t0; \
MULLD r0, h1, t4; \
MULHDU r0, h0, t1; \
MULHDU r0, h1, t5; \
ADDC t4, t1, t1; \
MULLD r0, h2, t2; \
ADDZE t5; \
MULHDU r1, h0, t4; \
MULLD r1, h0, h0; \
ADD t5, t2, t2; \
ADDC h0, t1, t1; \
MULLD h2, r1, t3; \
ADDZE t4, h0; \
MULHDU r1, h1, t5; \
MULLD r1, h1, t4; \
ADDC t4, t2, t2; \
ADDE t5, t3, t3; \
ADDC h0, t2, t2; \
MOVD $-4, t4; \
MOVD t0, h0; \
MOVD t1, h1; \
ADDZE t3; \
ANDCC $3, t2, h2; \
AND t2, t4, t0; \
ADDC t0, h0, h0; \
ADDE t3, h1, h1; \
SLD $62, t3, t4; \
SRD $2, t2; \
ADDZE h2; \
OR t4, t2, t2; \
SRD $2, t3; \
ADDC t2, h0, h0; \
ADDE t3, h1, h1; \
ADDZE h2
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func update(state *[7]uint64, msg []byte)
TEXT ·update(SB), $0-32
MOVD state+0(FP), R3
MOVD msg_base+8(FP), R4
MOVD msg_len+16(FP), R5
MOVD 0(R3), R8 // h0
MOVD 8(R3), R9 // h1
MOVD 16(R3), R10 // h2
MOVD 24(R3), R11 // r0
MOVD 32(R3), R12 // r1
CMP R5, $16
BLT bytes_between_0_and_15
loop:
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
multiply:
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
ADD $-16, R5
CMP R5, $16
BGE loop
bytes_between_0_and_15:
CMP $0, R5
BEQ done
MOVD $0, R16 // h0
MOVD $0, R17 // h1
flush_buffer:
CMP R5, $8
BLE just1
MOVD $8, R21
SUB R21, R5, R21
// Greater than 8 -- load the rightmost remaining bytes in msg
// and put into R17 (h1)
MOVD (R4)(R21), R17
MOVD $16, R22
// Find the offset to those bytes
SUB R5, R22, R22
SLD $3, R22
// Shift to get only the bytes in msg
SRD R22, R17, R17
// Put 1 at high end
MOVD $1, R23
SLD $3, R21
SLD R21, R23, R23
OR R23, R17, R17
// Remainder is 8
MOVD $8, R5
just1:
CMP R5, $8
BLT less8
// Exactly 8
MOVD (R4), R16
CMP $0, R17
// Check if we've already set R17; if not
// set 1 to indicate end of msg.
BNE carry
MOVD $1, R17
BR carry
less8:
MOVD $0, R16 // h0
MOVD $0, R22 // shift count
CMP R5, $4
BLT less4
MOVWZ (R4), R16
ADD $4, R4
ADD $-4, R5
MOVD $32, R22
less4:
CMP R5, $2
BLT less2
MOVHZ (R4), R21
SLD R22, R21, R21
OR R16, R21, R16
ADD $16, R22
ADD $-2, R5
ADD $2, R4
less2:
CMP $0, R5
BEQ insert1
MOVBZ (R4), R21
SLD R22, R21, R21
OR R16, R21, R16
ADD $8, R22
insert1:
// Insert 1 at end of msg
MOVD $1, R21
SLD R22, R21, R21
OR R16, R21, R16
carry:
// Add new values to h0, h1, h2
ADDC R16, R8
ADDE R17, R9
ADDE $0, R10
MOVD $16, R5
ADD R5, R4
BR multiply
done:
// Save h0, h1, h2 in state
MOVD R8, 0(R3)
MOVD R9, 8(R3)
MOVD R10, 16(R3)
RET
// func initialize(state *[7]uint64, key *[32]byte)
TEXT ·initialize(SB), $0-16
MOVD state+0(FP), R3
MOVD key+8(FP), R4
// state[0...7] is initialized with zero
// Load key
MOVD 0(R4), R5
MOVD 8(R4), R6
MOVD 16(R4), R7
MOVD 24(R4), R8
// Address of key mask
MOVD $·poly1305Mask<>(SB), R9
// Save original key in state
MOVD R7, 40(R3)
MOVD R8, 48(R3)
// Get mask
MOVD (R9), R7
MOVD 8(R9), R8
// And with key
AND R5, R7, R5
AND R6, R8, R6
// Save masked key in state
MOVD R5, 24(R3)
MOVD R6, 32(R3)
RET
// func finalize(tag *[TagSize]byte, state *[7]uint64)
TEXT ·finalize(SB), $0-16
MOVD tag+0(FP), R3
MOVD state+8(FP), R4
// Get h0, h1, h2 from state
MOVD 0(R4), R5
MOVD 8(R4), R6
MOVD 16(R4), R7
// Save h0, h1
MOVD R5, R8
MOVD R6, R9
MOVD $3, R20
MOVD $-1, R21
SUBC $-5, R5
SUBE R21, R6
SUBE R20, R7
MOVD $0, R21
SUBZE R21
// Check for carry
CMP $0, R21
ISEL $2, R5, R8, R5
ISEL $2, R6, R9, R6
MOVD 40(R4), R8
MOVD 48(R4), R9
ADDC R8, R5
ADDE R9, R6
MOVD R5, 0(R3)
MOVD R6, 8(R3)
RET

View file

@ -1,4 +1,4 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@ -6,79 +6,21 @@ package poly1305
import "encoding/binary"
const (
msgBlock = uint32(1 << 24)
finalBlock = uint32(0)
)
// sumGeneric generates an authenticator for msg using a one-time key and
// puts the 16-byte result into out. This is the generic implementation of
// Sum and should be called if no assembly implementation is available.
func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
h := newMACGeneric(key)
h.Write(msg)
h.Sum(out)
}
var (
h0, h1, h2, h3, h4 uint32 // the hash accumulators
r0, r1, r2, r3, r4 uint64 // the r part of the key
)
func newMACGeneric(key *[32]byte) (h macGeneric) {
h.r[0] = binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff
h.r[1] = (binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03
h.r[2] = (binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff
h.r[3] = (binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff
h.r[4] = (binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff
r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
h.s[0] = binary.LittleEndian.Uint32(key[16:])
h.s[1] = binary.LittleEndian.Uint32(key[20:])
h.s[2] = binary.LittleEndian.Uint32(key[24:])
h.s[3] = binary.LittleEndian.Uint32(key[28:])
return
}
type macGeneric struct {
h, r [5]uint32
s [4]uint32
buffer [TagSize]byte
offset int
}
func (h *macGeneric) Write(p []byte) (n int, err error) {
n = len(p)
if h.offset > 0 {
remaining := TagSize - h.offset
if n < remaining {
h.offset += copy(h.buffer[h.offset:], p)
return n, nil
}
copy(h.buffer[h.offset:], p[:remaining])
p = p[remaining:]
h.offset = 0
updateGeneric(h.buffer[:], msgBlock, &(h.h), &(h.r))
}
if nn := len(p) - (len(p) % TagSize); nn > 0 {
updateGeneric(p, msgBlock, &(h.h), &(h.r))
p = p[nn:]
}
if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p)
}
return n, nil
}
func (h *macGeneric) Sum(out *[16]byte) {
H, R := h.h, h.r
if h.offset > 0 {
var buffer [TagSize]byte
copy(buffer[:], h.buffer[:h.offset])
buffer[h.offset] = 1 // invariant: h.offset < TagSize
updateGeneric(buffer[:], finalBlock, &H, &R)
}
finalizeGeneric(out, &H, &(h.s))
}
func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) {
h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4]
r0, r1, r2, r3, r4 := uint64(r[0]), uint64(r[1]), uint64(r[2]), uint64(r[3]), uint64(r[4])
R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
for len(msg) >= TagSize {
@ -87,7 +29,7 @@ func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) {
h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | flag
h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
// h *= r
d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
@ -110,11 +52,36 @@ func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) {
msg = msg[TagSize:]
}
h[0], h[1], h[2], h[3], h[4] = h0, h1, h2, h3, h4
}
if len(msg) > 0 {
var block [TagSize]byte
off := copy(block[:], msg)
block[off] = 0x01
func finalizeGeneric(out *[TagSize]byte, h *[5]uint32, s *[4]uint32) {
h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4]
// h += msg
h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
// h *= r
d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
// h %= p
h0 = uint32(d0) & 0x3ffffff
h1 = uint32(d1) & 0x3ffffff
h2 = uint32(d2) & 0x3ffffff
h3 = uint32(d3) & 0x3ffffff
h4 = uint32(d4) & 0x3ffffff
h0 += uint32(d4>>26) * 5
h1 += h0 >> 26
h0 = h0 & 0x3ffffff
}
// h %= p reduction
h2 += h1 >> 26
@ -156,13 +123,13 @@ func finalizeGeneric(out *[TagSize]byte, h *[5]uint32, s *[4]uint32) {
// s: the s part of the key
// tag = (h + s) % (2^128)
t := uint64(h0) + uint64(s[0])
t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
h0 = uint32(t)
t = uint64(h1) + uint64(s[1]) + (t >> 32)
t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
h1 = uint32(t)
t = uint64(h2) + uint64(s[2]) + (t >> 32)
t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
h2 = uint32(t)
t = uint64(h3) + uint64(s[3]) + (t >> 32)
t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
h3 = uint32(t)
binary.LittleEndian.PutUint32(out[0:], h0)

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