refactor(proto): upgrade to gogo/protobuf/protoc-gen-gofast (#381)
* refactor(proto): upgrade to gogo/protobuf/protoc-gen-gofast * feat: update * feat: update
This commit is contained in:
		
							parent
							
								
									ffaae07b86
								
							
						
					
					
						commit
						facb8a9834
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -216,7 +216,7 @@ rpc/example/node/gorush_*_pb.js: rpc/proto/gorush.proto
 | 
			
		|||
	protoc -I rpc/proto rpc/proto/gorush.proto --js_out=import_style=commonjs,binary:rpc/example/node/ --grpc_out=rpc/example/node/ --plugin=protoc-gen-grpc=$(NODE_PROTOC_PLUGIN)
 | 
			
		||||
 | 
			
		||||
rpc/proto/gorush.pb.go: rpc/proto/gorush.proto
 | 
			
		||||
	protoc -I rpc/proto rpc/proto/gorush.proto --go_out=plugins=grpc:rpc/proto
 | 
			
		||||
	protoc -I rpc/proto -I ${PWD}/vendor/github.com/gogo/protobuf/proto rpc/proto/gorush.proto --gogofaster_out=plugins=grpc:rpc/proto
 | 
			
		||||
 | 
			
		||||
generate_proto: rpc/proto/gorush.pb.go rpc/example/node/gorush_*_pb.js
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Protocol Buffers for Go with Gadgets
 | 
			
		||||
 | 
			
		||||
Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
 | 
			
		||||
Copyright 2010 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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,6 @@ test: install generate-test-pbs
 | 
			
		|||
 | 
			
		||||
generate-test-pbs:
 | 
			
		||||
	make install
 | 
			
		||||
	make -C testdata
 | 
			
		||||
	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
 | 
			
		||||
	make -C test_proto
 | 
			
		||||
	make -C proto3_proto
 | 
			
		||||
	make
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,258 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 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.
 | 
			
		||||
 | 
			
		||||
// Protocol buffer deep copy and merge.
 | 
			
		||||
// TODO: RawMessage.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Clone returns a deep copy of a protocol buffer.
 | 
			
		||||
func Clone(src Message) Message {
 | 
			
		||||
	in := reflect.ValueOf(src)
 | 
			
		||||
	if in.IsNil() {
 | 
			
		||||
		return src
 | 
			
		||||
	}
 | 
			
		||||
	out := reflect.New(in.Type().Elem())
 | 
			
		||||
	dst := out.Interface().(Message)
 | 
			
		||||
	Merge(dst, src)
 | 
			
		||||
	return dst
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Merger is the interface representing objects that can merge messages of the same type.
 | 
			
		||||
type Merger interface {
 | 
			
		||||
	// Merge merges src into this message.
 | 
			
		||||
	// Required and optional fields that are set in src will be set to that value in dst.
 | 
			
		||||
	// Elements of repeated fields will be appended.
 | 
			
		||||
	//
 | 
			
		||||
	// Merge may panic if called with a different argument type than the receiver.
 | 
			
		||||
	Merge(src Message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// generatedMerger is the custom merge method that generated protos will have.
 | 
			
		||||
// We must add this method since a generate Merge method will conflict with
 | 
			
		||||
// many existing protos that have a Merge data field already defined.
 | 
			
		||||
type generatedMerger interface {
 | 
			
		||||
	XXX_Merge(src Message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Merge merges src into dst.
 | 
			
		||||
// Required and optional fields that are set in src will be set to that value in dst.
 | 
			
		||||
// Elements of repeated fields will be appended.
 | 
			
		||||
// Merge panics if src and dst are not the same type, or if dst is nil.
 | 
			
		||||
func Merge(dst, src Message) {
 | 
			
		||||
	if m, ok := dst.(Merger); ok {
 | 
			
		||||
		m.Merge(src)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	in := reflect.ValueOf(src)
 | 
			
		||||
	out := reflect.ValueOf(dst)
 | 
			
		||||
	if out.IsNil() {
 | 
			
		||||
		panic("proto: nil destination")
 | 
			
		||||
	}
 | 
			
		||||
	if in.Type() != out.Type() {
 | 
			
		||||
		panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
 | 
			
		||||
	}
 | 
			
		||||
	if in.IsNil() {
 | 
			
		||||
		return // Merge from nil src is a noop
 | 
			
		||||
	}
 | 
			
		||||
	if m, ok := dst.(generatedMerger); ok {
 | 
			
		||||
		m.XXX_Merge(src)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	mergeStruct(out.Elem(), in.Elem())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mergeStruct(out, in reflect.Value) {
 | 
			
		||||
	sprop := GetProperties(in.Type())
 | 
			
		||||
	for i := 0; i < in.NumField(); i++ {
 | 
			
		||||
		f := in.Type().Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
 | 
			
		||||
		emOut := out.Addr().Interface().(extensionsBytes)
 | 
			
		||||
		bIn := emIn.GetExtensions()
 | 
			
		||||
		bOut := emOut.GetExtensions()
 | 
			
		||||
		*bOut = append(*bOut, *bIn...)
 | 
			
		||||
	} else if emIn, err := extendable(in.Addr().Interface()); err == nil {
 | 
			
		||||
		emOut, _ := extendable(out.Addr().Interface())
 | 
			
		||||
		mIn, muIn := emIn.extensionsRead()
 | 
			
		||||
		if mIn != nil {
 | 
			
		||||
			mOut := emOut.extensionsWrite()
 | 
			
		||||
			muIn.Lock()
 | 
			
		||||
			mergeExtension(mOut, mIn)
 | 
			
		||||
			muIn.Unlock()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uf := in.FieldByName("XXX_unrecognized")
 | 
			
		||||
	if !uf.IsValid() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	uin := uf.Bytes()
 | 
			
		||||
	if len(uin) > 0 {
 | 
			
		||||
		out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mergeAny performs a merge between two values of the same type.
 | 
			
		||||
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
 | 
			
		||||
// prop is set if this is a struct field (it may be nil).
 | 
			
		||||
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
 | 
			
		||||
	if in.Type() == protoMessageType {
 | 
			
		||||
		if !in.IsNil() {
 | 
			
		||||
			if out.IsNil() {
 | 
			
		||||
				out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
 | 
			
		||||
			} else {
 | 
			
		||||
				Merge(out.Interface().(Message), in.Interface().(Message))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	switch in.Kind() {
 | 
			
		||||
	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
 | 
			
		||||
		reflect.String, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		if !viaPtr && isProto3Zero(in) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		out.Set(in)
 | 
			
		||||
	case reflect.Interface:
 | 
			
		||||
		// Probably a oneof field; copy non-nil values.
 | 
			
		||||
		if in.IsNil() {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// Allocate destination if it is not set, or set to a different type.
 | 
			
		||||
		// Otherwise we will merge as normal.
 | 
			
		||||
		if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
 | 
			
		||||
			out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
 | 
			
		||||
		}
 | 
			
		||||
		mergeAny(out.Elem(), in.Elem(), false, nil)
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
		if in.Len() == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if out.IsNil() {
 | 
			
		||||
			out.Set(reflect.MakeMap(in.Type()))
 | 
			
		||||
		}
 | 
			
		||||
		// For maps with value types of *T or []byte we need to deep copy each value.
 | 
			
		||||
		elemKind := in.Type().Elem().Kind()
 | 
			
		||||
		for _, key := range in.MapKeys() {
 | 
			
		||||
			var val reflect.Value
 | 
			
		||||
			switch elemKind {
 | 
			
		||||
			case reflect.Ptr:
 | 
			
		||||
				val = reflect.New(in.Type().Elem().Elem())
 | 
			
		||||
				mergeAny(val, in.MapIndex(key), false, nil)
 | 
			
		||||
			case reflect.Slice:
 | 
			
		||||
				val = in.MapIndex(key)
 | 
			
		||||
				val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
 | 
			
		||||
			default:
 | 
			
		||||
				val = in.MapIndex(key)
 | 
			
		||||
			}
 | 
			
		||||
			out.SetMapIndex(key, val)
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		if in.IsNil() {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if out.IsNil() {
 | 
			
		||||
			out.Set(reflect.New(in.Elem().Type()))
 | 
			
		||||
		}
 | 
			
		||||
		mergeAny(out.Elem(), in.Elem(), true, nil)
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		if in.IsNil() {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if in.Type().Elem().Kind() == reflect.Uint8 {
 | 
			
		||||
			// []byte is a scalar bytes field, not a repeated field.
 | 
			
		||||
 | 
			
		||||
			// Edge case: if this is in a proto3 message, a zero length
 | 
			
		||||
			// bytes field is considered the zero value, and should not
 | 
			
		||||
			// be merged.
 | 
			
		||||
			if prop != nil && prop.proto3 && in.Len() == 0 {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Make a deep copy.
 | 
			
		||||
			// Append to []byte{} instead of []byte(nil) so that we never end up
 | 
			
		||||
			// with a nil result.
 | 
			
		||||
			out.SetBytes(append([]byte{}, in.Bytes()...))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		n := in.Len()
 | 
			
		||||
		if out.IsNil() {
 | 
			
		||||
			out.Set(reflect.MakeSlice(in.Type(), 0, n))
 | 
			
		||||
		}
 | 
			
		||||
		switch in.Type().Elem().Kind() {
 | 
			
		||||
		case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
 | 
			
		||||
			reflect.String, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
			out.Set(reflect.AppendSlice(out, in))
 | 
			
		||||
		default:
 | 
			
		||||
			for i := 0; i < n; i++ {
 | 
			
		||||
				x := reflect.Indirect(reflect.New(in.Type().Elem()))
 | 
			
		||||
				mergeAny(x, in.Index(i), false, nil)
 | 
			
		||||
				out.Set(reflect.Append(out, x))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		mergeStruct(out, in)
 | 
			
		||||
	default:
 | 
			
		||||
		// unknown type, so not a protocol buffer
 | 
			
		||||
		log.Printf("proto: don't know how to copy %v", in)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func mergeExtension(out, in map[int32]Extension) {
 | 
			
		||||
	for extNum, eIn := range in {
 | 
			
		||||
		eOut := Extension{desc: eIn.desc}
 | 
			
		||||
		if eIn.value != nil {
 | 
			
		||||
			v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
 | 
			
		||||
			mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
 | 
			
		||||
			eOut.value = v.Interface()
 | 
			
		||||
		}
 | 
			
		||||
		if eIn.enc != nil {
 | 
			
		||||
			eOut.enc = make([]byte, len(eIn.enc))
 | 
			
		||||
			copy(eOut.enc, eIn.enc)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		out[extNum] = eOut
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
// 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
 | 
			
		||||
 | 
			
		||||
import "reflect"
 | 
			
		||||
 | 
			
		||||
type custom interface {
 | 
			
		||||
	Marshal() ([]byte, error)
 | 
			
		||||
	Unmarshal(data []byte) error
 | 
			
		||||
	Size() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var customType = reflect.TypeOf((*custom)(nil)).Elem()
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,428 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2010 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Routines for decoding protocol buffer data to construct in-memory representations.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// errOverflow is returned when an integer is too large to be represented.
 | 
			
		||||
var errOverflow = errors.New("proto: integer overflow")
 | 
			
		||||
 | 
			
		||||
// ErrInternalBadWireType is returned by generated code when an incorrect
 | 
			
		||||
// wire type is encountered. It does not get returned to user code.
 | 
			
		||||
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
 | 
			
		||||
 | 
			
		||||
// DecodeVarint reads a varint-encoded integer from the slice.
 | 
			
		||||
// It returns the integer and the number of bytes consumed, or
 | 
			
		||||
// zero if there is not enough.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// int32, int64, uint32, uint64, bool, and enum
 | 
			
		||||
// protocol buffer types.
 | 
			
		||||
func DecodeVarint(buf []byte) (x uint64, n int) {
 | 
			
		||||
	for shift := uint(0); shift < 64; shift += 7 {
 | 
			
		||||
		if n >= len(buf) {
 | 
			
		||||
			return 0, 0
 | 
			
		||||
		}
 | 
			
		||||
		b := uint64(buf[n])
 | 
			
		||||
		n++
 | 
			
		||||
		x |= (b & 0x7F) << shift
 | 
			
		||||
		if (b & 0x80) == 0 {
 | 
			
		||||
			return x, n
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The number is too large to represent in a 64-bit value.
 | 
			
		||||
	return 0, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
 | 
			
		||||
	i := p.index
 | 
			
		||||
	l := len(p.buf)
 | 
			
		||||
 | 
			
		||||
	for shift := uint(0); shift < 64; shift += 7 {
 | 
			
		||||
		if i >= l {
 | 
			
		||||
			err = io.ErrUnexpectedEOF
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		b := p.buf[i]
 | 
			
		||||
		i++
 | 
			
		||||
		x |= (uint64(b) & 0x7F) << shift
 | 
			
		||||
		if b < 0x80 {
 | 
			
		||||
			p.index = i
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The number is too large to represent in a 64-bit value.
 | 
			
		||||
	err = errOverflow
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeVarint reads a varint-encoded integer from the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// int32, int64, uint32, uint64, bool, and enum
 | 
			
		||||
// protocol buffer types.
 | 
			
		||||
func (p *Buffer) DecodeVarint() (x uint64, err error) {
 | 
			
		||||
	i := p.index
 | 
			
		||||
	buf := p.buf
 | 
			
		||||
 | 
			
		||||
	if i >= len(buf) {
 | 
			
		||||
		return 0, io.ErrUnexpectedEOF
 | 
			
		||||
	} else if buf[i] < 0x80 {
 | 
			
		||||
		p.index++
 | 
			
		||||
		return uint64(buf[i]), nil
 | 
			
		||||
	} else if len(buf)-i < 10 {
 | 
			
		||||
		return p.decodeVarintSlow()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var b uint64
 | 
			
		||||
	// we already checked the first byte
 | 
			
		||||
	x = uint64(buf[i]) - 0x80
 | 
			
		||||
	i++
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 7
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 7
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 14
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 14
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 21
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 21
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 28
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 28
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 35
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 35
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 42
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 42
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 49
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 49
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 56
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	x -= 0x80 << 56
 | 
			
		||||
 | 
			
		||||
	b = uint64(buf[i])
 | 
			
		||||
	i++
 | 
			
		||||
	x += b << 63
 | 
			
		||||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	// x -= 0x80 << 63 // Always zero.
 | 
			
		||||
 | 
			
		||||
	return 0, errOverflow
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
	p.index = i
 | 
			
		||||
	return x, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeFixed64 reads a 64-bit integer from the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// fixed64, sfixed64, and double protocol buffer types.
 | 
			
		||||
func (p *Buffer) DecodeFixed64() (x uint64, err error) {
 | 
			
		||||
	// x, err already 0
 | 
			
		||||
	i := p.index + 8
 | 
			
		||||
	if i < 0 || i > len(p.buf) {
 | 
			
		||||
		err = io.ErrUnexpectedEOF
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	p.index = i
 | 
			
		||||
 | 
			
		||||
	x = uint64(p.buf[i-8])
 | 
			
		||||
	x |= uint64(p.buf[i-7]) << 8
 | 
			
		||||
	x |= uint64(p.buf[i-6]) << 16
 | 
			
		||||
	x |= uint64(p.buf[i-5]) << 24
 | 
			
		||||
	x |= uint64(p.buf[i-4]) << 32
 | 
			
		||||
	x |= uint64(p.buf[i-3]) << 40
 | 
			
		||||
	x |= uint64(p.buf[i-2]) << 48
 | 
			
		||||
	x |= uint64(p.buf[i-1]) << 56
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeFixed32 reads a 32-bit integer from the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// fixed32, sfixed32, and float protocol buffer types.
 | 
			
		||||
func (p *Buffer) DecodeFixed32() (x uint64, err error) {
 | 
			
		||||
	// x, err already 0
 | 
			
		||||
	i := p.index + 4
 | 
			
		||||
	if i < 0 || i > len(p.buf) {
 | 
			
		||||
		err = io.ErrUnexpectedEOF
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	p.index = i
 | 
			
		||||
 | 
			
		||||
	x = uint64(p.buf[i-4])
 | 
			
		||||
	x |= uint64(p.buf[i-3]) << 8
 | 
			
		||||
	x |= uint64(p.buf[i-2]) << 16
 | 
			
		||||
	x |= uint64(p.buf[i-1]) << 24
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
 | 
			
		||||
// from the Buffer.
 | 
			
		||||
// This is the format used for the sint64 protocol buffer type.
 | 
			
		||||
func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
 | 
			
		||||
	x, err = p.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
 | 
			
		||||
// from  the Buffer.
 | 
			
		||||
// This is the format used for the sint32 protocol buffer type.
 | 
			
		||||
func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
 | 
			
		||||
	x, err = p.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
 | 
			
		||||
// This is the format used for the bytes protocol buffer
 | 
			
		||||
// type and for embedded messages.
 | 
			
		||||
func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
 | 
			
		||||
	n, err := p.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nb := int(n)
 | 
			
		||||
	if nb < 0 {
 | 
			
		||||
		return nil, fmt.Errorf("proto: bad byte length %d", nb)
 | 
			
		||||
	}
 | 
			
		||||
	end := p.index + nb
 | 
			
		||||
	if end < p.index || end > len(p.buf) {
 | 
			
		||||
		return nil, io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !alloc {
 | 
			
		||||
		// todo: check if can get more uses of alloc=false
 | 
			
		||||
		buf = p.buf[p.index:end]
 | 
			
		||||
		p.index += nb
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf = make([]byte, nb)
 | 
			
		||||
	copy(buf, p.buf[p.index:])
 | 
			
		||||
	p.index += nb
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeStringBytes reads an encoded string from the Buffer.
 | 
			
		||||
// This is the format used for the proto2 string type.
 | 
			
		||||
func (p *Buffer) DecodeStringBytes() (s string, err error) {
 | 
			
		||||
	buf, err := p.DecodeRawBytes(false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return string(buf), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshaler is the interface representing objects that can
 | 
			
		||||
// unmarshal themselves.  The argument points to data that may be
 | 
			
		||||
// overwritten, so implementations should not keep references to the
 | 
			
		||||
// buffer.
 | 
			
		||||
// Unmarshal implementations should not clear the receiver.
 | 
			
		||||
// Any unmarshaled data should be merged into the receiver.
 | 
			
		||||
// Callers of Unmarshal that do not want to retain existing data
 | 
			
		||||
// should Reset the receiver before calling Unmarshal.
 | 
			
		||||
type Unmarshaler interface {
 | 
			
		||||
	Unmarshal([]byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newUnmarshaler is the interface representing objects that can
 | 
			
		||||
// unmarshal themselves. The semantics are identical to Unmarshaler.
 | 
			
		||||
//
 | 
			
		||||
// This exists to support protoc-gen-go generated messages.
 | 
			
		||||
// The proto package will stop type-asserting to this interface in the future.
 | 
			
		||||
//
 | 
			
		||||
// DO NOT DEPEND ON THIS.
 | 
			
		||||
type newUnmarshaler interface {
 | 
			
		||||
	XXX_Unmarshal([]byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshal parses the protocol buffer representation in buf and places the
 | 
			
		||||
// decoded result in pb.  If the struct underlying pb does not match
 | 
			
		||||
// the data in buf, the results can be unpredictable.
 | 
			
		||||
//
 | 
			
		||||
// Unmarshal resets pb before starting to unmarshal, so any
 | 
			
		||||
// existing data in pb is always removed. Use UnmarshalMerge
 | 
			
		||||
// to preserve and append to existing data.
 | 
			
		||||
func Unmarshal(buf []byte, pb Message) error {
 | 
			
		||||
	pb.Reset()
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		return u.XXX_Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		return u.Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	return NewBuffer(buf).Unmarshal(pb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalMerge parses the protocol buffer representation in buf and
 | 
			
		||||
// writes the decoded result to pb.  If the struct underlying pb does not match
 | 
			
		||||
// the data in buf, the results can be unpredictable.
 | 
			
		||||
//
 | 
			
		||||
// UnmarshalMerge merges into existing data in pb.
 | 
			
		||||
// Most code should use Unmarshal instead.
 | 
			
		||||
func UnmarshalMerge(buf []byte, pb Message) error {
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		return u.XXX_Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		// NOTE: The history of proto have unfortunately been inconsistent
 | 
			
		||||
		// whether Unmarshaler should or should not implicitly clear itself.
 | 
			
		||||
		// Some implementations do, most do not.
 | 
			
		||||
		// Thus, calling this here may or may not do what people want.
 | 
			
		||||
		//
 | 
			
		||||
		// See https://github.com/golang/protobuf/issues/424
 | 
			
		||||
		return u.Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	return NewBuffer(buf).Unmarshal(pb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeMessage reads a count-delimited message from the Buffer.
 | 
			
		||||
func (p *Buffer) DecodeMessage(pb Message) error {
 | 
			
		||||
	enc, err := p.DecodeRawBytes(false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return NewBuffer(enc).Unmarshal(pb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeGroup reads a tag-delimited group from the Buffer.
 | 
			
		||||
// StartGroup tag is already consumed. This function consumes
 | 
			
		||||
// EndGroup tag.
 | 
			
		||||
func (p *Buffer) DecodeGroup(pb Message) error {
 | 
			
		||||
	b := p.buf[p.index:]
 | 
			
		||||
	x, y := findEndGroup(b)
 | 
			
		||||
	if x < 0 {
 | 
			
		||||
		return io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	err := Unmarshal(b[:x], pb)
 | 
			
		||||
	p.index += y
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshal parses the protocol buffer representation in the
 | 
			
		||||
// Buffer and places the decoded result in pb.  If the struct
 | 
			
		||||
// underlying pb does not match the data in the buffer, the results can be
 | 
			
		||||
// unpredictable.
 | 
			
		||||
//
 | 
			
		||||
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
 | 
			
		||||
func (p *Buffer) Unmarshal(pb Message) error {
 | 
			
		||||
	// If the object can unmarshal itself, let it.
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		err := u.XXX_Unmarshal(p.buf[p.index:])
 | 
			
		||||
		p.index = len(p.buf)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		// NOTE: The history of proto have unfortunately been inconsistent
 | 
			
		||||
		// whether Unmarshaler should or should not implicitly clear itself.
 | 
			
		||||
		// Some implementations do, most do not.
 | 
			
		||||
		// Thus, calling this here may or may not do what people want.
 | 
			
		||||
		//
 | 
			
		||||
		// See https://github.com/golang/protobuf/issues/424
 | 
			
		||||
		err := u.Unmarshal(p.buf[p.index:])
 | 
			
		||||
		p.index = len(p.buf)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Slow workaround for messages that aren't Unmarshalers.
 | 
			
		||||
	// This includes some hand-coded .pb.go files and
 | 
			
		||||
	// bootstrap protos.
 | 
			
		||||
	// TODO: fix all of those and then add Unmarshal to
 | 
			
		||||
	// the Message interface. Then:
 | 
			
		||||
	// The cast above and code below can be deleted.
 | 
			
		||||
	// The old unmarshaler can be deleted.
 | 
			
		||||
	// Clients can call Unmarshal directly (can already do that, actually).
 | 
			
		||||
	var info InternalMessageInfo
 | 
			
		||||
	err := info.Unmarshal(pb, p.buf[p.index:])
 | 
			
		||||
	p.index = len(p.buf)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,350 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2017 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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type generatedDiscarder interface {
 | 
			
		||||
	XXX_DiscardUnknown()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DiscardUnknown recursively discards all unknown fields from this message
 | 
			
		||||
// and all embedded messages.
 | 
			
		||||
//
 | 
			
		||||
// When unmarshaling a message with unrecognized fields, the tags and values
 | 
			
		||||
// of such fields are preserved in the Message. This allows a later call to
 | 
			
		||||
// marshal to be able to produce a message that continues to have those
 | 
			
		||||
// unrecognized fields. To avoid this, DiscardUnknown is used to
 | 
			
		||||
// explicitly clear the unknown fields after unmarshaling.
 | 
			
		||||
//
 | 
			
		||||
// For proto2 messages, the unknown fields of message extensions are only
 | 
			
		||||
// discarded from messages that have been accessed via GetExtension.
 | 
			
		||||
func DiscardUnknown(m Message) {
 | 
			
		||||
	if m, ok := m.(generatedDiscarder); ok {
 | 
			
		||||
		m.XXX_DiscardUnknown()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
 | 
			
		||||
	// but the master branch has no implementation for InternalMessageInfo,
 | 
			
		||||
	// so it would be more work to replicate that approach.
 | 
			
		||||
	discardLegacy(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DiscardUnknown recursively discards all unknown fields.
 | 
			
		||||
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
 | 
			
		||||
	di := atomicLoadDiscardInfo(&a.discard)
 | 
			
		||||
	if di == nil {
 | 
			
		||||
		di = getDiscardInfo(reflect.TypeOf(m).Elem())
 | 
			
		||||
		atomicStoreDiscardInfo(&a.discard, di)
 | 
			
		||||
	}
 | 
			
		||||
	di.discard(toPointer(&m))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type discardInfo struct {
 | 
			
		||||
	typ reflect.Type
 | 
			
		||||
 | 
			
		||||
	initialized int32 // 0: only typ is valid, 1: everything is valid
 | 
			
		||||
	lock        sync.Mutex
 | 
			
		||||
 | 
			
		||||
	fields       []discardFieldInfo
 | 
			
		||||
	unrecognized field
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type discardFieldInfo struct {
 | 
			
		||||
	field   field // Offset of field, guaranteed to be valid
 | 
			
		||||
	discard func(src pointer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	discardInfoMap  = map[reflect.Type]*discardInfo{}
 | 
			
		||||
	discardInfoLock sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getDiscardInfo(t reflect.Type) *discardInfo {
 | 
			
		||||
	discardInfoLock.Lock()
 | 
			
		||||
	defer discardInfoLock.Unlock()
 | 
			
		||||
	di := discardInfoMap[t]
 | 
			
		||||
	if di == nil {
 | 
			
		||||
		di = &discardInfo{typ: t}
 | 
			
		||||
		discardInfoMap[t] = di
 | 
			
		||||
	}
 | 
			
		||||
	return di
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (di *discardInfo) discard(src pointer) {
 | 
			
		||||
	if src.isNil() {
 | 
			
		||||
		return // Nothing to do.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if atomic.LoadInt32(&di.initialized) == 0 {
 | 
			
		||||
		di.computeDiscardInfo()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, fi := range di.fields {
 | 
			
		||||
		sfp := src.offset(fi.field)
 | 
			
		||||
		fi.discard(sfp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For proto2 messages, only discard unknown fields in message extensions
 | 
			
		||||
	// that have been accessed via GetExtension.
 | 
			
		||||
	if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
 | 
			
		||||
		// Ignore lock since DiscardUnknown is not concurrency safe.
 | 
			
		||||
		emm, _ := em.extensionsRead()
 | 
			
		||||
		for _, mx := range emm {
 | 
			
		||||
			if m, ok := mx.value.(Message); ok {
 | 
			
		||||
				DiscardUnknown(m)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if di.unrecognized.IsValid() {
 | 
			
		||||
		*src.offset(di.unrecognized).toBytes() = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (di *discardInfo) computeDiscardInfo() {
 | 
			
		||||
	di.lock.Lock()
 | 
			
		||||
	defer di.lock.Unlock()
 | 
			
		||||
	if di.initialized != 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := di.typ
 | 
			
		||||
	n := t.NumField()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dfi := discardFieldInfo{field: toField(&f)}
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				discardInfo := getDiscardInfo(tf)
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					sps := src.getPointerSlice()
 | 
			
		||||
					for _, sp := range sps {
 | 
			
		||||
						if !sp.isNil() {
 | 
			
		||||
							discardInfo.discard(sp)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				discardInfo := getDiscardInfo(tf)
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					sp := src.getPointer()
 | 
			
		||||
					if !sp.isNil() {
 | 
			
		||||
						discardInfo.discard(sp)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
 | 
			
		||||
					dfi.discard = func(src pointer) {
 | 
			
		||||
						sm := src.asPointerTo(tf).Elem()
 | 
			
		||||
						if sm.Len() == 0 {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							DiscardUnknown(val.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					dfi.discard = func(pointer) {} // Noop
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
 | 
			
		||||
			default: // E.g., interface{}
 | 
			
		||||
				// TODO: Make this faster?
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					su := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if !su.IsNil() {
 | 
			
		||||
						sv := su.Elem().Elem().Field(0)
 | 
			
		||||
						if sv.Kind() == reflect.Ptr && sv.IsNil() {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						switch sv.Type().Kind() {
 | 
			
		||||
						case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
							DiscardUnknown(sv.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		di.fields = append(di.fields, dfi)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	di.unrecognized = invalidField
 | 
			
		||||
	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
 | 
			
		||||
		if f.Type != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		di.unrecognized = toField(&f)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atomic.StoreInt32(&di.initialized, 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func discardLegacy(m Message) {
 | 
			
		||||
	v := reflect.ValueOf(m)
 | 
			
		||||
	if v.Kind() != reflect.Ptr || v.IsNil() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	v = v.Elem()
 | 
			
		||||
	if v.Kind() != reflect.Struct {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := v.Type()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < v.NumField(); i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		vf := v.Field(i)
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				for j := 0; j < vf.Len(); j++ {
 | 
			
		||||
					discardLegacy(vf.Index(j).Interface().(Message))
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				discardLegacy(vf.Interface().(Message))
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				tv := vf.Type().Elem()
 | 
			
		||||
				if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
 | 
			
		||||
					for _, key := range vf.MapKeys() {
 | 
			
		||||
						val := vf.MapIndex(key)
 | 
			
		||||
						discardLegacy(val.Interface().(Message))
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
 | 
			
		||||
			default: // E.g., test_proto.isCommunique_Union interface
 | 
			
		||||
				if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
 | 
			
		||||
					vf = vf.Elem() // E.g., *test_proto.Communique_Msg
 | 
			
		||||
					if !vf.IsNil() {
 | 
			
		||||
						vf = vf.Elem()   // E.g., test_proto.Communique_Msg
 | 
			
		||||
						vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
 | 
			
		||||
						if vf.Kind() == reflect.Ptr {
 | 
			
		||||
							discardLegacy(vf.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
 | 
			
		||||
		if vf.Type() != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		vf.Set(reflect.ValueOf([]byte(nil)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For proto2 messages, only discard unknown fields in message extensions
 | 
			
		||||
	// that have been accessed via GetExtension.
 | 
			
		||||
	if em, err := extendable(m); err == nil {
 | 
			
		||||
		// Ignore lock since discardLegacy is not concurrency safe.
 | 
			
		||||
		emm, _ := em.extensionsRead()
 | 
			
		||||
		for _, mx := range emm {
 | 
			
		||||
			if m, ok := mx.value.(Message); ok {
 | 
			
		||||
				discardLegacy(m)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,100 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2016 The Go Authors.  All rights reserved.
 | 
			
		||||
// https://github.com/golang/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
// contributors may be used to endorse or promote products derived from
 | 
			
		||||
// this software without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
// This file implements conversions between google.protobuf.Duration
 | 
			
		||||
// and time.Duration.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Range of a Duration in seconds, as specified in
 | 
			
		||||
	// google/protobuf/duration.proto. This is about 10,000 years in seconds.
 | 
			
		||||
	maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
 | 
			
		||||
	minSeconds = -maxSeconds
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// validateDuration determines whether the Duration is valid according to the
 | 
			
		||||
// definition in google/protobuf/duration.proto. A valid Duration
 | 
			
		||||
// may still be too large to fit into a time.Duration (the range of Duration
 | 
			
		||||
// is about 10,000 years, and the range of time.Duration is about 290).
 | 
			
		||||
func validateDuration(d *duration) error {
 | 
			
		||||
	if d == nil {
 | 
			
		||||
		return errors.New("duration: nil Duration")
 | 
			
		||||
	}
 | 
			
		||||
	if d.Seconds < minSeconds || d.Seconds > maxSeconds {
 | 
			
		||||
		return fmt.Errorf("duration: %#v: seconds out of range", d)
 | 
			
		||||
	}
 | 
			
		||||
	if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
 | 
			
		||||
		return fmt.Errorf("duration: %#v: nanos out of range", d)
 | 
			
		||||
	}
 | 
			
		||||
	// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
 | 
			
		||||
	if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
 | 
			
		||||
		return fmt.Errorf("duration: %#v: seconds and nanos have different signs", d)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DurationFromProto converts a Duration to a time.Duration. DurationFromProto
 | 
			
		||||
// returns an error if the Duration is invalid or is too large to be
 | 
			
		||||
// represented in a time.Duration.
 | 
			
		||||
func durationFromProto(p *duration) (time.Duration, error) {
 | 
			
		||||
	if err := validateDuration(p); err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	d := time.Duration(p.Seconds) * time.Second
 | 
			
		||||
	if int64(d/time.Second) != p.Seconds {
 | 
			
		||||
		return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
 | 
			
		||||
	}
 | 
			
		||||
	if p.Nanos != 0 {
 | 
			
		||||
		d += time.Duration(p.Nanos)
 | 
			
		||||
		if (d < 0) != (p.Nanos < 0) {
 | 
			
		||||
			return 0, fmt.Errorf("duration: %#v is out of range for time.Duration", p)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return d, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DurationProto converts a time.Duration to a Duration.
 | 
			
		||||
func durationProto(d time.Duration) *duration {
 | 
			
		||||
	nanos := d.Nanoseconds()
 | 
			
		||||
	secs := nanos / 1e9
 | 
			
		||||
	nanos -= secs * 1e9
 | 
			
		||||
	return &duration{
 | 
			
		||||
		Seconds: secs,
 | 
			
		||||
		Nanos:   int32(nanos),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2016, 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var durationType = reflect.TypeOf((*time.Duration)(nil)).Elem()
 | 
			
		||||
 | 
			
		||||
type duration struct {
 | 
			
		||||
	Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
 | 
			
		||||
	Nanos   int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *duration) Reset()       { *m = duration{} }
 | 
			
		||||
func (*duration) ProtoMessage()  {}
 | 
			
		||||
func (*duration) String() string { return "duration<string>" }
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterType((*duration)(nil), "gogo.protobuf.proto.duration")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,218 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2010 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Routines for encoding data into the wire format for protocol buffers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// errRepeatedHasNil is the error returned if Marshal is called with
 | 
			
		||||
	// a struct with a repeated field containing a nil element.
 | 
			
		||||
	errRepeatedHasNil = errors.New("proto: repeated field has nil element")
 | 
			
		||||
 | 
			
		||||
	// errOneofHasNil is the error returned if Marshal is called with
 | 
			
		||||
	// a struct with a oneof field containing a nil element.
 | 
			
		||||
	errOneofHasNil = errors.New("proto: oneof field has nil value")
 | 
			
		||||
 | 
			
		||||
	// ErrNil is the error returned if Marshal is called with nil.
 | 
			
		||||
	ErrNil = errors.New("proto: Marshal called with nil")
 | 
			
		||||
 | 
			
		||||
	// ErrTooLarge is the error returned if Marshal is called with a
 | 
			
		||||
	// message that encodes to >2GB.
 | 
			
		||||
	ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// The fundamental encoders that put bytes on the wire.
 | 
			
		||||
// Those that take integer types all accept uint64 and are
 | 
			
		||||
// therefore of type valueEncoder.
 | 
			
		||||
 | 
			
		||||
const maxVarintBytes = 10 // maximum length of a varint
 | 
			
		||||
 | 
			
		||||
// EncodeVarint returns the varint encoding of x.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// int32, int64, uint32, uint64, bool, and enum
 | 
			
		||||
// protocol buffer types.
 | 
			
		||||
// Not used by the package itself, but helpful to clients
 | 
			
		||||
// wishing to use the same encoding.
 | 
			
		||||
func EncodeVarint(x uint64) []byte {
 | 
			
		||||
	var buf [maxVarintBytes]byte
 | 
			
		||||
	var n int
 | 
			
		||||
	for n = 0; x > 127; n++ {
 | 
			
		||||
		buf[n] = 0x80 | uint8(x&0x7F)
 | 
			
		||||
		x >>= 7
 | 
			
		||||
	}
 | 
			
		||||
	buf[n] = uint8(x)
 | 
			
		||||
	n++
 | 
			
		||||
	return buf[0:n]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeVarint writes a varint-encoded integer to the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// int32, int64, uint32, uint64, bool, and enum
 | 
			
		||||
// protocol buffer types.
 | 
			
		||||
func (p *Buffer) EncodeVarint(x uint64) error {
 | 
			
		||||
	for x >= 1<<7 {
 | 
			
		||||
		p.buf = append(p.buf, uint8(x&0x7f|0x80))
 | 
			
		||||
		x >>= 7
 | 
			
		||||
	}
 | 
			
		||||
	p.buf = append(p.buf, uint8(x))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SizeVarint returns the varint encoding size of an integer.
 | 
			
		||||
func SizeVarint(x uint64) int {
 | 
			
		||||
	switch {
 | 
			
		||||
	case x < 1<<7:
 | 
			
		||||
		return 1
 | 
			
		||||
	case x < 1<<14:
 | 
			
		||||
		return 2
 | 
			
		||||
	case x < 1<<21:
 | 
			
		||||
		return 3
 | 
			
		||||
	case x < 1<<28:
 | 
			
		||||
		return 4
 | 
			
		||||
	case x < 1<<35:
 | 
			
		||||
		return 5
 | 
			
		||||
	case x < 1<<42:
 | 
			
		||||
		return 6
 | 
			
		||||
	case x < 1<<49:
 | 
			
		||||
		return 7
 | 
			
		||||
	case x < 1<<56:
 | 
			
		||||
		return 8
 | 
			
		||||
	case x < 1<<63:
 | 
			
		||||
		return 9
 | 
			
		||||
	}
 | 
			
		||||
	return 10
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeFixed64 writes a 64-bit integer to the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// fixed64, sfixed64, and double protocol buffer types.
 | 
			
		||||
func (p *Buffer) EncodeFixed64(x uint64) error {
 | 
			
		||||
	p.buf = append(p.buf,
 | 
			
		||||
		uint8(x),
 | 
			
		||||
		uint8(x>>8),
 | 
			
		||||
		uint8(x>>16),
 | 
			
		||||
		uint8(x>>24),
 | 
			
		||||
		uint8(x>>32),
 | 
			
		||||
		uint8(x>>40),
 | 
			
		||||
		uint8(x>>48),
 | 
			
		||||
		uint8(x>>56))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeFixed32 writes a 32-bit integer to the Buffer.
 | 
			
		||||
// This is the format for the
 | 
			
		||||
// fixed32, sfixed32, and float protocol buffer types.
 | 
			
		||||
func (p *Buffer) EncodeFixed32(x uint64) error {
 | 
			
		||||
	p.buf = append(p.buf,
 | 
			
		||||
		uint8(x),
 | 
			
		||||
		uint8(x>>8),
 | 
			
		||||
		uint8(x>>16),
 | 
			
		||||
		uint8(x>>24))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
 | 
			
		||||
// to the Buffer.
 | 
			
		||||
// This is the format used for the sint64 protocol buffer type.
 | 
			
		||||
func (p *Buffer) EncodeZigzag64(x uint64) error {
 | 
			
		||||
	// use signed number to get arithmetic right shift.
 | 
			
		||||
	return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
 | 
			
		||||
// to the Buffer.
 | 
			
		||||
// This is the format used for the sint32 protocol buffer type.
 | 
			
		||||
func (p *Buffer) EncodeZigzag32(x uint64) error {
 | 
			
		||||
	// use signed number to get arithmetic right shift.
 | 
			
		||||
	return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
 | 
			
		||||
// This is the format used for the bytes protocol buffer
 | 
			
		||||
// type and for embedded messages.
 | 
			
		||||
func (p *Buffer) EncodeRawBytes(b []byte) error {
 | 
			
		||||
	p.EncodeVarint(uint64(len(b)))
 | 
			
		||||
	p.buf = append(p.buf, b...)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeStringBytes writes an encoded string to the Buffer.
 | 
			
		||||
// This is the format used for the proto2 string type.
 | 
			
		||||
func (p *Buffer) EncodeStringBytes(s string) error {
 | 
			
		||||
	p.EncodeVarint(uint64(len(s)))
 | 
			
		||||
	p.buf = append(p.buf, s...)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshaler is the interface representing objects that can marshal themselves.
 | 
			
		||||
type Marshaler interface {
 | 
			
		||||
	Marshal() ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeMessage writes the protocol buffer to the Buffer,
 | 
			
		||||
// prefixed by a varint-encoded length.
 | 
			
		||||
func (p *Buffer) EncodeMessage(pb Message) error {
 | 
			
		||||
	siz := Size(pb)
 | 
			
		||||
	p.EncodeVarint(uint64(siz))
 | 
			
		||||
	return p.Marshal(pb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// All protocol buffer fields are nillable, but be careful.
 | 
			
		||||
func isNil(v reflect.Value) bool {
 | 
			
		||||
	switch v.Kind() {
 | 
			
		||||
	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
 | 
			
		||||
		return v.IsNil()
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
// http://github.com/gogo/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
func NewRequiredNotSetError(field string) *RequiredNotSetError {
 | 
			
		||||
	return &RequiredNotSetError{field}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,300 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2011 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.
 | 
			
		||||
 | 
			
		||||
// Protocol buffer comparison.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
Equal returns true iff protocol buffers a and b are equal.
 | 
			
		||||
The arguments must both be pointers to protocol buffer structs.
 | 
			
		||||
 | 
			
		||||
Equality is defined in this way:
 | 
			
		||||
  - Two messages are equal iff they are the same type,
 | 
			
		||||
    corresponding fields are equal, unknown field sets
 | 
			
		||||
    are equal, and extensions sets are equal.
 | 
			
		||||
  - Two set scalar fields are equal iff their values are equal.
 | 
			
		||||
    If the fields are of a floating-point type, remember that
 | 
			
		||||
    NaN != x for all x, including NaN. If the message is defined
 | 
			
		||||
    in a proto3 .proto file, fields are not "set"; specifically,
 | 
			
		||||
    zero length proto3 "bytes" fields are equal (nil == {}).
 | 
			
		||||
  - Two repeated fields are equal iff their lengths are the same,
 | 
			
		||||
    and their corresponding elements are equal. Note a "bytes" field,
 | 
			
		||||
    although represented by []byte, is not a repeated field and the
 | 
			
		||||
    rule for the scalar fields described above applies.
 | 
			
		||||
  - Two unset fields are equal.
 | 
			
		||||
  - Two unknown field sets are equal if their current
 | 
			
		||||
    encoded state is equal.
 | 
			
		||||
  - Two extension sets are equal iff they have corresponding
 | 
			
		||||
    elements that are pairwise equal.
 | 
			
		||||
  - Two map fields are equal iff their lengths are the same,
 | 
			
		||||
    and they contain the same set of elements. Zero-length map
 | 
			
		||||
    fields are equal.
 | 
			
		||||
  - Every other combination of things are not equal.
 | 
			
		||||
 | 
			
		||||
The return value is undefined if a and b are not protocol buffers.
 | 
			
		||||
*/
 | 
			
		||||
func Equal(a, b Message) bool {
 | 
			
		||||
	if a == nil || b == nil {
 | 
			
		||||
		return a == b
 | 
			
		||||
	}
 | 
			
		||||
	v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
 | 
			
		||||
	if v1.Type() != v2.Type() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if v1.Kind() == reflect.Ptr {
 | 
			
		||||
		if v1.IsNil() {
 | 
			
		||||
			return v2.IsNil()
 | 
			
		||||
		}
 | 
			
		||||
		if v2.IsNil() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		v1, v2 = v1.Elem(), v2.Elem()
 | 
			
		||||
	}
 | 
			
		||||
	if v1.Kind() != reflect.Struct {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return equalStruct(v1, v2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// v1 and v2 are known to have the same type.
 | 
			
		||||
func equalStruct(v1, v2 reflect.Value) bool {
 | 
			
		||||
	sprop := GetProperties(v1.Type())
 | 
			
		||||
	for i := 0; i < v1.NumField(); i++ {
 | 
			
		||||
		f := v1.Type().Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		f1, f2 := v1.Field(i), v2.Field(i)
 | 
			
		||||
		if f.Type.Kind() == reflect.Ptr {
 | 
			
		||||
			if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
 | 
			
		||||
				// both unset
 | 
			
		||||
				continue
 | 
			
		||||
			} else if n1 != n2 {
 | 
			
		||||
				// set/unset mismatch
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			f1, f2 = f1.Elem(), f2.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if !equalAny(f1, f2, sprop.Prop[i]) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
 | 
			
		||||
		em2 := v2.FieldByName("XXX_InternalExtensions")
 | 
			
		||||
		if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
 | 
			
		||||
		em2 := v2.FieldByName("XXX_extensions")
 | 
			
		||||
		if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uf := v1.FieldByName("XXX_unrecognized")
 | 
			
		||||
	if !uf.IsValid() {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u1 := uf.Bytes()
 | 
			
		||||
	u2 := v2.FieldByName("XXX_unrecognized").Bytes()
 | 
			
		||||
	return bytes.Equal(u1, u2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// v1 and v2 are known to have the same type.
 | 
			
		||||
// prop may be nil.
 | 
			
		||||
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
 | 
			
		||||
	if v1.Type() == protoMessageType {
 | 
			
		||||
		m1, _ := v1.Interface().(Message)
 | 
			
		||||
		m2, _ := v2.Interface().(Message)
 | 
			
		||||
		return Equal(m1, m2)
 | 
			
		||||
	}
 | 
			
		||||
	switch v1.Kind() {
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		return v1.Bool() == v2.Bool()
 | 
			
		||||
	case reflect.Float32, reflect.Float64:
 | 
			
		||||
		return v1.Float() == v2.Float()
 | 
			
		||||
	case reflect.Int32, reflect.Int64:
 | 
			
		||||
		return v1.Int() == v2.Int()
 | 
			
		||||
	case reflect.Interface:
 | 
			
		||||
		// Probably a oneof field; compare the inner values.
 | 
			
		||||
		n1, n2 := v1.IsNil(), v2.IsNil()
 | 
			
		||||
		if n1 || n2 {
 | 
			
		||||
			return n1 == n2
 | 
			
		||||
		}
 | 
			
		||||
		e1, e2 := v1.Elem(), v2.Elem()
 | 
			
		||||
		if e1.Type() != e2.Type() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return equalAny(e1, e2, nil)
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
		if v1.Len() != v2.Len() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		for _, key := range v1.MapKeys() {
 | 
			
		||||
			val2 := v2.MapIndex(key)
 | 
			
		||||
			if !val2.IsValid() {
 | 
			
		||||
				// This key was not found in the second map.
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			if !equalAny(v1.MapIndex(key), val2, nil) {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		// Maps may have nil values in them, so check for nil.
 | 
			
		||||
		if v1.IsNil() && v2.IsNil() {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		if v1.IsNil() != v2.IsNil() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return equalAny(v1.Elem(), v2.Elem(), prop)
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		if v1.Type().Elem().Kind() == reflect.Uint8 {
 | 
			
		||||
			// short circuit: []byte
 | 
			
		||||
 | 
			
		||||
			// Edge case: if this is in a proto3 message, a zero length
 | 
			
		||||
			// bytes field is considered the zero value.
 | 
			
		||||
			if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
			if v1.IsNil() != v2.IsNil() {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if v1.Len() != v2.Len() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		for i := 0; i < v1.Len(); i++ {
 | 
			
		||||
			if !equalAny(v1.Index(i), v2.Index(i), prop) {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		return v1.Interface().(string) == v2.Interface().(string)
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		return equalStruct(v1, v2)
 | 
			
		||||
	case reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		return v1.Uint() == v2.Uint()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// unknown type, so not a protocol buffer
 | 
			
		||||
	log.Printf("proto: don't know how to compare %v", v1)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// base is the struct type that the extensions are based on.
 | 
			
		||||
// x1 and x2 are InternalExtensions.
 | 
			
		||||
func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
 | 
			
		||||
	em1, _ := x1.extensionsRead()
 | 
			
		||||
	em2, _ := x2.extensionsRead()
 | 
			
		||||
	return equalExtMap(base, em1, em2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 | 
			
		||||
	if len(em1) != len(em2) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for extNum, e1 := range em1 {
 | 
			
		||||
		e2, ok := em2[extNum]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m1, m2 := e1.value, e2.value
 | 
			
		||||
 | 
			
		||||
		if m1 == nil && m2 == nil {
 | 
			
		||||
			// Both have only encoded form.
 | 
			
		||||
			if bytes.Equal(e1.enc, e2.enc) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			// The bytes are different, but the extensions might still be
 | 
			
		||||
			// equal. We need to decode them to compare.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if m1 != nil && m2 != nil {
 | 
			
		||||
			// Both are unencoded.
 | 
			
		||||
			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// At least one is encoded. To do a semantically correct comparison
 | 
			
		||||
		// we need to unmarshal them first.
 | 
			
		||||
		var desc *ExtensionDesc
 | 
			
		||||
		if m := extensionMaps[base]; m != nil {
 | 
			
		||||
			desc = m[extNum]
 | 
			
		||||
		}
 | 
			
		||||
		if desc == nil {
 | 
			
		||||
			// If both have only encoded form and the bytes are the same,
 | 
			
		||||
			// it is handled above. We get here when the bytes are different.
 | 
			
		||||
			// We don't know how to decode it, so just compare them as byte
 | 
			
		||||
			// slices.
 | 
			
		||||
			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		if m1 == nil {
 | 
			
		||||
			m1, err = decodeExtension(e1.enc, desc)
 | 
			
		||||
		}
 | 
			
		||||
		if m2 == nil && err == nil {
 | 
			
		||||
			m2, err = decodeExtension(e2.enc, desc)
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// The encoded form is invalid.
 | 
			
		||||
			log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,604 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2010 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Types and routines for supporting protocol buffer extensions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
 | 
			
		||||
var ErrMissingExtension = errors.New("proto: missing extension")
 | 
			
		||||
 | 
			
		||||
// ExtensionRange represents a range of message extensions for a protocol buffer.
 | 
			
		||||
// Used in code generated by the protocol compiler.
 | 
			
		||||
type ExtensionRange struct {
 | 
			
		||||
	Start, End int32 // both inclusive
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extendableProto is an interface implemented by any protocol buffer generated by the current
 | 
			
		||||
// proto compiler that may be extended.
 | 
			
		||||
type extendableProto interface {
 | 
			
		||||
	Message
 | 
			
		||||
	ExtensionRangeArray() []ExtensionRange
 | 
			
		||||
	extensionsWrite() map[int32]Extension
 | 
			
		||||
	extensionsRead() (map[int32]Extension, sync.Locker)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
 | 
			
		||||
// version of the proto compiler that may be extended.
 | 
			
		||||
type extendableProtoV1 interface {
 | 
			
		||||
	Message
 | 
			
		||||
	ExtensionRangeArray() []ExtensionRange
 | 
			
		||||
	ExtensionMap() map[int32]Extension
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
 | 
			
		||||
type extensionAdapter struct {
 | 
			
		||||
	extendableProtoV1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e extensionAdapter) extensionsWrite() map[int32]Extension {
 | 
			
		||||
	return e.ExtensionMap()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
 | 
			
		||||
	return e.ExtensionMap(), notLocker{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
 | 
			
		||||
type notLocker struct{}
 | 
			
		||||
 | 
			
		||||
func (n notLocker) Lock()   {}
 | 
			
		||||
func (n notLocker) Unlock() {}
 | 
			
		||||
 | 
			
		||||
// extendable returns the extendableProto interface for the given generated proto message.
 | 
			
		||||
// If the proto message has the old extension format, it returns a wrapper that implements
 | 
			
		||||
// the extendableProto interface.
 | 
			
		||||
func extendable(p interface{}) (extendableProto, error) {
 | 
			
		||||
	switch p := p.(type) {
 | 
			
		||||
	case extendableProto:
 | 
			
		||||
		if isNilPtr(p) {
 | 
			
		||||
			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
 | 
			
		||||
		}
 | 
			
		||||
		return p, nil
 | 
			
		||||
	case extendableProtoV1:
 | 
			
		||||
		if isNilPtr(p) {
 | 
			
		||||
			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
 | 
			
		||||
		}
 | 
			
		||||
		return extensionAdapter{p}, nil
 | 
			
		||||
	case extensionsBytes:
 | 
			
		||||
		return slowExtensionAdapter{p}, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Don't allocate a specific error containing %T:
 | 
			
		||||
	// this is the hot path for Clone and MarshalText.
 | 
			
		||||
	return nil, errNotExtendable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
 | 
			
		||||
 | 
			
		||||
func isNilPtr(x interface{}) bool {
 | 
			
		||||
	v := reflect.ValueOf(x)
 | 
			
		||||
	return v.Kind() == reflect.Ptr && v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// XXX_InternalExtensions is an internal representation of proto extensions.
 | 
			
		||||
//
 | 
			
		||||
// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
 | 
			
		||||
// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
 | 
			
		||||
//
 | 
			
		||||
// The methods of XXX_InternalExtensions are not concurrency safe in general,
 | 
			
		||||
// but calls to logically read-only methods such as has and get may be executed concurrently.
 | 
			
		||||
type XXX_InternalExtensions struct {
 | 
			
		||||
	// The struct must be indirect so that if a user inadvertently copies a
 | 
			
		||||
	// generated message and its embedded XXX_InternalExtensions, they
 | 
			
		||||
	// avoid the mayhem of a copied mutex.
 | 
			
		||||
	//
 | 
			
		||||
	// The mutex serializes all logically read-only operations to p.extensionMap.
 | 
			
		||||
	// It is up to the client to ensure that write operations to p.extensionMap are
 | 
			
		||||
	// mutually exclusive with other accesses.
 | 
			
		||||
	p *struct {
 | 
			
		||||
		mu           sync.Mutex
 | 
			
		||||
		extensionMap map[int32]Extension
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extensionsWrite returns the extension map, creating it on first use.
 | 
			
		||||
func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
 | 
			
		||||
	if e.p == nil {
 | 
			
		||||
		e.p = new(struct {
 | 
			
		||||
			mu           sync.Mutex
 | 
			
		||||
			extensionMap map[int32]Extension
 | 
			
		||||
		})
 | 
			
		||||
		e.p.extensionMap = make(map[int32]Extension)
 | 
			
		||||
	}
 | 
			
		||||
	return e.p.extensionMap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extensionsRead returns the extensions map for read-only use.  It may be nil.
 | 
			
		||||
// The caller must hold the returned mutex's lock when accessing Elements within the map.
 | 
			
		||||
func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
 | 
			
		||||
	if e.p == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	return e.p.extensionMap, &e.p.mu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtensionDesc represents an extension specification.
 | 
			
		||||
// Used in generated code from the protocol compiler.
 | 
			
		||||
type ExtensionDesc struct {
 | 
			
		||||
	ExtendedType  Message     // nil pointer to the type that is being extended
 | 
			
		||||
	ExtensionType interface{} // nil pointer to the extension type
 | 
			
		||||
	Field         int32       // field number
 | 
			
		||||
	Name          string      // fully-qualified name of extension, for text formatting
 | 
			
		||||
	Tag           string      // protobuf tag style
 | 
			
		||||
	Filename      string      // name of the file in which the extension is defined
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ed *ExtensionDesc) repeated() bool {
 | 
			
		||||
	t := reflect.TypeOf(ed.ExtensionType)
 | 
			
		||||
	return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extension represents an extension in a message.
 | 
			
		||||
type Extension struct {
 | 
			
		||||
	// When an extension is stored in a message using SetExtension
 | 
			
		||||
	// only desc and value are set. When the message is marshaled
 | 
			
		||||
	// enc will be set to the encoded form of the message.
 | 
			
		||||
	//
 | 
			
		||||
	// When a message is unmarshaled and contains extensions, each
 | 
			
		||||
	// 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 interface{}
 | 
			
		||||
	enc   []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetRawExtension is for testing only.
 | 
			
		||||
func SetRawExtension(base Message, id int32, b []byte) {
 | 
			
		||||
	if ebase, ok := base.(extensionsBytes); ok {
 | 
			
		||||
		clearExtension(base, id)
 | 
			
		||||
		ext := ebase.GetExtensions()
 | 
			
		||||
		*ext = append(*ext, b...)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	epb, err := extendable(base)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	extmap := epb.extensionsWrite()
 | 
			
		||||
	extmap[id] = Extension{enc: b}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isExtensionField returns true iff the given field number is in an extension range.
 | 
			
		||||
func isExtensionField(pb extendableProto, field int32) bool {
 | 
			
		||||
	for _, er := range pb.ExtensionRangeArray() {
 | 
			
		||||
		if er.Start <= field && field <= er.End {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// checkExtensionTypes checks that the given extension is valid for pb.
 | 
			
		||||
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
 | 
			
		||||
	var pbi interface{} = pb
 | 
			
		||||
	// Check the extended type.
 | 
			
		||||
	if ea, ok := pbi.(extensionAdapter); ok {
 | 
			
		||||
		pbi = ea.extendableProtoV1
 | 
			
		||||
	}
 | 
			
		||||
	if ea, ok := pbi.(slowExtensionAdapter); ok {
 | 
			
		||||
		pbi = ea.extensionsBytes
 | 
			
		||||
	}
 | 
			
		||||
	if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
 | 
			
		||||
		return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
 | 
			
		||||
	}
 | 
			
		||||
	// Check the range.
 | 
			
		||||
	if !isExtensionField(pb, extension.Field) {
 | 
			
		||||
		return errors.New("proto: bad extension number; not in declared ranges")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extPropKey is sufficient to uniquely identify an extension.
 | 
			
		||||
type extPropKey struct {
 | 
			
		||||
	base  reflect.Type
 | 
			
		||||
	field int32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var extProp = struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
	m map[extPropKey]*Properties
 | 
			
		||||
}{
 | 
			
		||||
	m: make(map[extPropKey]*Properties),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func extensionProperties(ed *ExtensionDesc) *Properties {
 | 
			
		||||
	key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
 | 
			
		||||
 | 
			
		||||
	extProp.RLock()
 | 
			
		||||
	if prop, ok := extProp.m[key]; ok {
 | 
			
		||||
		extProp.RUnlock()
 | 
			
		||||
		return prop
 | 
			
		||||
	}
 | 
			
		||||
	extProp.RUnlock()
 | 
			
		||||
 | 
			
		||||
	extProp.Lock()
 | 
			
		||||
	defer extProp.Unlock()
 | 
			
		||||
	// Check again.
 | 
			
		||||
	if prop, ok := extProp.m[key]; ok {
 | 
			
		||||
		return prop
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prop := new(Properties)
 | 
			
		||||
	prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
 | 
			
		||||
	extProp.m[key] = prop
 | 
			
		||||
	return prop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasExtension returns whether the given extension is present in pb.
 | 
			
		||||
func HasExtension(pb Message, extension *ExtensionDesc) bool {
 | 
			
		||||
	if epb, doki := pb.(extensionsBytes); doki {
 | 
			
		||||
		ext := epb.GetExtensions()
 | 
			
		||||
		buf := *ext
 | 
			
		||||
		o := 0
 | 
			
		||||
		for o < len(buf) {
 | 
			
		||||
			tag, n := DecodeVarint(buf[o:])
 | 
			
		||||
			fieldNum := int32(tag >> 3)
 | 
			
		||||
			if int32(fieldNum) == extension.Field {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
			wireType := int(tag & 0x7)
 | 
			
		||||
			o += n
 | 
			
		||||
			l, err := size(buf[o:], wireType)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			o += l
 | 
			
		||||
		}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Check types, field numbers, etc.?
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	extmap, mu := epb.extensionsRead()
 | 
			
		||||
	if extmap == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	_, ok := extmap[extension.Field]
 | 
			
		||||
	mu.Unlock()
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearExtension removes the given extension from pb.
 | 
			
		||||
func ClearExtension(pb Message, extension *ExtensionDesc) {
 | 
			
		||||
	clearExtension(pb, extension.Field)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clearExtension(pb Message, fieldNum int32) {
 | 
			
		||||
	if epb, ok := pb.(extensionsBytes); ok {
 | 
			
		||||
		offset := 0
 | 
			
		||||
		for offset != -1 {
 | 
			
		||||
			offset = deleteExtension(epb, fieldNum, offset)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Check types, field numbers, etc.?
 | 
			
		||||
	extmap := epb.extensionsWrite()
 | 
			
		||||
	delete(extmap, fieldNum)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExtension retrieves a proto2 extended field from pb.
 | 
			
		||||
//
 | 
			
		||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
 | 
			
		||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
 | 
			
		||||
// If the field is not present, then the default value is returned (if one is specified),
 | 
			
		||||
// otherwise ErrMissingExtension is reported.
 | 
			
		||||
//
 | 
			
		||||
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
 | 
			
		||||
// then GetExtension returns the raw encoded bytes of the field extension.
 | 
			
		||||
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	if epb, doki := pb.(extensionsBytes); doki {
 | 
			
		||||
		ext := epb.GetExtensions()
 | 
			
		||||
		return decodeExtensionFromBytes(extension, *ext)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if extension.ExtendedType != nil {
 | 
			
		||||
		// can only check type if this is a complete descriptor
 | 
			
		||||
		if cerr := checkExtensionTypes(epb, extension); cerr != nil {
 | 
			
		||||
			return nil, cerr
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	emap, mu := epb.extensionsRead()
 | 
			
		||||
	if emap == nil {
 | 
			
		||||
		return defaultExtensionValue(extension)
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	e, ok := emap[extension.Field]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// defaultExtensionValue returns the default value or
 | 
			
		||||
		// ErrMissingExtension if there is no default.
 | 
			
		||||
		return defaultExtensionValue(extension)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if e.value != nil {
 | 
			
		||||
		// Already decoded. Check the descriptor, though.
 | 
			
		||||
		if e.desc != extension {
 | 
			
		||||
			// This shouldn't happen. If it does, it means that
 | 
			
		||||
			// GetExtension was called twice with two different
 | 
			
		||||
			// descriptors with the same field number.
 | 
			
		||||
			return nil, errors.New("proto: descriptor conflict")
 | 
			
		||||
		}
 | 
			
		||||
		return e.value, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if extension.ExtensionType == nil {
 | 
			
		||||
		// incomplete descriptor
 | 
			
		||||
		return e.enc, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v, err := decodeExtension(e.enc, extension)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Remember the decoded version and drop the encoded version.
 | 
			
		||||
	// That way it is safe to mutate what we return.
 | 
			
		||||
	e.value = v
 | 
			
		||||
	e.desc = extension
 | 
			
		||||
	e.enc = nil
 | 
			
		||||
	emap[extension.Field] = e
 | 
			
		||||
	return e.value, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// defaultExtensionValue returns the default value for extension.
 | 
			
		||||
// If no default for an extension is defined ErrMissingExtension is returned.
 | 
			
		||||
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	if extension.ExtensionType == nil {
 | 
			
		||||
		// incomplete descriptor, so no default
 | 
			
		||||
		return nil, ErrMissingExtension
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
	props := extensionProperties(extension)
 | 
			
		||||
 | 
			
		||||
	sf, _, err := fieldDefault(t, props)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if sf == nil || sf.value == nil {
 | 
			
		||||
		// There is no default value.
 | 
			
		||||
		return nil, ErrMissingExtension
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t.Kind() != reflect.Ptr {
 | 
			
		||||
		// We do not need to return a Ptr, we can directly return sf.value.
 | 
			
		||||
		return sf.value, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We need to return an interface{} that is a pointer to sf.value.
 | 
			
		||||
	value := reflect.New(t).Elem()
 | 
			
		||||
	value.Set(reflect.New(value.Type().Elem()))
 | 
			
		||||
	if sf.kind == reflect.Int32 {
 | 
			
		||||
		// We may have an int32 or an enum, but the underlying data is int32.
 | 
			
		||||
		// Since we can't set an int32 into a non int32 reflect.value directly
 | 
			
		||||
		// set it as a int32.
 | 
			
		||||
		value.Elem().SetInt(int64(sf.value.(int32)))
 | 
			
		||||
	} else {
 | 
			
		||||
		value.Elem().Set(reflect.ValueOf(sf.value))
 | 
			
		||||
	}
 | 
			
		||||
	return value.Interface(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decodeExtension decodes an extension encoded in b.
 | 
			
		||||
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	t := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
	unmarshal := typeUnmarshaler(t, extension.Tag)
 | 
			
		||||
 | 
			
		||||
	// t is a pointer to a struct, pointer to basic type or a slice.
 | 
			
		||||
	// Allocate space to store the pointer/slice.
 | 
			
		||||
	value := reflect.New(t).Elem()
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		wire := int(x) & 7
 | 
			
		||||
 | 
			
		||||
		b, err = unmarshal(b, valToPointer(value.Addr()), wire)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(b) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return value.Interface(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
 | 
			
		||||
// The returned slice has the same length as es; missing extensions will appear as nil elements.
 | 
			
		||||
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	extensions = make([]interface{}, len(es))
 | 
			
		||||
	for i, e := range es {
 | 
			
		||||
		extensions[i], err = GetExtension(epb, e)
 | 
			
		||||
		if err == ErrMissingExtension {
 | 
			
		||||
			err = nil
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
 | 
			
		||||
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
 | 
			
		||||
// just the Field field, which defines the extension's field number.
 | 
			
		||||
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	registeredExtensions := RegisteredExtensions(pb)
 | 
			
		||||
 | 
			
		||||
	emap, mu := epb.extensionsRead()
 | 
			
		||||
	if emap == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	extensions := make([]*ExtensionDesc, 0, len(emap))
 | 
			
		||||
	for extid, e := range emap {
 | 
			
		||||
		desc := e.desc
 | 
			
		||||
		if desc == nil {
 | 
			
		||||
			desc = registeredExtensions[extid]
 | 
			
		||||
			if desc == nil {
 | 
			
		||||
				desc = &ExtensionDesc{Field: extid}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		extensions = append(extensions, desc)
 | 
			
		||||
	}
 | 
			
		||||
	return extensions, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		newb, err := encodeExtension(extension, value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		bb := epb.GetExtensions()
 | 
			
		||||
		*bb = append(*bb, newb...)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := checkExtensionTypes(epb, extension); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	typ := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
	if typ != reflect.TypeOf(value) {
 | 
			
		||||
		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
 | 
			
		||||
	// from an ErrNil due to a missing field. Extensions are
 | 
			
		||||
	// always optional, so the encoder would just swallow the error
 | 
			
		||||
	// and drop all the extensions from the encoded message.
 | 
			
		||||
	if reflect.ValueOf(value).IsNil() {
 | 
			
		||||
		return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	extmap := epb.extensionsWrite()
 | 
			
		||||
	extmap[extension.Field] = Extension{desc: extension, value: value}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearAllExtensions clears all extensions from pb.
 | 
			
		||||
func ClearAllExtensions(pb Message) {
 | 
			
		||||
	if epb, doki := pb.(extensionsBytes); doki {
 | 
			
		||||
		ext := epb.GetExtensions()
 | 
			
		||||
		*ext = []byte{}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	m := epb.extensionsWrite()
 | 
			
		||||
	for k := range m {
 | 
			
		||||
		delete(m, k)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A global registry of extensions.
 | 
			
		||||
// The generated code will register the generated descriptors by calling RegisterExtension.
 | 
			
		||||
 | 
			
		||||
var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
 | 
			
		||||
 | 
			
		||||
// RegisterExtension is called from the generated code.
 | 
			
		||||
func RegisterExtension(desc *ExtensionDesc) {
 | 
			
		||||
	st := reflect.TypeOf(desc.ExtendedType).Elem()
 | 
			
		||||
	m := extensionMaps[st]
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		m = make(map[int32]*ExtensionDesc)
 | 
			
		||||
		extensionMaps[st] = m
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := m[desc.Field]; ok {
 | 
			
		||||
		panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
 | 
			
		||||
	}
 | 
			
		||||
	m[desc.Field] = desc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisteredExtensions returns a map of the registered extensions of a
 | 
			
		||||
// protocol buffer struct, indexed by the extension number.
 | 
			
		||||
// The argument pb should be a nil pointer to the struct type.
 | 
			
		||||
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
 | 
			
		||||
	return extensionMaps[reflect.TypeOf(pb).Elem()]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,368 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
// http://github.com/gogo/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type extensionsBytes interface {
 | 
			
		||||
	Message
 | 
			
		||||
	ExtensionRangeArray() []ExtensionRange
 | 
			
		||||
	GetExtensions() *[]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type slowExtensionAdapter struct {
 | 
			
		||||
	extensionsBytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s slowExtensionAdapter) extensionsWrite() map[int32]Extension {
 | 
			
		||||
	panic("Please report a bug to github.com/gogo/protobuf if you see this message: Writing extensions is not supported for extensions stored in a byte slice field.")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s slowExtensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
 | 
			
		||||
	b := s.GetExtensions()
 | 
			
		||||
	m, err := BytesToExtensionsMap(*b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return m, notLocker{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetBoolExtension(pb Message, extension *ExtensionDesc, ifnotset bool) bool {
 | 
			
		||||
	if reflect.ValueOf(pb).IsNil() {
 | 
			
		||||
		return ifnotset
 | 
			
		||||
	}
 | 
			
		||||
	value, err := GetExtension(pb, extension)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ifnotset
 | 
			
		||||
	}
 | 
			
		||||
	if value == nil {
 | 
			
		||||
		return ifnotset
 | 
			
		||||
	}
 | 
			
		||||
	if value.(*bool) == nil {
 | 
			
		||||
		return ifnotset
 | 
			
		||||
	}
 | 
			
		||||
	return *(value.(*bool))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Extension) Equal(that *Extension) bool {
 | 
			
		||||
	if err := this.Encode(); err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if err := that.Encode(); err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return bytes.Equal(this.enc, that.enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Extension) Compare(that *Extension) int {
 | 
			
		||||
	if err := this.Encode(); err != nil {
 | 
			
		||||
		return 1
 | 
			
		||||
	}
 | 
			
		||||
	if err := that.Encode(); err != nil {
 | 
			
		||||
		return -1
 | 
			
		||||
	}
 | 
			
		||||
	return bytes.Compare(this.enc, that.enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SizeOfInternalExtension(m extendableProto) (n int) {
 | 
			
		||||
	info := getMarshalInfo(reflect.TypeOf(m))
 | 
			
		||||
	return info.sizeV1Extensions(m.extensionsWrite())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sortableMapElem struct {
 | 
			
		||||
	field int32
 | 
			
		||||
	ext   Extension
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newSortableExtensionsFromMap(m map[int32]Extension) sortableExtensions {
 | 
			
		||||
	s := make(sortableExtensions, 0, len(m))
 | 
			
		||||
	for k, v := range m {
 | 
			
		||||
		s = append(s, &sortableMapElem{field: k, ext: v})
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sortableExtensions []*sortableMapElem
 | 
			
		||||
 | 
			
		||||
func (this sortableExtensions) Len() int { return len(this) }
 | 
			
		||||
 | 
			
		||||
func (this sortableExtensions) Swap(i, j int) { this[i], this[j] = this[j], this[i] }
 | 
			
		||||
 | 
			
		||||
func (this sortableExtensions) Less(i, j int) bool { return this[i].field < this[j].field }
 | 
			
		||||
 | 
			
		||||
func (this sortableExtensions) String() string {
 | 
			
		||||
	sort.Sort(this)
 | 
			
		||||
	ss := make([]string, len(this))
 | 
			
		||||
	for i := range this {
 | 
			
		||||
		ss[i] = fmt.Sprintf("%d: %v", this[i].field, this[i].ext)
 | 
			
		||||
	}
 | 
			
		||||
	return "map[" + strings.Join(ss, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StringFromInternalExtension(m extendableProto) string {
 | 
			
		||||
	return StringFromExtensionsMap(m.extensionsWrite())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StringFromExtensionsMap(m map[int32]Extension) string {
 | 
			
		||||
	return newSortableExtensionsFromMap(m).String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StringFromExtensionsBytes(ext []byte) string {
 | 
			
		||||
	m, err := BytesToExtensionsMap(ext)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return StringFromExtensionsMap(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func EncodeInternalExtension(m extendableProto, data []byte) (n int, err error) {
 | 
			
		||||
	return EncodeExtensionMap(m.extensionsWrite(), data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
 | 
			
		||||
	o := 0
 | 
			
		||||
	for _, e := range m {
 | 
			
		||||
		if err := e.Encode(); err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		n := copy(data[o:], e.enc)
 | 
			
		||||
		if n != len(e.enc) {
 | 
			
		||||
			return 0, io.ErrShortBuffer
 | 
			
		||||
		}
 | 
			
		||||
		o += n
 | 
			
		||||
	}
 | 
			
		||||
	return o, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
 | 
			
		||||
	e := m[id]
 | 
			
		||||
	if err := e.Encode(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return e.enc, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func size(buf []byte, wire int) (int, error) {
 | 
			
		||||
	switch wire {
 | 
			
		||||
	case WireVarint:
 | 
			
		||||
		_, n := DecodeVarint(buf)
 | 
			
		||||
		return n, nil
 | 
			
		||||
	case WireFixed64:
 | 
			
		||||
		return 8, nil
 | 
			
		||||
	case WireBytes:
 | 
			
		||||
		v, n := DecodeVarint(buf)
 | 
			
		||||
		return int(v) + n, nil
 | 
			
		||||
	case WireFixed32:
 | 
			
		||||
		return 4, nil
 | 
			
		||||
	case WireStartGroup:
 | 
			
		||||
		offset := 0
 | 
			
		||||
		for {
 | 
			
		||||
			u, n := DecodeVarint(buf[offset:])
 | 
			
		||||
			fwire := int(u & 0x7)
 | 
			
		||||
			offset += n
 | 
			
		||||
			if fwire == WireEndGroup {
 | 
			
		||||
				return offset, nil
 | 
			
		||||
			}
 | 
			
		||||
			s, err := size(buf[offset:], wire)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0, err
 | 
			
		||||
			}
 | 
			
		||||
			offset += s
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("proto: can't get size for unknown wire type %d", wire)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BytesToExtensionsMap(buf []byte) (map[int32]Extension, error) {
 | 
			
		||||
	m := make(map[int32]Extension)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for i < len(buf) {
 | 
			
		||||
		tag, n := DecodeVarint(buf[i:])
 | 
			
		||||
		if n <= 0 {
 | 
			
		||||
			return nil, fmt.Errorf("unable to decode varint")
 | 
			
		||||
		}
 | 
			
		||||
		fieldNum := int32(tag >> 3)
 | 
			
		||||
		wireType := int(tag & 0x7)
 | 
			
		||||
		l, err := size(buf[i+n:], wireType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		end := i + int(l) + n
 | 
			
		||||
		m[int32(fieldNum)] = Extension{enc: buf[i:end]}
 | 
			
		||||
		i = end
 | 
			
		||||
	}
 | 
			
		||||
	return m, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewExtension(e []byte) Extension {
 | 
			
		||||
	ee := Extension{enc: make([]byte, len(e))}
 | 
			
		||||
	copy(ee.enc, e)
 | 
			
		||||
	return ee
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func AppendExtension(e Message, tag int32, buf []byte) {
 | 
			
		||||
	if ee, eok := e.(extensionsBytes); eok {
 | 
			
		||||
		ext := ee.GetExtensions()
 | 
			
		||||
		*ext = append(*ext, buf...)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if ee, eok := e.(extendableProto); eok {
 | 
			
		||||
		m := ee.extensionsWrite()
 | 
			
		||||
		ext := m[int32(tag)] // may be missing
 | 
			
		||||
		ext.enc = append(ext.enc, buf...)
 | 
			
		||||
		m[int32(tag)] = ext
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encodeExtension(extension *ExtensionDesc, value interface{}) ([]byte, error) {
 | 
			
		||||
	u := getMarshalInfo(reflect.TypeOf(extension.ExtendedType))
 | 
			
		||||
	ei := u.getExtElemInfo(extension)
 | 
			
		||||
	v := value
 | 
			
		||||
	p := toAddrPointer(&v, ei.isptr)
 | 
			
		||||
	siz := ei.sizer(p, SizeVarint(ei.wiretag))
 | 
			
		||||
	buf := make([]byte, 0, siz)
 | 
			
		||||
	return ei.marshaler(buf, p, ei.wiretag, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func decodeExtensionFromBytes(extension *ExtensionDesc, buf []byte) (interface{}, error) {
 | 
			
		||||
	o := 0
 | 
			
		||||
	for o < len(buf) {
 | 
			
		||||
		tag, n := DecodeVarint((buf)[o:])
 | 
			
		||||
		fieldNum := int32(tag >> 3)
 | 
			
		||||
		wireType := int(tag & 0x7)
 | 
			
		||||
		if o+n > len(buf) {
 | 
			
		||||
			return nil, fmt.Errorf("unable to decode extension")
 | 
			
		||||
		}
 | 
			
		||||
		l, err := size((buf)[o+n:], wireType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if int32(fieldNum) == extension.Field {
 | 
			
		||||
			if o+n+l > len(buf) {
 | 
			
		||||
				return nil, fmt.Errorf("unable to decode extension")
 | 
			
		||||
			}
 | 
			
		||||
			v, err := decodeExtension((buf)[o:o+n+l], extension)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			return v, nil
 | 
			
		||||
		}
 | 
			
		||||
		o += n + l
 | 
			
		||||
	}
 | 
			
		||||
	return defaultExtensionValue(extension)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Extension) Encode() error {
 | 
			
		||||
	if this.enc == nil {
 | 
			
		||||
		var err error
 | 
			
		||||
		this.enc, err = encodeExtension(this.desc, this.value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this Extension) GoString() string {
 | 
			
		||||
	if err := this.Encode(); err != nil {
 | 
			
		||||
		return fmt.Sprintf("error encoding extension: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("proto.NewExtension(%#v)", this.enc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetUnsafeExtension(pb Message, fieldNum int32, value interface{}) error {
 | 
			
		||||
	typ := reflect.TypeOf(pb).Elem()
 | 
			
		||||
	ext, ok := extensionMaps[typ]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String())
 | 
			
		||||
	}
 | 
			
		||||
	desc, ok := ext[fieldNum]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return errors.New("proto: bad extension number; not in declared ranges")
 | 
			
		||||
	}
 | 
			
		||||
	return SetExtension(pb, desc, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetUnsafeExtension(pb Message, fieldNum int32) (interface{}, error) {
 | 
			
		||||
	typ := reflect.TypeOf(pb).Elem()
 | 
			
		||||
	ext, ok := extensionMaps[typ]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("proto: bad extended type; %s is not extendable", typ.String())
 | 
			
		||||
	}
 | 
			
		||||
	desc, ok := ext[fieldNum]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("unregistered field number %d", fieldNum)
 | 
			
		||||
	}
 | 
			
		||||
	return GetExtension(pb, desc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewUnsafeXXX_InternalExtensions(m map[int32]Extension) XXX_InternalExtensions {
 | 
			
		||||
	x := &XXX_InternalExtensions{
 | 
			
		||||
		p: new(struct {
 | 
			
		||||
			mu           sync.Mutex
 | 
			
		||||
			extensionMap map[int32]Extension
 | 
			
		||||
		}),
 | 
			
		||||
	}
 | 
			
		||||
	x.p.extensionMap = m
 | 
			
		||||
	return *x
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetUnsafeExtensionsMap(extendable Message) map[int32]Extension {
 | 
			
		||||
	pb := extendable.(extendableProto)
 | 
			
		||||
	return pb.extensionsWrite()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
 | 
			
		||||
	ext := pb.GetExtensions()
 | 
			
		||||
	for offset < len(*ext) {
 | 
			
		||||
		tag, n1 := DecodeVarint((*ext)[offset:])
 | 
			
		||||
		fieldNum := int32(tag >> 3)
 | 
			
		||||
		wireType := int(tag & 0x7)
 | 
			
		||||
		n2, err := size((*ext)[offset+n1:], wireType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		newOffset := offset + n1 + n2
 | 
			
		||||
		if fieldNum == theFieldNum {
 | 
			
		||||
			*ext = append((*ext)[:offset], (*ext)[newOffset:]...)
 | 
			
		||||
			return offset
 | 
			
		||||
		}
 | 
			
		||||
		offset = newOffset
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,929 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2010 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 converts data structures to and from the wire format of
 | 
			
		||||
protocol buffers.  It works in concert with the Go source code generated
 | 
			
		||||
for .proto files by the protocol compiler.
 | 
			
		||||
 | 
			
		||||
A summary of the properties of the protocol buffer interface
 | 
			
		||||
for a protocol buffer variable v:
 | 
			
		||||
 | 
			
		||||
  - Names are turned from camel_case to CamelCase for export.
 | 
			
		||||
  - There are no methods on v to set fields; just treat
 | 
			
		||||
	them as structure fields.
 | 
			
		||||
  - There are getters that return a field's value if set,
 | 
			
		||||
	and return the field's default value if unset.
 | 
			
		||||
	The getters work even if the receiver is a nil message.
 | 
			
		||||
  - The zero value for a struct is its correct initialization state.
 | 
			
		||||
	All desired fields must be set before marshaling.
 | 
			
		||||
  - A Reset() method will restore a protobuf struct to its zero state.
 | 
			
		||||
  - Non-repeated fields are pointers to the values; nil means unset.
 | 
			
		||||
	That is, optional or required field int32 f becomes F *int32.
 | 
			
		||||
  - Repeated fields are slices.
 | 
			
		||||
  - Helper functions are available to aid the setting of fields.
 | 
			
		||||
	msg.Foo = proto.String("hello") // set field
 | 
			
		||||
  - Constants are defined to hold the default values of all fields that
 | 
			
		||||
	have them.  They have the form Default_StructName_FieldName.
 | 
			
		||||
	Because the getter methods handle defaulted values,
 | 
			
		||||
	direct use of these constants should be rare.
 | 
			
		||||
  - Enums are given type names and maps from names to values.
 | 
			
		||||
	Enum values are prefixed by the enclosing message's name, or by the
 | 
			
		||||
	enum's type name if it is a top-level enum. Enum types have a String
 | 
			
		||||
	method, and a Enum method to assist in message construction.
 | 
			
		||||
  - Nested messages, groups and enums have type names prefixed with the name of
 | 
			
		||||
	the surrounding message type.
 | 
			
		||||
  - Extensions are given descriptor names that start with E_,
 | 
			
		||||
	followed by an underscore-delimited list of the nested messages
 | 
			
		||||
	that contain it (if any) followed by the CamelCased name of the
 | 
			
		||||
	extension field itself.  HasExtension, ClearExtension, GetExtension
 | 
			
		||||
	and SetExtension are functions for manipulating extensions.
 | 
			
		||||
  - Oneof field sets are given a single field in their message,
 | 
			
		||||
	with distinguished wrapper types for each possible field value.
 | 
			
		||||
  - Marshal and Unmarshal are functions to encode and decode the wire format.
 | 
			
		||||
 | 
			
		||||
When the .proto file specifies `syntax="proto3"`, there are some differences:
 | 
			
		||||
 | 
			
		||||
  - Non-repeated fields of non-message type are values instead of pointers.
 | 
			
		||||
  - Enum types do not get an Enum method.
 | 
			
		||||
 | 
			
		||||
The simplest way to describe this is to see an example.
 | 
			
		||||
Given file test.proto, containing
 | 
			
		||||
 | 
			
		||||
	package example;
 | 
			
		||||
 | 
			
		||||
	enum FOO { X = 17; }
 | 
			
		||||
 | 
			
		||||
	message Test {
 | 
			
		||||
	  required string label = 1;
 | 
			
		||||
	  optional int32 type = 2 [default=77];
 | 
			
		||||
	  repeated int64 reps = 3;
 | 
			
		||||
	  optional group OptionalGroup = 4 {
 | 
			
		||||
	    required string RequiredField = 5;
 | 
			
		||||
	  }
 | 
			
		||||
	  oneof union {
 | 
			
		||||
	    int32 number = 6;
 | 
			
		||||
	    string name = 7;
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
The resulting file, test.pb.go, is:
 | 
			
		||||
 | 
			
		||||
	package example
 | 
			
		||||
 | 
			
		||||
	import proto "github.com/gogo/protobuf/proto"
 | 
			
		||||
	import math "math"
 | 
			
		||||
 | 
			
		||||
	type FOO int32
 | 
			
		||||
	const (
 | 
			
		||||
		FOO_X FOO = 17
 | 
			
		||||
	)
 | 
			
		||||
	var FOO_name = map[int32]string{
 | 
			
		||||
		17: "X",
 | 
			
		||||
	}
 | 
			
		||||
	var FOO_value = map[string]int32{
 | 
			
		||||
		"X": 17,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (x FOO) Enum() *FOO {
 | 
			
		||||
		p := new(FOO)
 | 
			
		||||
		*p = x
 | 
			
		||||
		return p
 | 
			
		||||
	}
 | 
			
		||||
	func (x FOO) String() string {
 | 
			
		||||
		return proto.EnumName(FOO_name, int32(x))
 | 
			
		||||
	}
 | 
			
		||||
	func (x *FOO) UnmarshalJSON(data []byte) error {
 | 
			
		||||
		value, err := proto.UnmarshalJSONEnum(FOO_value, data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		*x = FOO(value)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type Test struct {
 | 
			
		||||
		Label         *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
 | 
			
		||||
		Type          *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
 | 
			
		||||
		Reps          []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
 | 
			
		||||
		Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
 | 
			
		||||
		// Types that are valid to be assigned to Union:
 | 
			
		||||
		//	*Test_Number
 | 
			
		||||
		//	*Test_Name
 | 
			
		||||
		Union            isTest_Union `protobuf_oneof:"union"`
 | 
			
		||||
		XXX_unrecognized []byte       `json:"-"`
 | 
			
		||||
	}
 | 
			
		||||
	func (m *Test) Reset()         { *m = Test{} }
 | 
			
		||||
	func (m *Test) String() string { return proto.CompactTextString(m) }
 | 
			
		||||
	func (*Test) ProtoMessage() {}
 | 
			
		||||
 | 
			
		||||
	type isTest_Union interface {
 | 
			
		||||
		isTest_Union()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type Test_Number struct {
 | 
			
		||||
		Number int32 `protobuf:"varint,6,opt,name=number"`
 | 
			
		||||
	}
 | 
			
		||||
	type Test_Name struct {
 | 
			
		||||
		Name string `protobuf:"bytes,7,opt,name=name"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (*Test_Number) isTest_Union() {}
 | 
			
		||||
	func (*Test_Name) isTest_Union()   {}
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetUnion() isTest_Union {
 | 
			
		||||
		if m != nil {
 | 
			
		||||
			return m.Union
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	const Default_Test_Type int32 = 77
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetLabel() string {
 | 
			
		||||
		if m != nil && m.Label != nil {
 | 
			
		||||
			return *m.Label
 | 
			
		||||
		}
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetType() int32 {
 | 
			
		||||
		if m != nil && m.Type != nil {
 | 
			
		||||
			return *m.Type
 | 
			
		||||
		}
 | 
			
		||||
		return Default_Test_Type
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
 | 
			
		||||
		if m != nil {
 | 
			
		||||
			return m.Optionalgroup
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type Test_OptionalGroup struct {
 | 
			
		||||
		RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
	func (m *Test_OptionalGroup) Reset()         { *m = Test_OptionalGroup{} }
 | 
			
		||||
	func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
 | 
			
		||||
 | 
			
		||||
	func (m *Test_OptionalGroup) GetRequiredField() string {
 | 
			
		||||
		if m != nil && m.RequiredField != nil {
 | 
			
		||||
			return *m.RequiredField
 | 
			
		||||
		}
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetNumber() int32 {
 | 
			
		||||
		if x, ok := m.GetUnion().(*Test_Number); ok {
 | 
			
		||||
			return x.Number
 | 
			
		||||
		}
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func (m *Test) GetName() string {
 | 
			
		||||
		if x, ok := m.GetUnion().(*Test_Name); ok {
 | 
			
		||||
			return x.Name
 | 
			
		||||
		}
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	func init() {
 | 
			
		||||
		proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
To create and play with a Test object:
 | 
			
		||||
 | 
			
		||||
	package main
 | 
			
		||||
 | 
			
		||||
	import (
 | 
			
		||||
		"log"
 | 
			
		||||
 | 
			
		||||
		"github.com/gogo/protobuf/proto"
 | 
			
		||||
		pb "./example.pb"
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	func main() {
 | 
			
		||||
		test := &pb.Test{
 | 
			
		||||
			Label: proto.String("hello"),
 | 
			
		||||
			Type:  proto.Int32(17),
 | 
			
		||||
			Reps:  []int64{1, 2, 3},
 | 
			
		||||
			Optionalgroup: &pb.Test_OptionalGroup{
 | 
			
		||||
				RequiredField: proto.String("good bye"),
 | 
			
		||||
			},
 | 
			
		||||
			Union: &pb.Test_Name{"fred"},
 | 
			
		||||
		}
 | 
			
		||||
		data, err := proto.Marshal(test)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal("marshaling error: ", err)
 | 
			
		||||
		}
 | 
			
		||||
		newTest := &pb.Test{}
 | 
			
		||||
		err = proto.Unmarshal(data, newTest)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal("unmarshaling error: ", err)
 | 
			
		||||
		}
 | 
			
		||||
		// Now test and newTest contain the same data.
 | 
			
		||||
		if test.GetLabel() != newTest.GetLabel() {
 | 
			
		||||
			log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
 | 
			
		||||
		}
 | 
			
		||||
		// Use a type switch to determine which oneof was set.
 | 
			
		||||
		switch u := test.Union.(type) {
 | 
			
		||||
		case *pb.Test_Number: // u.Number contains the number.
 | 
			
		||||
		case *pb.Test_Name: // u.Name contains the string.
 | 
			
		||||
		}
 | 
			
		||||
		// etc.
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
 | 
			
		||||
 | 
			
		||||
// Message is implemented by generated protocol buffer messages.
 | 
			
		||||
type Message interface {
 | 
			
		||||
	Reset()
 | 
			
		||||
	String() string
 | 
			
		||||
	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;
 | 
			
		||||
// the global functions Marshal and Unmarshal create a
 | 
			
		||||
// temporary Buffer and are fine for most applications.
 | 
			
		||||
type Buffer struct {
 | 
			
		||||
	buf   []byte // encode/decode byte stream
 | 
			
		||||
	index int    // read point
 | 
			
		||||
 | 
			
		||||
	deterministic bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBuffer allocates a new Buffer and initializes its internal data to
 | 
			
		||||
// the contents of the argument slice.
 | 
			
		||||
func NewBuffer(e []byte) *Buffer {
 | 
			
		||||
	return &Buffer{buf: e}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
 | 
			
		||||
func (p *Buffer) Reset() {
 | 
			
		||||
	p.buf = p.buf[0:0] // for reading/writing
 | 
			
		||||
	p.index = 0        // for reading
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetBuf replaces the internal buffer with the slice,
 | 
			
		||||
// ready for unmarshaling the contents of the slice.
 | 
			
		||||
func (p *Buffer) SetBuf(s []byte) {
 | 
			
		||||
	p.buf = s
 | 
			
		||||
	p.index = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bytes returns the contents of the Buffer.
 | 
			
		||||
func (p *Buffer) Bytes() []byte { return p.buf }
 | 
			
		||||
 | 
			
		||||
// SetDeterministic sets whether to use deterministic serialization.
 | 
			
		||||
//
 | 
			
		||||
// Deterministic serialization guarantees that for a given binary, equal
 | 
			
		||||
// messages will always be serialized to the same bytes. This implies:
 | 
			
		||||
//
 | 
			
		||||
//   - Repeated serialization of a message will return the same bytes.
 | 
			
		||||
//   - Different processes of the same binary (which may be executing on
 | 
			
		||||
//     different machines) will serialize equal messages to the same bytes.
 | 
			
		||||
//
 | 
			
		||||
// Note that the deterministic serialization is NOT canonical across
 | 
			
		||||
// languages. It is not guaranteed to remain stable over time. It is unstable
 | 
			
		||||
// across different builds with schema changes due to unknown fields.
 | 
			
		||||
// Users who need canonical serialization (e.g., persistent storage in a
 | 
			
		||||
// canonical form, fingerprinting, etc.) should define their own
 | 
			
		||||
// canonicalization specification and implement their own serializer rather
 | 
			
		||||
// than relying on this API.
 | 
			
		||||
//
 | 
			
		||||
// If deterministic serialization is requested, map entries will be sorted
 | 
			
		||||
// by keys in lexographical order. This is an implementation detail and
 | 
			
		||||
// subject to change.
 | 
			
		||||
func (p *Buffer) SetDeterministic(deterministic bool) {
 | 
			
		||||
	p.deterministic = deterministic
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Helper routines for simplifying the creation of optional fields of basic type.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Bool is a helper routine that allocates a new bool value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Bool(v bool) *bool {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32 is a helper routine that allocates a new int32 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Int32(v int32) *int32 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int is a helper routine that allocates a new int32 value
 | 
			
		||||
// to store v and returns a pointer to it, but unlike Int32
 | 
			
		||||
// its argument value is an int.
 | 
			
		||||
func Int(v int) *int32 {
 | 
			
		||||
	p := new(int32)
 | 
			
		||||
	*p = int32(v)
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64 is a helper routine that allocates a new int64 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Int64(v int64) *int64 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32 is a helper routine that allocates a new float32 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Float32(v float32) *float32 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64 is a helper routine that allocates a new float64 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Float64(v float64) *float64 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uint32 is a helper routine that allocates a new uint32 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Uint32(v uint32) *uint32 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uint64 is a helper routine that allocates a new uint64 value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func Uint64(v uint64) *uint64 {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String is a helper routine that allocates a new string value
 | 
			
		||||
// to store v and returns a pointer to it.
 | 
			
		||||
func String(v string) *string {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnumName is a helper function to simplify printing protocol buffer enums
 | 
			
		||||
// by name.  Given an enum map and a value, it returns a useful string.
 | 
			
		||||
func EnumName(m map[int32]string, v int32) string {
 | 
			
		||||
	s, ok := m[v]
 | 
			
		||||
	if ok {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.Itoa(int(v))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
 | 
			
		||||
// from their JSON-encoded representation. Given a map from the enum's symbolic
 | 
			
		||||
// names to its int values, and a byte buffer containing the JSON-encoded
 | 
			
		||||
// value, it returns an int32 that can be cast to the enum type by the caller.
 | 
			
		||||
//
 | 
			
		||||
// The function can deal with both JSON representations, numeric and symbolic.
 | 
			
		||||
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
 | 
			
		||||
	if data[0] == '"' {
 | 
			
		||||
		// New style: enums are strings.
 | 
			
		||||
		var repr string
 | 
			
		||||
		if err := json.Unmarshal(data, &repr); err != nil {
 | 
			
		||||
			return -1, err
 | 
			
		||||
		}
 | 
			
		||||
		val, ok := m[repr]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
 | 
			
		||||
		}
 | 
			
		||||
		return val, nil
 | 
			
		||||
	}
 | 
			
		||||
	// Old style: enums are ints.
 | 
			
		||||
	var val int32
 | 
			
		||||
	if err := json.Unmarshal(data, &val); err != nil {
 | 
			
		||||
		return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
 | 
			
		||||
	}
 | 
			
		||||
	return val, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DebugPrint dumps the encoded data in b in a debugging format with a header
 | 
			
		||||
// including the string s. Used in testing but made available for general debugging.
 | 
			
		||||
func (p *Buffer) DebugPrint(s string, b []byte) {
 | 
			
		||||
	var u uint64
 | 
			
		||||
 | 
			
		||||
	obuf := p.buf
 | 
			
		||||
	sindex := p.index
 | 
			
		||||
	p.buf = b
 | 
			
		||||
	p.index = 0
 | 
			
		||||
	depth := 0
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("\n--- %s ---\n", s)
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	for {
 | 
			
		||||
		for i := 0; i < depth; i++ {
 | 
			
		||||
			fmt.Print("  ")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		index := p.index
 | 
			
		||||
		if index == len(p.buf) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		op, err := p.DecodeVarint()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Printf("%3d: fetching op err %v\n", index, err)
 | 
			
		||||
			break out
 | 
			
		||||
		}
 | 
			
		||||
		tag := op >> 3
 | 
			
		||||
		wire := op & 7
 | 
			
		||||
 | 
			
		||||
		switch wire {
 | 
			
		||||
		default:
 | 
			
		||||
			fmt.Printf("%3d: t=%3d unknown wire=%d\n",
 | 
			
		||||
				index, tag, wire)
 | 
			
		||||
			break out
 | 
			
		||||
 | 
			
		||||
		case WireBytes:
 | 
			
		||||
			var r []byte
 | 
			
		||||
 | 
			
		||||
			r, err = p.DecodeRawBytes(false)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				break out
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
 | 
			
		||||
			if len(r) <= 6 {
 | 
			
		||||
				for i := 0; i < len(r); i++ {
 | 
			
		||||
					fmt.Printf(" %.2x", r[i])
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				for i := 0; i < 3; i++ {
 | 
			
		||||
					fmt.Printf(" %.2x", r[i])
 | 
			
		||||
				}
 | 
			
		||||
				fmt.Printf(" ..")
 | 
			
		||||
				for i := len(r) - 3; i < len(r); i++ {
 | 
			
		||||
					fmt.Printf(" %.2x", r[i])
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("\n")
 | 
			
		||||
 | 
			
		||||
		case WireFixed32:
 | 
			
		||||
			u, err = p.DecodeFixed32()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
 | 
			
		||||
				break out
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
 | 
			
		||||
 | 
			
		||||
		case WireFixed64:
 | 
			
		||||
			u, err = p.DecodeFixed64()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
 | 
			
		||||
				break out
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
 | 
			
		||||
 | 
			
		||||
		case WireVarint:
 | 
			
		||||
			u, err = p.DecodeVarint()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
 | 
			
		||||
				break out
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
 | 
			
		||||
 | 
			
		||||
		case WireStartGroup:
 | 
			
		||||
			fmt.Printf("%3d: t=%3d start\n", index, tag)
 | 
			
		||||
			depth++
 | 
			
		||||
 | 
			
		||||
		case WireEndGroup:
 | 
			
		||||
			depth--
 | 
			
		||||
			fmt.Printf("%3d: t=%3d end\n", index, tag)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if depth != 0 {
 | 
			
		||||
		fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("\n")
 | 
			
		||||
 | 
			
		||||
	p.buf = obuf
 | 
			
		||||
	p.index = sindex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetDefaults sets unset protocol buffer fields to their default values.
 | 
			
		||||
// It only modifies fields that are both unset and have defined defaults.
 | 
			
		||||
// It recursively sets default values in any non-nil sub-messages.
 | 
			
		||||
func SetDefaults(pb Message) {
 | 
			
		||||
	setDefaults(reflect.ValueOf(pb), true, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// v is a struct.
 | 
			
		||||
func setDefaults(v reflect.Value, recur, zeros bool) {
 | 
			
		||||
	if v.Kind() == reflect.Ptr {
 | 
			
		||||
		v = v.Elem()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defaultMu.RLock()
 | 
			
		||||
	dm, ok := defaults[v.Type()]
 | 
			
		||||
	defaultMu.RUnlock()
 | 
			
		||||
	if !ok {
 | 
			
		||||
		dm = buildDefaultMessage(v.Type())
 | 
			
		||||
		defaultMu.Lock()
 | 
			
		||||
		defaults[v.Type()] = dm
 | 
			
		||||
		defaultMu.Unlock()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, sf := range dm.scalars {
 | 
			
		||||
		f := v.Field(sf.index)
 | 
			
		||||
		if !f.IsNil() {
 | 
			
		||||
			// field already set
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		dv := sf.value
 | 
			
		||||
		if dv == nil && !zeros {
 | 
			
		||||
			// no explicit default, and don't want to set zeros
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		fptr := f.Addr().Interface() // **T
 | 
			
		||||
		// TODO: Consider batching the allocations we do here.
 | 
			
		||||
		switch sf.kind {
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			b := new(bool)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*b = dv.(bool)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**bool)) = b
 | 
			
		||||
		case reflect.Float32:
 | 
			
		||||
			f := new(float32)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*f = dv.(float32)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**float32)) = f
 | 
			
		||||
		case reflect.Float64:
 | 
			
		||||
			f := new(float64)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*f = dv.(float64)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**float64)) = f
 | 
			
		||||
		case reflect.Int32:
 | 
			
		||||
			// might be an enum
 | 
			
		||||
			if ft := f.Type(); ft != int32PtrType {
 | 
			
		||||
				// enum
 | 
			
		||||
				f.Set(reflect.New(ft.Elem()))
 | 
			
		||||
				if dv != nil {
 | 
			
		||||
					f.Elem().SetInt(int64(dv.(int32)))
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				// int32 field
 | 
			
		||||
				i := new(int32)
 | 
			
		||||
				if dv != nil {
 | 
			
		||||
					*i = dv.(int32)
 | 
			
		||||
				}
 | 
			
		||||
				*(fptr.(**int32)) = i
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Int64:
 | 
			
		||||
			i := new(int64)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*i = dv.(int64)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**int64)) = i
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			s := new(string)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*s = dv.(string)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**string)) = s
 | 
			
		||||
		case reflect.Uint8:
 | 
			
		||||
			// exceptional case: []byte
 | 
			
		||||
			var b []byte
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				db := dv.([]byte)
 | 
			
		||||
				b = make([]byte, len(db))
 | 
			
		||||
				copy(b, db)
 | 
			
		||||
			} else {
 | 
			
		||||
				b = []byte{}
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(*[]byte)) = b
 | 
			
		||||
		case reflect.Uint32:
 | 
			
		||||
			u := new(uint32)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*u = dv.(uint32)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**uint32)) = u
 | 
			
		||||
		case reflect.Uint64:
 | 
			
		||||
			u := new(uint64)
 | 
			
		||||
			if dv != nil {
 | 
			
		||||
				*u = dv.(uint64)
 | 
			
		||||
			}
 | 
			
		||||
			*(fptr.(**uint64)) = u
 | 
			
		||||
		default:
 | 
			
		||||
			log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, ni := range dm.nested {
 | 
			
		||||
		f := v.Field(ni)
 | 
			
		||||
		// f is *T or T or []*T or []T
 | 
			
		||||
		switch f.Kind() {
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			setDefaults(f, recur, zeros)
 | 
			
		||||
 | 
			
		||||
		case reflect.Ptr:
 | 
			
		||||
			if f.IsNil() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			setDefaults(f, recur, zeros)
 | 
			
		||||
 | 
			
		||||
		case reflect.Slice:
 | 
			
		||||
			for i := 0; i < f.Len(); i++ {
 | 
			
		||||
				e := f.Index(i)
 | 
			
		||||
				if e.Kind() == reflect.Ptr && e.IsNil() {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				setDefaults(e, recur, zeros)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			for _, k := range f.MapKeys() {
 | 
			
		||||
				e := f.MapIndex(k)
 | 
			
		||||
				if e.IsNil() {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				setDefaults(e, recur, zeros)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// defaults maps a protocol buffer struct type to a slice of the fields,
 | 
			
		||||
	// with its scalar fields set to their proto-declared non-zero default values.
 | 
			
		||||
	defaultMu sync.RWMutex
 | 
			
		||||
	defaults  = make(map[reflect.Type]defaultMessage)
 | 
			
		||||
 | 
			
		||||
	int32PtrType = reflect.TypeOf((*int32)(nil))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// defaultMessage represents information about the default values of a message.
 | 
			
		||||
type defaultMessage struct {
 | 
			
		||||
	scalars []scalarField
 | 
			
		||||
	nested  []int // struct field index of nested messages
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type scalarField struct {
 | 
			
		||||
	index int          // struct field index
 | 
			
		||||
	kind  reflect.Kind // element type (the T in *T or []T)
 | 
			
		||||
	value interface{}  // the proto-declared default value, or nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// t is a struct type.
 | 
			
		||||
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 | 
			
		||||
	sprop := GetProperties(t)
 | 
			
		||||
	for _, prop := range sprop.Prop {
 | 
			
		||||
		fi, ok := sprop.decoderTags.get(prop.Tag)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			// XXX_unrecognized
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		ft := t.Field(fi).Type
 | 
			
		||||
 | 
			
		||||
		sf, nested, err := fieldDefault(ft, prop)
 | 
			
		||||
		switch {
 | 
			
		||||
		case err != nil:
 | 
			
		||||
			log.Print(err)
 | 
			
		||||
		case nested:
 | 
			
		||||
			dm.nested = append(dm.nested, fi)
 | 
			
		||||
		case sf != nil:
 | 
			
		||||
			sf.index = fi
 | 
			
		||||
			dm.scalars = append(dm.scalars, *sf)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return dm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fieldDefault returns the scalarField for field type ft.
 | 
			
		||||
// sf will be nil if the field can not have a default.
 | 
			
		||||
// nestedMessage will be true if this is a nested message.
 | 
			
		||||
// Note that sf.index is not set on return.
 | 
			
		||||
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
 | 
			
		||||
		} else {
 | 
			
		||||
			canHaveDefault = true // proto2 scalar field
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		switch ft.Elem().Kind() {
 | 
			
		||||
		case reflect.Ptr, reflect.Struct:
 | 
			
		||||
			nestedMessage = true // repeated message
 | 
			
		||||
		case reflect.Uint8:
 | 
			
		||||
			canHaveDefault = true // bytes field
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
		if ft.Elem().Kind() == reflect.Ptr {
 | 
			
		||||
			nestedMessage = true // map with message values
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !canHaveDefault {
 | 
			
		||||
		if nestedMessage {
 | 
			
		||||
			return nil, true, nil
 | 
			
		||||
		}
 | 
			
		||||
		return nil, false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We now know that ft is a pointer or slice.
 | 
			
		||||
	sf = &scalarField{kind: ft.Elem().Kind()}
 | 
			
		||||
 | 
			
		||||
	// scalar fields without defaults
 | 
			
		||||
	if !prop.HasDefault {
 | 
			
		||||
		return sf, false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// a scalar field: either *T or []byte
 | 
			
		||||
	switch ft.Elem().Kind() {
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		x, err := strconv.ParseBool(prop.Default)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = x
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		x, err := strconv.ParseFloat(prop.Default, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = float32(x)
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		x, err := strconv.ParseFloat(prop.Default, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = x
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		x, err := strconv.ParseInt(prop.Default, 10, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = int32(x)
 | 
			
		||||
	case reflect.Int64:
 | 
			
		||||
		x, err := strconv.ParseInt(prop.Default, 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = x
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		sf.value = prop.Default
 | 
			
		||||
	case reflect.Uint8:
 | 
			
		||||
		// []byte (not *uint8)
 | 
			
		||||
		sf.value = []byte(prop.Default)
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		x, err := strconv.ParseUint(prop.Default, 10, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = uint32(x)
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
		x, err := strconv.ParseUint(prop.Default, 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
 | 
			
		||||
		}
 | 
			
		||||
		sf.value = x
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sf, false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mapKeys returns a sort.Interface to be used for sorting the map keys.
 | 
			
		||||
// Map fields may have key types of non-float scalars, strings and enums.
 | 
			
		||||
func mapKeys(vs []reflect.Value) sort.Interface {
 | 
			
		||||
	s := mapKeySorter{vs: vs}
 | 
			
		||||
 | 
			
		||||
	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
 | 
			
		||||
	if len(vs) == 0 {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	switch vs[0].Kind() {
 | 
			
		||||
	case reflect.Int32, reflect.Int64:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
 | 
			
		||||
	case reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mapKeySorter struct {
 | 
			
		||||
	vs   []reflect.Value
 | 
			
		||||
	less func(a, b reflect.Value) bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s mapKeySorter) Len() int      { return len(s.vs) }
 | 
			
		||||
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
 | 
			
		||||
func (s mapKeySorter) Less(i, j int) bool {
 | 
			
		||||
	return s.less(s.vs[i], s.vs[j])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isProto3Zero reports whether v is a zero proto3 value.
 | 
			
		||||
func isProto3Zero(v reflect.Value) bool {
 | 
			
		||||
	switch v.Kind() {
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		return !v.Bool()
 | 
			
		||||
	case reflect.Int32, reflect.Int64:
 | 
			
		||||
		return v.Int() == 0
 | 
			
		||||
	case reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		return v.Uint() == 0
 | 
			
		||||
	case reflect.Float32, reflect.Float64:
 | 
			
		||||
		return v.Float() == 0
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		return v.String() == ""
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// This type is not subject to any compatibility guarantee.
 | 
			
		||||
type InternalMessageInfo struct {
 | 
			
		||||
	marshal   *marshalInfo
 | 
			
		||||
	unmarshal *unmarshalInfo
 | 
			
		||||
	merge     *mergeInfo
 | 
			
		||||
	discard   *discardInfo
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
// http://github.com/gogo/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Sizer interface {
 | 
			
		||||
	Size() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ProtoSizer interface {
 | 
			
		||||
	ProtoSize() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MarshalJSONEnum(m map[int32]string, value int32) ([]byte, error) {
 | 
			
		||||
	s, ok := m[value]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		s = strconv.Itoa(int(value))
 | 
			
		||||
	}
 | 
			
		||||
	return json.Marshal(s)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,314 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2010 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Support for message sets.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 | 
			
		||||
// A message type ID is required for storing a protocol buffer in a message set.
 | 
			
		||||
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
 | 
			
		||||
 | 
			
		||||
// The first two types (_MessageSet_Item and messageSet)
 | 
			
		||||
// model what the protocol compiler produces for the following protocol message:
 | 
			
		||||
//   message MessageSet {
 | 
			
		||||
//     repeated group Item = 1 {
 | 
			
		||||
//       required int32 type_id = 2;
 | 
			
		||||
//       required string message = 3;
 | 
			
		||||
//     };
 | 
			
		||||
//   }
 | 
			
		||||
// That is the MessageSet wire format. We can't use a proto to generate these
 | 
			
		||||
// because that would introduce a circular dependency between it and this package.
 | 
			
		||||
 | 
			
		||||
type _MessageSet_Item struct {
 | 
			
		||||
	TypeId  *int32 `protobuf:"varint,2,req,name=type_id"`
 | 
			
		||||
	Message []byte `protobuf:"bytes,3,req,name=message"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type messageSet struct {
 | 
			
		||||
	Item             []*_MessageSet_Item `protobuf:"group,1,rep"`
 | 
			
		||||
	XXX_unrecognized []byte
 | 
			
		||||
	// TODO: caching?
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Make sure messageSet is a Message.
 | 
			
		||||
var _ Message = (*messageSet)(nil)
 | 
			
		||||
 | 
			
		||||
// messageTypeIder is an interface satisfied by a protocol buffer type
 | 
			
		||||
// that may be stored in a MessageSet.
 | 
			
		||||
type messageTypeIder interface {
 | 
			
		||||
	MessageTypeId() int32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 | 
			
		||||
	mti, ok := pb.(messageTypeIder)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	id := mti.MessageTypeId()
 | 
			
		||||
	for _, item := range ms.Item {
 | 
			
		||||
		if *item.TypeId == id {
 | 
			
		||||
			return item
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Has(pb Message) bool {
 | 
			
		||||
	return ms.find(pb) != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Unmarshal(pb Message) error {
 | 
			
		||||
	if item := ms.find(pb); item != nil {
 | 
			
		||||
		return Unmarshal(item.Message, pb)
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := pb.(messageTypeIder); !ok {
 | 
			
		||||
		return errNoMessageTypeID
 | 
			
		||||
	}
 | 
			
		||||
	return nil // TODO: return error instead?
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Marshal(pb Message) error {
 | 
			
		||||
	msg, err := Marshal(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if item := ms.find(pb); item != nil {
 | 
			
		||||
		// reuse existing item
 | 
			
		||||
		item.Message = msg
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mti, ok := pb.(messageTypeIder)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return errNoMessageTypeID
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mtid := mti.MessageTypeId()
 | 
			
		||||
	ms.Item = append(ms.Item, &_MessageSet_Item{
 | 
			
		||||
		TypeId:  &mtid,
 | 
			
		||||
		Message: msg,
 | 
			
		||||
	})
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Reset()         { *ms = messageSet{} }
 | 
			
		||||
func (ms *messageSet) String() string { return CompactTextString(ms) }
 | 
			
		||||
func (*messageSet) ProtoMessage()     {}
 | 
			
		||||
 | 
			
		||||
// Support for the message_set_wire_format message option.
 | 
			
		||||
 | 
			
		||||
func skipVarint(buf []byte) []byte {
 | 
			
		||||
	i := 0
 | 
			
		||||
	for ; buf[i]&0x80 != 0; i++ {
 | 
			
		||||
	}
 | 
			
		||||
	return buf[i+1:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
	var m map[int32]Extension
 | 
			
		||||
	switch exts := exts.(type) {
 | 
			
		||||
	case *XXX_InternalExtensions:
 | 
			
		||||
		m = exts.extensionsWrite()
 | 
			
		||||
	case map[int32]Extension:
 | 
			
		||||
		m = exts
 | 
			
		||||
	default:
 | 
			
		||||
		return errors.New("proto: not an extension map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ms := new(messageSet)
 | 
			
		||||
	if err := Unmarshal(buf, ms); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	for _, item := range ms.Item {
 | 
			
		||||
		id := *item.TypeId
 | 
			
		||||
		msg := item.Message
 | 
			
		||||
 | 
			
		||||
		// Restore wire type and field number varint, plus length varint.
 | 
			
		||||
		// Be careful to preserve duplicate items.
 | 
			
		||||
		b := EncodeVarint(uint64(id)<<3 | WireBytes)
 | 
			
		||||
		if ext, ok := m[id]; ok {
 | 
			
		||||
			// Existing data; rip off the tag and length varint
 | 
			
		||||
			// so we join the new data correctly.
 | 
			
		||||
			// We can assume that ext.enc is set because we are unmarshaling.
 | 
			
		||||
			o := ext.enc[len(b):]   // skip wire type and field number
 | 
			
		||||
			_, n := DecodeVarint(o) // calculate length of length varint
 | 
			
		||||
			o = o[n:]               // skip length varint
 | 
			
		||||
			msg = append(o, msg...) // join old data and new data
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, EncodeVarint(uint64(len(msg)))...)
 | 
			
		||||
		b = append(b, msg...)
 | 
			
		||||
 | 
			
		||||
		m[id] = Extension{enc: b}
 | 
			
		||||
	}
 | 
			
		||||
	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,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,357 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 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.
 | 
			
		||||
 | 
			
		||||
// +build purego appengine js
 | 
			
		||||
 | 
			
		||||
// This file contains an implementation of proto field accesses using package reflect.
 | 
			
		||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
 | 
			
		||||
// be used on App Engine.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const unsafeAllowed = false
 | 
			
		||||
 | 
			
		||||
// A field identifies a field in a struct, accessible from a pointer.
 | 
			
		||||
// In this implementation, a field is identified by the sequence of field indices
 | 
			
		||||
// passed to reflect's FieldByIndex.
 | 
			
		||||
type field []int
 | 
			
		||||
 | 
			
		||||
// toField returns a field equivalent to the given reflect field.
 | 
			
		||||
func toField(f *reflect.StructField) field {
 | 
			
		||||
	return f.Index
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// invalidField is an invalid field identifier.
 | 
			
		||||
var invalidField = field(nil)
 | 
			
		||||
 | 
			
		||||
// zeroField is a noop when calling pointer.offset.
 | 
			
		||||
var zeroField = field([]int{})
 | 
			
		||||
 | 
			
		||||
// IsValid reports whether the field identifier is valid.
 | 
			
		||||
func (f field) IsValid() bool { return f != nil }
 | 
			
		||||
 | 
			
		||||
// The pointer type is for the table-driven decoder.
 | 
			
		||||
// The implementation here uses a reflect.Value of pointer type to
 | 
			
		||||
// create a generic pointer. In pointer_unsafe.go we use unsafe
 | 
			
		||||
// instead of reflect to implement the same (but faster) interface.
 | 
			
		||||
type pointer struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toPointer converts an interface of pointer type to a pointer
 | 
			
		||||
// that points to the same target.
 | 
			
		||||
func toPointer(i *Message) pointer {
 | 
			
		||||
	return pointer{v: reflect.ValueOf(*i)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toAddrPointer converts an interface to a pointer that points to
 | 
			
		||||
// the interface data.
 | 
			
		||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
 | 
			
		||||
	v := reflect.ValueOf(*i)
 | 
			
		||||
	u := reflect.New(v.Type())
 | 
			
		||||
	u.Elem().Set(v)
 | 
			
		||||
	return pointer{v: u}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// valToPointer converts v to a pointer.  v must be of pointer type.
 | 
			
		||||
func valToPointer(v reflect.Value) pointer {
 | 
			
		||||
	return pointer{v: v}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// offset converts from a pointer to a structure to a pointer to
 | 
			
		||||
// one of its fields.
 | 
			
		||||
func (p pointer) offset(f field) pointer {
 | 
			
		||||
	return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) isNil() bool {
 | 
			
		||||
	return p.v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// grow updates the slice s in place to make it one element longer.
 | 
			
		||||
// s must be addressable.
 | 
			
		||||
// Returns the (addressable) new element.
 | 
			
		||||
func grow(s reflect.Value) reflect.Value {
 | 
			
		||||
	n, m := s.Len(), s.Cap()
 | 
			
		||||
	if n < m {
 | 
			
		||||
		s.SetLen(n + 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
 | 
			
		||||
	}
 | 
			
		||||
	return s.Index(n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toInt64() *int64 {
 | 
			
		||||
	return p.v.Interface().(*int64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Ptr() **int64 {
 | 
			
		||||
	return p.v.Interface().(**int64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Slice() *[]int64 {
 | 
			
		||||
	return p.v.Interface().(*[]int64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var int32ptr = reflect.TypeOf((*int32)(nil))
 | 
			
		||||
 | 
			
		||||
func (p pointer) toInt32() *int32 {
 | 
			
		||||
	return p.v.Convert(int32ptr).Interface().(*int32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The toInt32Ptr/Slice methods don't work because of enums.
 | 
			
		||||
// Instead, we must use set/get methods for the int32ptr/slice case.
 | 
			
		||||
/*
 | 
			
		||||
	func (p pointer) toInt32Ptr() **int32 {
 | 
			
		||||
		return p.v.Interface().(**int32)
 | 
			
		||||
}
 | 
			
		||||
	func (p pointer) toInt32Slice() *[]int32 {
 | 
			
		||||
		return p.v.Interface().(*[]int32)
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
func (p pointer) getInt32Ptr() *int32 {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		return p.v.Elem().Interface().(*int32)
 | 
			
		||||
	}
 | 
			
		||||
	// an enum
 | 
			
		||||
	return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setInt32Ptr(v int32) {
 | 
			
		||||
	// Allocate value in a *int32. Possibly convert that to a *enum.
 | 
			
		||||
	// Then assign it to a **int32 or **enum.
 | 
			
		||||
	// Note: we can convert *int32 to *enum, but we can't convert
 | 
			
		||||
	// **int32 to **enum!
 | 
			
		||||
	p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInt32Slice copies []int32 from p as a new slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) getInt32Slice() []int32 {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		return p.v.Elem().Interface().([]int32)
 | 
			
		||||
	}
 | 
			
		||||
	// an enum
 | 
			
		||||
	// Allocate a []int32, then assign []enum's values into it.
 | 
			
		||||
	// Note: we can't convert []enum to []int32.
 | 
			
		||||
	slice := p.v.Elem()
 | 
			
		||||
	s := make([]int32, slice.Len())
 | 
			
		||||
	for i := 0; i < slice.Len(); i++ {
 | 
			
		||||
		s[i] = int32(slice.Index(i).Int())
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setInt32Slice copies []int32 into p as a new slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) setInt32Slice(v []int32) {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		p.v.Elem().Set(reflect.ValueOf(v))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// an enum
 | 
			
		||||
	// Allocate a []enum, then assign []int32's values into it.
 | 
			
		||||
	// Note: we can't convert []enum to []int32.
 | 
			
		||||
	slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
 | 
			
		||||
	for i, x := range v {
 | 
			
		||||
		slice.Index(i).SetInt(int64(x))
 | 
			
		||||
	}
 | 
			
		||||
	p.v.Elem().Set(slice)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) appendInt32Slice(v int32) {
 | 
			
		||||
	grow(p.v.Elem()).SetInt(int64(v))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toUint64() *uint64 {
 | 
			
		||||
	return p.v.Interface().(*uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Ptr() **uint64 {
 | 
			
		||||
	return p.v.Interface().(**uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Slice() *[]uint64 {
 | 
			
		||||
	return p.v.Interface().(*[]uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32() *uint32 {
 | 
			
		||||
	return p.v.Interface().(*uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Ptr() **uint32 {
 | 
			
		||||
	return p.v.Interface().(**uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Slice() *[]uint32 {
 | 
			
		||||
	return p.v.Interface().(*[]uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBool() *bool {
 | 
			
		||||
	return p.v.Interface().(*bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolPtr() **bool {
 | 
			
		||||
	return p.v.Interface().(**bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolSlice() *[]bool {
 | 
			
		||||
	return p.v.Interface().(*[]bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64() *float64 {
 | 
			
		||||
	return p.v.Interface().(*float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Ptr() **float64 {
 | 
			
		||||
	return p.v.Interface().(**float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Slice() *[]float64 {
 | 
			
		||||
	return p.v.Interface().(*[]float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32() *float32 {
 | 
			
		||||
	return p.v.Interface().(*float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Ptr() **float32 {
 | 
			
		||||
	return p.v.Interface().(**float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Slice() *[]float32 {
 | 
			
		||||
	return p.v.Interface().(*[]float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toString() *string {
 | 
			
		||||
	return p.v.Interface().(*string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringPtr() **string {
 | 
			
		||||
	return p.v.Interface().(**string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringSlice() *[]string {
 | 
			
		||||
	return p.v.Interface().(*[]string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytes() *[]byte {
 | 
			
		||||
	return p.v.Interface().(*[]byte)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytesSlice() *[][]byte {
 | 
			
		||||
	return p.v.Interface().(*[][]byte)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
 | 
			
		||||
	return p.v.Interface().(*XXX_InternalExtensions)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toOldExtensions() *map[int32]Extension {
 | 
			
		||||
	return p.v.Interface().(*map[int32]Extension)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) getPointer() pointer {
 | 
			
		||||
	return pointer{v: p.v.Elem()}
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setPointer(q pointer) {
 | 
			
		||||
	p.v.Elem().Set(q.v)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) appendPointer(q pointer) {
 | 
			
		||||
	grow(p.v.Elem()).Set(q.v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPointerSlice copies []*T from p as a new []pointer.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) getPointerSlice() []pointer {
 | 
			
		||||
	if p.v.IsNil() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	n := p.v.Elem().Len()
 | 
			
		||||
	s := make([]pointer, n)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		s[i] = pointer{v: p.v.Elem().Index(i)}
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPointerSlice copies []pointer into p as a new []*T.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) setPointerSlice(v []pointer) {
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
 | 
			
		||||
	for _, p := range v {
 | 
			
		||||
		s = reflect.Append(s, p.v)
 | 
			
		||||
	}
 | 
			
		||||
	p.v.Elem().Set(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInterfacePointer returns a pointer that points to the
 | 
			
		||||
// interface data of the interface pointed by p.
 | 
			
		||||
func (p pointer) getInterfacePointer() pointer {
 | 
			
		||||
	if p.v.Elem().IsNil() {
 | 
			
		||||
		return pointer{v: p.v.Elem()}
 | 
			
		||||
	}
 | 
			
		||||
	return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
 | 
			
		||||
	// TODO: check that p.v.Type().Elem() == t?
 | 
			
		||||
	return p.v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var atomicLock sync.Mutex
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
// 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.
 | 
			
		||||
 | 
			
		||||
// +build purego appengine js
 | 
			
		||||
 | 
			
		||||
// This file contains an implementation of proto field accesses using package reflect.
 | 
			
		||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
 | 
			
		||||
// be used on App Engine.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO: untested, so probably incorrect.
 | 
			
		||||
 | 
			
		||||
func (p pointer) getRef() pointer {
 | 
			
		||||
	return pointer{v: p.v.Addr()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) appendRef(v pointer, typ reflect.Type) {
 | 
			
		||||
	slice := p.getSlice(typ)
 | 
			
		||||
	elem := v.asPointerTo(typ).Elem()
 | 
			
		||||
	newSlice := reflect.Append(slice, elem)
 | 
			
		||||
	slice.Set(newSlice)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) getSlice(typ reflect.Type) reflect.Value {
 | 
			
		||||
	sliceTyp := reflect.SliceOf(typ)
 | 
			
		||||
	slice := p.asPointerTo(sliceTyp)
 | 
			
		||||
	slice = slice.Elem()
 | 
			
		||||
	return slice
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,308 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2012 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.
 | 
			
		||||
 | 
			
		||||
// +build !purego,!appengine,!js
 | 
			
		||||
 | 
			
		||||
// This file contains the implementation of the proto field accesses using package unsafe.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const unsafeAllowed = true
 | 
			
		||||
 | 
			
		||||
// A field identifies a field in a struct, accessible from a pointer.
 | 
			
		||||
// In this implementation, a field is identified by its byte offset from the start of the struct.
 | 
			
		||||
type field uintptr
 | 
			
		||||
 | 
			
		||||
// toField returns a field equivalent to the given reflect field.
 | 
			
		||||
func toField(f *reflect.StructField) field {
 | 
			
		||||
	return field(f.Offset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// invalidField is an invalid field identifier.
 | 
			
		||||
const invalidField = ^field(0)
 | 
			
		||||
 | 
			
		||||
// zeroField is a noop when calling pointer.offset.
 | 
			
		||||
const zeroField = field(0)
 | 
			
		||||
 | 
			
		||||
// IsValid reports whether the field identifier is valid.
 | 
			
		||||
func (f field) IsValid() bool {
 | 
			
		||||
	return f != invalidField
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The pointer type below is for the new table-driven encoder/decoder.
 | 
			
		||||
// The implementation here uses unsafe.Pointer to create a generic pointer.
 | 
			
		||||
// In pointer_reflect.go we use reflect instead of unsafe to implement
 | 
			
		||||
// the same (but slower) interface.
 | 
			
		||||
type pointer struct {
 | 
			
		||||
	p unsafe.Pointer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// size of pointer
 | 
			
		||||
var ptrSize = unsafe.Sizeof(uintptr(0))
 | 
			
		||||
 | 
			
		||||
// toPointer converts an interface of pointer type to a pointer
 | 
			
		||||
// that points to the same target.
 | 
			
		||||
func toPointer(i *Message) pointer {
 | 
			
		||||
	// Super-tricky - read pointer out of data word of interface value.
 | 
			
		||||
	// Saves ~25ns over the equivalent:
 | 
			
		||||
	// return valToPointer(reflect.ValueOf(*i))
 | 
			
		||||
	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toAddrPointer converts an interface to a pointer that points to
 | 
			
		||||
// the interface data.
 | 
			
		||||
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.
 | 
			
		||||
		return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
 | 
			
		||||
	}
 | 
			
		||||
	// 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.
 | 
			
		||||
func valToPointer(v reflect.Value) pointer {
 | 
			
		||||
	return pointer{p: unsafe.Pointer(v.Pointer())}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// offset converts from a pointer to a structure to a pointer to
 | 
			
		||||
// one of its fields.
 | 
			
		||||
func (p pointer) offset(f field) pointer {
 | 
			
		||||
	// For safety, we should panic if !f.IsValid, however calling panic causes
 | 
			
		||||
	// this to no longer be inlineable, which is a serious performance cost.
 | 
			
		||||
	/*
 | 
			
		||||
		if !f.IsValid() {
 | 
			
		||||
			panic("invalid field")
 | 
			
		||||
		}
 | 
			
		||||
	*/
 | 
			
		||||
	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) isNil() bool {
 | 
			
		||||
	return p.p == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toInt64() *int64 {
 | 
			
		||||
	return (*int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Ptr() **int64 {
 | 
			
		||||
	return (**int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Slice() *[]int64 {
 | 
			
		||||
	return (*[]int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt32() *int32 {
 | 
			
		||||
	return (*int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
 | 
			
		||||
/*
 | 
			
		||||
	func (p pointer) toInt32Ptr() **int32 {
 | 
			
		||||
		return (**int32)(p.p)
 | 
			
		||||
	}
 | 
			
		||||
	func (p pointer) toInt32Slice() *[]int32 {
 | 
			
		||||
		return (*[]int32)(p.p)
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
func (p pointer) getInt32Ptr() *int32 {
 | 
			
		||||
	return *(**int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setInt32Ptr(v int32) {
 | 
			
		||||
	*(**int32)(p.p) = &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInt32Slice loads a []int32 from p.
 | 
			
		||||
// The value returned is aliased with the original slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) getInt32Slice() []int32 {
 | 
			
		||||
	return *(*[]int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setInt32Slice stores a []int32 to p.
 | 
			
		||||
// The value set is aliased with the input slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) setInt32Slice(v []int32) {
 | 
			
		||||
	*(*[]int32)(p.p) = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
 | 
			
		||||
func (p pointer) appendInt32Slice(v int32) {
 | 
			
		||||
	s := (*[]int32)(p.p)
 | 
			
		||||
	*s = append(*s, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toUint64() *uint64 {
 | 
			
		||||
	return (*uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Ptr() **uint64 {
 | 
			
		||||
	return (**uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Slice() *[]uint64 {
 | 
			
		||||
	return (*[]uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32() *uint32 {
 | 
			
		||||
	return (*uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Ptr() **uint32 {
 | 
			
		||||
	return (**uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Slice() *[]uint32 {
 | 
			
		||||
	return (*[]uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBool() *bool {
 | 
			
		||||
	return (*bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolPtr() **bool {
 | 
			
		||||
	return (**bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolSlice() *[]bool {
 | 
			
		||||
	return (*[]bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64() *float64 {
 | 
			
		||||
	return (*float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Ptr() **float64 {
 | 
			
		||||
	return (**float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Slice() *[]float64 {
 | 
			
		||||
	return (*[]float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32() *float32 {
 | 
			
		||||
	return (*float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Ptr() **float32 {
 | 
			
		||||
	return (**float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Slice() *[]float32 {
 | 
			
		||||
	return (*[]float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toString() *string {
 | 
			
		||||
	return (*string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringPtr() **string {
 | 
			
		||||
	return (**string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringSlice() *[]string {
 | 
			
		||||
	return (*[]string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytes() *[]byte {
 | 
			
		||||
	return (*[]byte)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytesSlice() *[][]byte {
 | 
			
		||||
	return (*[][]byte)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
 | 
			
		||||
	return (*XXX_InternalExtensions)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toOldExtensions() *map[int32]Extension {
 | 
			
		||||
	return (*map[int32]Extension)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPointerSlice loads []*T from p as a []pointer.
 | 
			
		||||
// The value returned is aliased with the original slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) getPointerSlice() []pointer {
 | 
			
		||||
	// Super-tricky - p should point to a []*T where T is a
 | 
			
		||||
	// message type. We load it as []pointer.
 | 
			
		||||
	return *(*[]pointer)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPointerSlice stores []pointer into p as a []*T.
 | 
			
		||||
// The value set is aliased with the input slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) setPointerSlice(v []pointer) {
 | 
			
		||||
	// Super-tricky - p should point to a []*T where T is a
 | 
			
		||||
	// message type. We store it as []pointer.
 | 
			
		||||
	*(*[]pointer)(p.p) = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPointer loads the pointer at p and returns it.
 | 
			
		||||
func (p pointer) getPointer() pointer {
 | 
			
		||||
	return pointer{p: *(*unsafe.Pointer)(p.p)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPointer stores the pointer q at p.
 | 
			
		||||
func (p pointer) setPointer(q pointer) {
 | 
			
		||||
	*(*unsafe.Pointer)(p.p) = q.p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// append q to the slice pointed to by p.
 | 
			
		||||
func (p pointer) appendPointer(q pointer) {
 | 
			
		||||
	s := (*[]unsafe.Pointer)(p.p)
 | 
			
		||||
	*s = append(*s, q.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInterfacePointer returns a pointer that points to the
 | 
			
		||||
// interface data of the interface pointed by p.
 | 
			
		||||
func (p pointer) getInterfacePointer() pointer {
 | 
			
		||||
	// Super-tricky - read pointer out of data word of interface value.
 | 
			
		||||
	return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// asPointerTo returns a reflect.Value that is a pointer to an
 | 
			
		||||
// object of type t stored at p.
 | 
			
		||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
 | 
			
		||||
	return reflect.NewAt(t, p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
 | 
			
		||||
	return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
 | 
			
		||||
	return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
 | 
			
		||||
	return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
 | 
			
		||||
	return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
// 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.
 | 
			
		||||
 | 
			
		||||
// +build !purego,!appengine,!js
 | 
			
		||||
 | 
			
		||||
// This file contains the implementation of the proto field accesses using package unsafe.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (p pointer) getRef() pointer {
 | 
			
		||||
	return pointer{p: (unsafe.Pointer)(&p.p)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) appendRef(v pointer, typ reflect.Type) {
 | 
			
		||||
	slice := p.getSlice(typ)
 | 
			
		||||
	elem := v.asPointerTo(typ).Elem()
 | 
			
		||||
	newSlice := reflect.Append(slice, elem)
 | 
			
		||||
	slice.Set(newSlice)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) getSlice(typ reflect.Type) reflect.Value {
 | 
			
		||||
	sliceTyp := reflect.SliceOf(typ)
 | 
			
		||||
	slice := p.asPointerTo(sliceTyp)
 | 
			
		||||
	slice = slice.Elem()
 | 
			
		||||
	return slice
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,608 @@
 | 
			
		|||
// 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.
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Routines for encoding data into the wire format for protocol buffers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const debug bool = false
 | 
			
		||||
 | 
			
		||||
// Constants that identify the encoding of a value on the wire.
 | 
			
		||||
const (
 | 
			
		||||
	WireVarint     = 0
 | 
			
		||||
	WireFixed64    = 1
 | 
			
		||||
	WireBytes      = 2
 | 
			
		||||
	WireStartGroup = 3
 | 
			
		||||
	WireEndGroup   = 4
 | 
			
		||||
	WireFixed32    = 5
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// tagMap is an optimization over map[int]int for typical protocol buffer
 | 
			
		||||
// use-cases. Encoded protocol buffers are often in tag order with small tag
 | 
			
		||||
// numbers.
 | 
			
		||||
type tagMap struct {
 | 
			
		||||
	fastTags []int
 | 
			
		||||
	slowTags map[int]int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// tagMapFastLimit is the upper bound on the tag number that will be stored in
 | 
			
		||||
// the tagMap slice rather than its map.
 | 
			
		||||
const tagMapFastLimit = 1024
 | 
			
		||||
 | 
			
		||||
func (p *tagMap) get(t int) (int, bool) {
 | 
			
		||||
	if t > 0 && t < tagMapFastLimit {
 | 
			
		||||
		if t >= len(p.fastTags) {
 | 
			
		||||
			return 0, false
 | 
			
		||||
		}
 | 
			
		||||
		fi := p.fastTags[t]
 | 
			
		||||
		return fi, fi >= 0
 | 
			
		||||
	}
 | 
			
		||||
	fi, ok := p.slowTags[t]
 | 
			
		||||
	return fi, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tagMap) put(t int, fi int) {
 | 
			
		||||
	if t > 0 && t < tagMapFastLimit {
 | 
			
		||||
		for len(p.fastTags) < t+1 {
 | 
			
		||||
			p.fastTags = append(p.fastTags, -1)
 | 
			
		||||
		}
 | 
			
		||||
		p.fastTags[t] = fi
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if p.slowTags == nil {
 | 
			
		||||
		p.slowTags = make(map[int]int)
 | 
			
		||||
	}
 | 
			
		||||
	p.slowTags[t] = fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StructProperties represents properties for all the fields of a struct.
 | 
			
		||||
// decoderTags and decoderOrigNames should only be used by the decoder.
 | 
			
		||||
type StructProperties struct {
 | 
			
		||||
	Prop             []*Properties  // properties for each field
 | 
			
		||||
	reqCount         int            // required count
 | 
			
		||||
	decoderTags      tagMap         // map from proto tag to struct field number
 | 
			
		||||
	decoderOrigNames map[string]int // map from original name to struct field number
 | 
			
		||||
	order            []int          // list of struct field numbers in tag order
 | 
			
		||||
 | 
			
		||||
	// OneofTypes contains information about the oneof fields in this message.
 | 
			
		||||
	// It is keyed by the original name of a field.
 | 
			
		||||
	OneofTypes map[string]*OneofProperties
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OneofProperties represents information about a specific field in a oneof.
 | 
			
		||||
type OneofProperties struct {
 | 
			
		||||
	Type  reflect.Type // pointer to generated struct type for this oneof field
 | 
			
		||||
	Field int          // struct field number of the containing oneof in the message
 | 
			
		||||
	Prop  *Properties
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
 | 
			
		||||
// See encode.go, (*Buffer).enc_struct.
 | 
			
		||||
 | 
			
		||||
func (sp *StructProperties) Len() int { return len(sp.order) }
 | 
			
		||||
func (sp *StructProperties) Less(i, j int) bool {
 | 
			
		||||
	return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
 | 
			
		||||
}
 | 
			
		||||
func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
 | 
			
		||||
 | 
			
		||||
// Properties represents the protocol-specific behavior of a single struct field.
 | 
			
		||||
type Properties struct {
 | 
			
		||||
	Name     string // name of the field, for error messages
 | 
			
		||||
	OrigName string // original name before protocol compiler (always set)
 | 
			
		||||
	JSONName string // name to use for JSON; determined by protoc
 | 
			
		||||
	Wire     string
 | 
			
		||||
	WireType int
 | 
			
		||||
	Tag      int
 | 
			
		||||
	Required bool
 | 
			
		||||
	Optional bool
 | 
			
		||||
	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; set for []byte only
 | 
			
		||||
	oneof    bool   // whether this is a oneof field
 | 
			
		||||
 | 
			
		||||
	Default     string // default value
 | 
			
		||||
	HasDefault  bool   // whether an explicit default was provided
 | 
			
		||||
	CustomType  string
 | 
			
		||||
	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
 | 
			
		||||
	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.
 | 
			
		||||
func (p *Properties) String() string {
 | 
			
		||||
	s := p.Wire
 | 
			
		||||
	s += ","
 | 
			
		||||
	s += strconv.Itoa(p.Tag)
 | 
			
		||||
	if p.Required {
 | 
			
		||||
		s += ",req"
 | 
			
		||||
	}
 | 
			
		||||
	if p.Optional {
 | 
			
		||||
		s += ",opt"
 | 
			
		||||
	}
 | 
			
		||||
	if p.Repeated {
 | 
			
		||||
		s += ",rep"
 | 
			
		||||
	}
 | 
			
		||||
	if p.Packed {
 | 
			
		||||
		s += ",packed"
 | 
			
		||||
	}
 | 
			
		||||
	s += ",name=" + p.OrigName
 | 
			
		||||
	if p.JSONName != p.OrigName {
 | 
			
		||||
		s += ",json=" + p.JSONName
 | 
			
		||||
	}
 | 
			
		||||
	if p.proto3 {
 | 
			
		||||
		s += ",proto3"
 | 
			
		||||
	}
 | 
			
		||||
	if p.oneof {
 | 
			
		||||
		s += ",oneof"
 | 
			
		||||
	}
 | 
			
		||||
	if len(p.Enum) > 0 {
 | 
			
		||||
		s += ",enum=" + p.Enum
 | 
			
		||||
	}
 | 
			
		||||
	if p.HasDefault {
 | 
			
		||||
		s += ",def=" + p.Default
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse populates p by parsing a string in the protobuf struct field tag style.
 | 
			
		||||
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 {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.Wire = fields[0]
 | 
			
		||||
	switch p.Wire {
 | 
			
		||||
	case "varint":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
	case "fixed32":
 | 
			
		||||
		p.WireType = WireFixed32
 | 
			
		||||
	case "fixed64":
 | 
			
		||||
		p.WireType = WireFixed64
 | 
			
		||||
	case "zigzag32":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
	case "zigzag64":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
	case "bytes", "group":
 | 
			
		||||
		p.WireType = WireBytes
 | 
			
		||||
		// no numeric converter for non-numeric types
 | 
			
		||||
	default:
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	p.Tag, err = strconv.Atoi(fields[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
outer:
 | 
			
		||||
	for i := 2; i < len(fields); i++ {
 | 
			
		||||
		f := fields[i]
 | 
			
		||||
		switch {
 | 
			
		||||
		case f == "req":
 | 
			
		||||
			p.Required = true
 | 
			
		||||
		case f == "opt":
 | 
			
		||||
			p.Optional = true
 | 
			
		||||
		case f == "rep":
 | 
			
		||||
			p.Repeated = true
 | 
			
		||||
		case f == "packed":
 | 
			
		||||
			p.Packed = true
 | 
			
		||||
		case strings.HasPrefix(f, "name="):
 | 
			
		||||
			p.OrigName = f[5:]
 | 
			
		||||
		case strings.HasPrefix(f, "json="):
 | 
			
		||||
			p.JSONName = f[5:]
 | 
			
		||||
		case strings.HasPrefix(f, "enum="):
 | 
			
		||||
			p.Enum = f[5:]
 | 
			
		||||
		case f == "proto3":
 | 
			
		||||
			p.proto3 = true
 | 
			
		||||
		case f == "oneof":
 | 
			
		||||
			p.oneof = true
 | 
			
		||||
		case strings.HasPrefix(f, "def="):
 | 
			
		||||
			p.HasDefault = true
 | 
			
		||||
			p.Default = f[4:] // rest of string
 | 
			
		||||
			if i+1 < len(fields) {
 | 
			
		||||
				// Commas aren't escaped, and def is always last.
 | 
			
		||||
				p.Default += "," + strings.Join(fields[i+1:], ",")
 | 
			
		||||
				break outer
 | 
			
		||||
			}
 | 
			
		||||
		case strings.HasPrefix(f, "embedded="):
 | 
			
		||||
			p.OrigName = strings.Split(f, "=")[1]
 | 
			
		||||
		case strings.HasPrefix(f, "customtype="):
 | 
			
		||||
			p.CustomType = strings.Split(f, "=")[1]
 | 
			
		||||
		case strings.HasPrefix(f, "casttype="):
 | 
			
		||||
			p.CastType = strings.Split(f, "=")[1]
 | 
			
		||||
		case f == "stdtime":
 | 
			
		||||
			p.StdTime = true
 | 
			
		||||
		case f == "stdduration":
 | 
			
		||||
			p.StdDuration = true
 | 
			
		||||
		case f == "wktptr":
 | 
			
		||||
			p.WktPointer = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
 | 
			
		||||
 | 
			
		||||
// setFieldProps initializes the field properties for submessages and maps.
 | 
			
		||||
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
 | 
			
		||||
	isMap := typ.Kind() == reflect.Map
 | 
			
		||||
	if len(p.CustomType) > 0 && !isMap {
 | 
			
		||||
		p.ctype = typ
 | 
			
		||||
		p.setTag(lockGetProp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if p.StdTime && !isMap {
 | 
			
		||||
		p.setTag(lockGetProp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if p.StdDuration && !isMap {
 | 
			
		||||
		p.setTag(lockGetProp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if p.WktPointer && !isMap {
 | 
			
		||||
		p.setTag(lockGetProp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	switch t1 := typ; t1.Kind() {
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		p.stype = typ
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		if t1.Elem().Kind() == reflect.Struct {
 | 
			
		||||
			p.stype = t1.Elem()
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		switch t2 := t1.Elem(); t2.Kind() {
 | 
			
		||||
		case reflect.Ptr:
 | 
			
		||||
			switch t3 := t2.Elem(); t3.Kind() {
 | 
			
		||||
			case reflect.Struct:
 | 
			
		||||
				p.stype = t3
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			p.stype = t2
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
 | 
			
		||||
		p.mtype = t1
 | 
			
		||||
		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),
 | 
			
		||||
			// so we need encoders for the pointer to this type.
 | 
			
		||||
			vtype = reflect.PtrTo(vtype)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p.mvalprop.CustomType = p.CustomType
 | 
			
		||||
		p.mvalprop.StdDuration = p.StdDuration
 | 
			
		||||
		p.mvalprop.StdTime = p.StdTime
 | 
			
		||||
		p.mvalprop.WktPointer = p.WktPointer
 | 
			
		||||
		p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
 | 
			
		||||
	}
 | 
			
		||||
	p.setTag(lockGetProp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Properties) setTag(lockGetProp bool) {
 | 
			
		||||
	if p.stype != nil {
 | 
			
		||||
		if lockGetProp {
 | 
			
		||||
			p.sprop = GetProperties(p.stype)
 | 
			
		||||
		} else {
 | 
			
		||||
			p.sprop = getPropertiesLocked(p.stype)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Init populates the properties from a protocol buffer struct tag.
 | 
			
		||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
 | 
			
		||||
	p.init(typ, name, tag, f, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
 | 
			
		||||
	// "bytes,49,opt,def=hello!"
 | 
			
		||||
	p.Name = name
 | 
			
		||||
	p.OrigName = name
 | 
			
		||||
	if tag == "" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	p.Parse(tag)
 | 
			
		||||
	p.setFieldProps(typ, f, lockGetProp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	propertiesMu  sync.RWMutex
 | 
			
		||||
	propertiesMap = make(map[reflect.Type]*StructProperties)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetProperties returns the list of properties for the type represented by t.
 | 
			
		||||
// t must represent a generated struct type of a protocol message.
 | 
			
		||||
func GetProperties(t reflect.Type) *StructProperties {
 | 
			
		||||
	if t.Kind() != reflect.Struct {
 | 
			
		||||
		panic("proto: type must have kind struct")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Most calls to GetProperties in a long-running program will be
 | 
			
		||||
	// retrieving details for types we have seen before.
 | 
			
		||||
	propertiesMu.RLock()
 | 
			
		||||
	sprop, ok := propertiesMap[t]
 | 
			
		||||
	propertiesMu.RUnlock()
 | 
			
		||||
	if ok {
 | 
			
		||||
		if collectStats {
 | 
			
		||||
			stats.Chit++
 | 
			
		||||
		}
 | 
			
		||||
		return sprop
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	propertiesMu.Lock()
 | 
			
		||||
	sprop = getPropertiesLocked(t)
 | 
			
		||||
	propertiesMu.Unlock()
 | 
			
		||||
	return sprop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
	propertiesMap[t] = prop
 | 
			
		||||
 | 
			
		||||
	// build properties
 | 
			
		||||
	prop.Prop = make([]*Properties, t.NumField())
 | 
			
		||||
	prop.order = make([]int, t.NumField())
 | 
			
		||||
 | 
			
		||||
	isOneofMessage := false
 | 
			
		||||
	for i := 0; i < t.NumField(); i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		p := new(Properties)
 | 
			
		||||
		name := f.Name
 | 
			
		||||
		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
 | 
			
		||||
 | 
			
		||||
		oneof := f.Tag.Get("protobuf_oneof") // special case
 | 
			
		||||
		if oneof != "" {
 | 
			
		||||
			isOneofMessage = true
 | 
			
		||||
			// Oneof fields don't use the traditional protobuf tag.
 | 
			
		||||
			p.OrigName = oneof
 | 
			
		||||
		}
 | 
			
		||||
		prop.Prop[i] = p
 | 
			
		||||
		prop.order[i] = i
 | 
			
		||||
		if debug {
 | 
			
		||||
			print(i, " ", f.Name, " ", t.String(), " ")
 | 
			
		||||
			if p.Tag > 0 {
 | 
			
		||||
				print(p.String())
 | 
			
		||||
			}
 | 
			
		||||
			print("\n")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Re-order prop.order.
 | 
			
		||||
	sort.Sort(prop)
 | 
			
		||||
 | 
			
		||||
	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{}
 | 
			
		||||
		_, _, _, 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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// build required counts
 | 
			
		||||
	// build tags
 | 
			
		||||
	reqCount := 0
 | 
			
		||||
	prop.decoderOrigNames = make(map[string]int)
 | 
			
		||||
	for i, p := range prop.Prop {
 | 
			
		||||
		if strings.HasPrefix(p.Name, "XXX_") {
 | 
			
		||||
			// Internal fields should not appear in tags/origNames maps.
 | 
			
		||||
			// They are handled specially when encoding and decoding.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if p.Required {
 | 
			
		||||
			reqCount++
 | 
			
		||||
		}
 | 
			
		||||
		prop.decoderTags.put(p.Tag, i)
 | 
			
		||||
		prop.decoderOrigNames[p.OrigName] = i
 | 
			
		||||
	}
 | 
			
		||||
	prop.reqCount = reqCount
 | 
			
		||||
 | 
			
		||||
	return prop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A global registry of enum types.
 | 
			
		||||
// The generated code will register the generated maps by calling RegisterEnum.
 | 
			
		||||
 | 
			
		||||
var enumValueMaps = make(map[string]map[string]int32)
 | 
			
		||||
var enumStringMaps = make(map[string]map[int32]string)
 | 
			
		||||
 | 
			
		||||
// RegisterEnum is called from the generated code to install the enum descriptor
 | 
			
		||||
// maps into the global table to aid parsing text format protocol buffers.
 | 
			
		||||
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
 | 
			
		||||
	if _, ok := enumValueMaps[typeName]; ok {
 | 
			
		||||
		panic("proto: duplicate enum registered: " + typeName)
 | 
			
		||||
	}
 | 
			
		||||
	enumValueMaps[typeName] = valueMap
 | 
			
		||||
	if _, ok := enumStringMaps[typeName]; ok {
 | 
			
		||||
		panic("proto: duplicate enum registered: " + typeName)
 | 
			
		||||
	}
 | 
			
		||||
	enumStringMaps[typeName] = unusedNameMap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnumValueMap returns the mapping from names to integers of the
 | 
			
		||||
// enum type enumType, or a nil if not found.
 | 
			
		||||
func EnumValueMap(enumType string) map[string]int32 {
 | 
			
		||||
	return enumValueMaps[enumType]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A registry of all linked message types.
 | 
			
		||||
// The string is a fully-qualified proto name ("pkg.Message").
 | 
			
		||||
var (
 | 
			
		||||
	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers
 | 
			
		||||
	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types
 | 
			
		||||
	revProtoTypes  = make(map[reflect.Type]string)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RegisterType is called from generated code and maps from the fully qualified
 | 
			
		||||
// proto name to the type (pointer to struct) of the protocol buffer.
 | 
			
		||||
func RegisterType(x Message, name string) {
 | 
			
		||||
	if _, ok := protoTypedNils[name]; ok {
 | 
			
		||||
		// TODO: Some day, make this a panic.
 | 
			
		||||
		log.Printf("proto: duplicate proto type registered: %s", name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := reflect.TypeOf(x)
 | 
			
		||||
	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
 | 
			
		||||
		// Generated code always calls RegisterType with nil x.
 | 
			
		||||
		// This check is just for extra safety.
 | 
			
		||||
		protoTypedNils[name] = x
 | 
			
		||||
	} else {
 | 
			
		||||
		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
 | 
			
		||||
	}
 | 
			
		||||
	revProtoTypes[t] = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterMapType is called from generated code and maps from the fully qualified
 | 
			
		||||
// proto name to the native map type of the proto map definition.
 | 
			
		||||
func RegisterMapType(x interface{}, name string) {
 | 
			
		||||
	if reflect.TypeOf(x).Kind() != reflect.Map {
 | 
			
		||||
		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := protoMapTypes[name]; ok {
 | 
			
		||||
		log.Printf("proto: duplicate proto type registered: %s", name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := reflect.TypeOf(x)
 | 
			
		||||
	protoMapTypes[name] = t
 | 
			
		||||
	revProtoTypes[t] = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MessageName returns the fully-qualified proto name for the given message type.
 | 
			
		||||
func MessageName(x Message) string {
 | 
			
		||||
	type xname interface {
 | 
			
		||||
		XXX_MessageName() string
 | 
			
		||||
	}
 | 
			
		||||
	if m, ok := x.(xname); ok {
 | 
			
		||||
		return m.XXX_MessageName()
 | 
			
		||||
	}
 | 
			
		||||
	return revProtoTypes[reflect.TypeOf(x)]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MessageType returns the message type (pointer to struct) for a named message.
 | 
			
		||||
// The type is not guaranteed to implement proto.Message if the name refers to a
 | 
			
		||||
// map entry.
 | 
			
		||||
func MessageType(name string) reflect.Type {
 | 
			
		||||
	if t, ok := protoTypedNils[name]; ok {
 | 
			
		||||
		return reflect.TypeOf(t)
 | 
			
		||||
	}
 | 
			
		||||
	return protoMapTypes[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A registry of all linked proto files.
 | 
			
		||||
var (
 | 
			
		||||
	protoFiles = make(map[string][]byte) // file name => fileDescriptor
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RegisterFile is called from generated code and maps from the
 | 
			
		||||
// full file name of a .proto file to its compressed FileDescriptorProto.
 | 
			
		||||
func RegisterFile(filename string, fileDescriptor []byte) {
 | 
			
		||||
	protoFiles[filename] = fileDescriptor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
 | 
			
		||||
func FileDescriptor(filename string) []byte { return protoFiles[filename] }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
// 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var sizerType = reflect.TypeOf((*Sizer)(nil)).Elem()
 | 
			
		||||
var protosizerType = reflect.TypeOf((*ProtoSizer)(nil)).Elem()
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
// http://github.com/gogo/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Skip(data []byte) (n int, err error) {
 | 
			
		||||
	l := len(data)
 | 
			
		||||
	index := 0
 | 
			
		||||
	for index < l {
 | 
			
		||||
		var wire uint64
 | 
			
		||||
		for shift := uint(0); ; shift += 7 {
 | 
			
		||||
			if index >= l {
 | 
			
		||||
				return 0, io.ErrUnexpectedEOF
 | 
			
		||||
			}
 | 
			
		||||
			b := data[index]
 | 
			
		||||
			index++
 | 
			
		||||
			wire |= (uint64(b) & 0x7F) << shift
 | 
			
		||||
			if b < 0x80 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		wireType := int(wire & 0x7)
 | 
			
		||||
		switch wireType {
 | 
			
		||||
		case 0:
 | 
			
		||||
			for {
 | 
			
		||||
				if index >= l {
 | 
			
		||||
					return 0, io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				index++
 | 
			
		||||
				if data[index-1] < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return index, nil
 | 
			
		||||
		case 1:
 | 
			
		||||
			index += 8
 | 
			
		||||
			return index, nil
 | 
			
		||||
		case 2:
 | 
			
		||||
			var length int
 | 
			
		||||
			for shift := uint(0); ; shift += 7 {
 | 
			
		||||
				if index >= l {
 | 
			
		||||
					return 0, io.ErrUnexpectedEOF
 | 
			
		||||
				}
 | 
			
		||||
				b := data[index]
 | 
			
		||||
				index++
 | 
			
		||||
				length |= (int(b) & 0x7F) << shift
 | 
			
		||||
				if b < 0x80 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			index += length
 | 
			
		||||
			return index, nil
 | 
			
		||||
		case 3:
 | 
			
		||||
			for {
 | 
			
		||||
				var innerWire uint64
 | 
			
		||||
				var start int = index
 | 
			
		||||
				for shift := uint(0); ; shift += 7 {
 | 
			
		||||
					if index >= l {
 | 
			
		||||
						return 0, io.ErrUnexpectedEOF
 | 
			
		||||
					}
 | 
			
		||||
					b := data[index]
 | 
			
		||||
					index++
 | 
			
		||||
					innerWire |= (uint64(b) & 0x7F) << shift
 | 
			
		||||
					if b < 0x80 {
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				innerWireType := int(innerWire & 0x7)
 | 
			
		||||
				if innerWireType == 4 {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				next, err := Skip(data[start:])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
				index = start + next
 | 
			
		||||
			}
 | 
			
		||||
			return index, nil
 | 
			
		||||
		case 4:
 | 
			
		||||
			return index, nil
 | 
			
		||||
		case 5:
 | 
			
		||||
			index += 4
 | 
			
		||||
			return index, nil
 | 
			
		||||
		default:
 | 
			
		||||
			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,388 @@
 | 
			
		|||
// 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// makeMessageRefMarshaler differs a bit from makeMessageMarshaler
 | 
			
		||||
// It marshal a message T instead of a *T
 | 
			
		||||
func makeMessageRefMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			siz := u.size(ptr)
 | 
			
		||||
			return siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			siz := u.cachedsize(ptr)
 | 
			
		||||
			b = appendVarint(b, uint64(siz))
 | 
			
		||||
			return u.marshal(b, ptr, deterministic)
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// makeMessageRefSliceMarshaler differs quite a lot from makeMessageSliceMarshaler
 | 
			
		||||
// It marshals a slice of messages []T instead of []*T
 | 
			
		||||
func makeMessageRefSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			n := 0
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				e := elem.Interface()
 | 
			
		||||
				v := toAddrPointer(&e, false)
 | 
			
		||||
				siz := u.size(v)
 | 
			
		||||
				n += siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
			}
 | 
			
		||||
			return n
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			var err, errreq error
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				e := elem.Interface()
 | 
			
		||||
				v := toAddrPointer(&e, false)
 | 
			
		||||
				b = appendVarint(b, wiretag)
 | 
			
		||||
				siz := u.size(v)
 | 
			
		||||
				b = appendVarint(b, uint64(siz))
 | 
			
		||||
				b, err = u.marshal(b, v, deterministic)
 | 
			
		||||
 | 
			
		||||
				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, errreq
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeCustomPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return 0
 | 
			
		||||
			}
 | 
			
		||||
			m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
 | 
			
		||||
			siz := m.Size()
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return b, nil
 | 
			
		||||
			}
 | 
			
		||||
			m := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(custom)
 | 
			
		||||
			siz := m.Size()
 | 
			
		||||
			buf, err := m.Marshal()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(siz))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeCustomMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			m := ptr.asPointerTo(u.typ).Interface().(custom)
 | 
			
		||||
			siz := m.Size()
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			m := ptr.asPointerTo(u.typ).Interface().(custom)
 | 
			
		||||
			siz := m.Size()
 | 
			
		||||
			buf, err := m.Marshal()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(siz))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeTimeMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
 | 
			
		||||
			ts, err := timestampProto(*t)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0
 | 
			
		||||
			}
 | 
			
		||||
			siz := Size(ts)
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			t := ptr.asPointerTo(u.typ).Interface().(*time.Time)
 | 
			
		||||
			ts, err := timestampProto(*t)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			buf, err := Marshal(ts)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(len(buf)))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeTimePtrMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return 0
 | 
			
		||||
			}
 | 
			
		||||
			t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
 | 
			
		||||
			ts, err := timestampProto(*t)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0
 | 
			
		||||
			}
 | 
			
		||||
			siz := Size(ts)
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return b, nil
 | 
			
		||||
			}
 | 
			
		||||
			t := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Time)
 | 
			
		||||
			ts, err := timestampProto(*t)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			buf, err := Marshal(ts)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(len(buf)))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeTimeSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			n := 0
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				t := elem.Interface().(time.Time)
 | 
			
		||||
				ts, err := timestampProto(t)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0
 | 
			
		||||
				}
 | 
			
		||||
				siz := Size(ts)
 | 
			
		||||
				n += siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
			}
 | 
			
		||||
			return n
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				t := elem.Interface().(time.Time)
 | 
			
		||||
				ts, err := timestampProto(t)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				siz := Size(ts)
 | 
			
		||||
				buf, err := Marshal(ts)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				b = appendVarint(b, wiretag)
 | 
			
		||||
				b = appendVarint(b, uint64(siz))
 | 
			
		||||
				b = append(b, buf...)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeTimePtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			s := ptr.getSlice(reflect.PtrTo(u.typ))
 | 
			
		||||
			n := 0
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				t := elem.Interface().(*time.Time)
 | 
			
		||||
				ts, err := timestampProto(*t)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0
 | 
			
		||||
				}
 | 
			
		||||
				siz := Size(ts)
 | 
			
		||||
				n += siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
			}
 | 
			
		||||
			return n
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			s := ptr.getSlice(reflect.PtrTo(u.typ))
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				t := elem.Interface().(*time.Time)
 | 
			
		||||
				ts, err := timestampProto(*t)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				siz := Size(ts)
 | 
			
		||||
				buf, err := Marshal(ts)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				b = appendVarint(b, wiretag)
 | 
			
		||||
				b = appendVarint(b, uint64(siz))
 | 
			
		||||
				b = append(b, buf...)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeDurationMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
 | 
			
		||||
			dur := durationProto(*d)
 | 
			
		||||
			siz := Size(dur)
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			d := ptr.asPointerTo(u.typ).Interface().(*time.Duration)
 | 
			
		||||
			dur := durationProto(*d)
 | 
			
		||||
			buf, err := Marshal(dur)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(len(buf)))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeDurationPtrMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return 0
 | 
			
		||||
			}
 | 
			
		||||
			d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
 | 
			
		||||
			dur := durationProto(*d)
 | 
			
		||||
			siz := Size(dur)
 | 
			
		||||
			return tagsize + SizeVarint(uint64(siz)) + siz
 | 
			
		||||
		}, func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			if ptr.isNil() {
 | 
			
		||||
				return b, nil
 | 
			
		||||
			}
 | 
			
		||||
			d := ptr.asPointerTo(reflect.PtrTo(u.typ)).Elem().Interface().(*time.Duration)
 | 
			
		||||
			dur := durationProto(*d)
 | 
			
		||||
			buf, err := Marshal(dur)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = appendVarint(b, wiretag)
 | 
			
		||||
			b = appendVarint(b, uint64(len(buf)))
 | 
			
		||||
			b = append(b, buf...)
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeDurationSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			n := 0
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				d := elem.Interface().(time.Duration)
 | 
			
		||||
				dur := durationProto(d)
 | 
			
		||||
				siz := Size(dur)
 | 
			
		||||
				n += siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
			}
 | 
			
		||||
			return n
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			s := ptr.getSlice(u.typ)
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				d := elem.Interface().(time.Duration)
 | 
			
		||||
				dur := durationProto(d)
 | 
			
		||||
				siz := Size(dur)
 | 
			
		||||
				buf, err := Marshal(dur)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				b = appendVarint(b, wiretag)
 | 
			
		||||
				b = appendVarint(b, uint64(siz))
 | 
			
		||||
				b = append(b, buf...)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeDurationPtrSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
 | 
			
		||||
	return func(ptr pointer, tagsize int) int {
 | 
			
		||||
			s := ptr.getSlice(reflect.PtrTo(u.typ))
 | 
			
		||||
			n := 0
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				d := elem.Interface().(*time.Duration)
 | 
			
		||||
				dur := durationProto(*d)
 | 
			
		||||
				siz := Size(dur)
 | 
			
		||||
				n += siz + SizeVarint(uint64(siz)) + tagsize
 | 
			
		||||
			}
 | 
			
		||||
			return n
 | 
			
		||||
		},
 | 
			
		||||
		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
 | 
			
		||||
			s := ptr.getSlice(reflect.PtrTo(u.typ))
 | 
			
		||||
			for i := 0; i < s.Len(); i++ {
 | 
			
		||||
				elem := s.Index(i)
 | 
			
		||||
				d := elem.Interface().(*time.Duration)
 | 
			
		||||
				dur := durationProto(*d)
 | 
			
		||||
				siz := Size(dur)
 | 
			
		||||
				buf, err := Marshal(dur)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, err
 | 
			
		||||
				}
 | 
			
		||||
				b = appendVarint(b, wiretag)
 | 
			
		||||
				b = appendVarint(b, uint64(siz))
 | 
			
		||||
				b = append(b, buf...)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return b, nil
 | 
			
		||||
		}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,657 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2016 The Go Authors.  All rights reserved.
 | 
			
		||||
// https://github.com/golang/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
// contributors may be used to endorse or promote products derived from
 | 
			
		||||
// this software without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Merge merges the src message into dst.
 | 
			
		||||
// This assumes that dst and src of the same type and are non-nil.
 | 
			
		||||
func (a *InternalMessageInfo) Merge(dst, src Message) {
 | 
			
		||||
	mi := atomicLoadMergeInfo(&a.merge)
 | 
			
		||||
	if mi == nil {
 | 
			
		||||
		mi = getMergeInfo(reflect.TypeOf(dst).Elem())
 | 
			
		||||
		atomicStoreMergeInfo(&a.merge, mi)
 | 
			
		||||
	}
 | 
			
		||||
	mi.merge(toPointer(&dst), toPointer(&src))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mergeInfo struct {
 | 
			
		||||
	typ reflect.Type
 | 
			
		||||
 | 
			
		||||
	initialized int32 // 0: only typ is valid, 1: everything is valid
 | 
			
		||||
	lock        sync.Mutex
 | 
			
		||||
 | 
			
		||||
	fields       []mergeFieldInfo
 | 
			
		||||
	unrecognized field // Offset of XXX_unrecognized
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mergeFieldInfo struct {
 | 
			
		||||
	field field // Offset of field, guaranteed to be valid
 | 
			
		||||
 | 
			
		||||
	// isPointer reports whether the value in the field is a pointer.
 | 
			
		||||
	// This is true for the following situations:
 | 
			
		||||
	//	* Pointer to struct
 | 
			
		||||
	//	* Pointer to basic type (proto2 only)
 | 
			
		||||
	//	* Slice (first value in slice header is a pointer)
 | 
			
		||||
	//	* String (first value in string header is a pointer)
 | 
			
		||||
	isPointer bool
 | 
			
		||||
 | 
			
		||||
	// basicWidth reports the width of the field assuming that it is directly
 | 
			
		||||
	// embedded in the struct (as is the case for basic types in proto3).
 | 
			
		||||
	// The possible values are:
 | 
			
		||||
	// 	0: invalid
 | 
			
		||||
	//	1: bool
 | 
			
		||||
	//	4: int32, uint32, float32
 | 
			
		||||
	//	8: int64, uint64, float64
 | 
			
		||||
	basicWidth int
 | 
			
		||||
 | 
			
		||||
	// Where dst and src are pointers to the types being merged.
 | 
			
		||||
	merge func(dst, src pointer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mergeInfoMap  = map[reflect.Type]*mergeInfo{}
 | 
			
		||||
	mergeInfoLock sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getMergeInfo(t reflect.Type) *mergeInfo {
 | 
			
		||||
	mergeInfoLock.Lock()
 | 
			
		||||
	defer mergeInfoLock.Unlock()
 | 
			
		||||
	mi := mergeInfoMap[t]
 | 
			
		||||
	if mi == nil {
 | 
			
		||||
		mi = &mergeInfo{typ: t}
 | 
			
		||||
		mergeInfoMap[t] = mi
 | 
			
		||||
	}
 | 
			
		||||
	return mi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// merge merges src into dst assuming they are both of type *mi.typ.
 | 
			
		||||
func (mi *mergeInfo) merge(dst, src pointer) {
 | 
			
		||||
	if dst.isNil() {
 | 
			
		||||
		panic("proto: nil destination")
 | 
			
		||||
	}
 | 
			
		||||
	if src.isNil() {
 | 
			
		||||
		return // Nothing to do.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if atomic.LoadInt32(&mi.initialized) == 0 {
 | 
			
		||||
		mi.computeMergeInfo()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, fi := range mi.fields {
 | 
			
		||||
		sfp := src.offset(fi.field)
 | 
			
		||||
 | 
			
		||||
		// As an optimization, we can avoid the merge function call cost
 | 
			
		||||
		// if we know for sure that the source will have no effect
 | 
			
		||||
		// by checking if it is the zero value.
 | 
			
		||||
		if unsafeAllowed {
 | 
			
		||||
			if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if fi.basicWidth > 0 {
 | 
			
		||||
				switch {
 | 
			
		||||
				case fi.basicWidth == 1 && !*sfp.toBool():
 | 
			
		||||
					continue
 | 
			
		||||
				case fi.basicWidth == 4 && *sfp.toUint32() == 0:
 | 
			
		||||
					continue
 | 
			
		||||
				case fi.basicWidth == 8 && *sfp.toUint64() == 0:
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dfp := dst.offset(fi.field)
 | 
			
		||||
		fi.merge(dfp, sfp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: Make this faster?
 | 
			
		||||
	out := dst.asPointerTo(mi.typ).Elem()
 | 
			
		||||
	in := src.asPointerTo(mi.typ).Elem()
 | 
			
		||||
	if emIn, err := extendable(in.Addr().Interface()); err == nil {
 | 
			
		||||
		emOut, _ := extendable(out.Addr().Interface())
 | 
			
		||||
		mIn, muIn := emIn.extensionsRead()
 | 
			
		||||
		if mIn != nil {
 | 
			
		||||
			mOut := emOut.extensionsWrite()
 | 
			
		||||
			muIn.Lock()
 | 
			
		||||
			mergeExtension(mOut, mIn)
 | 
			
		||||
			muIn.Unlock()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mi.unrecognized.IsValid() {
 | 
			
		||||
		if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
 | 
			
		||||
			*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mi *mergeInfo) computeMergeInfo() {
 | 
			
		||||
	mi.lock.Lock()
 | 
			
		||||
	defer mi.lock.Unlock()
 | 
			
		||||
	if mi.initialized != 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := mi.typ
 | 
			
		||||
	n := t.NumField()
 | 
			
		||||
 | 
			
		||||
	props := GetProperties(t)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mfi := mergeFieldInfo{field: toField(&f)}
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// As an optimization, we can avoid the merge function call cost
 | 
			
		||||
		// if we know for sure that the source will have no effect
 | 
			
		||||
		// by checking if it is the zero value.
 | 
			
		||||
		if unsafeAllowed {
 | 
			
		||||
			switch tf.Kind() {
 | 
			
		||||
			case reflect.Ptr, reflect.Slice, reflect.String:
 | 
			
		||||
				// As a special case, we assume slices and strings are pointers
 | 
			
		||||
				// since we know that the first field in the SliceSlice or
 | 
			
		||||
				// StringHeader is a data pointer.
 | 
			
		||||
				mfi.isPointer = true
 | 
			
		||||
			case reflect.Bool:
 | 
			
		||||
				mfi.basicWidth = 1
 | 
			
		||||
			case reflect.Int32, reflect.Uint32, reflect.Float32:
 | 
			
		||||
				mfi.basicWidth = 4
 | 
			
		||||
			case reflect.Int64, reflect.Uint64, reflect.Float64:
 | 
			
		||||
				mfi.basicWidth = 8
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get at its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic("both pointer and slice for basic type in " + tf.Name())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Int32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
 | 
			
		||||
					/*
 | 
			
		||||
						sfsp := src.toInt32Slice()
 | 
			
		||||
						if *sfsp != nil {
 | 
			
		||||
							dfsp := dst.toInt32Slice()
 | 
			
		||||
							*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
							if *dfsp == nil {
 | 
			
		||||
								*dfsp = []int64{}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					*/
 | 
			
		||||
					sfs := src.getInt32Slice()
 | 
			
		||||
					if sfs != nil {
 | 
			
		||||
						dfs := dst.getInt32Slice()
 | 
			
		||||
						dfs = append(dfs, sfs...)
 | 
			
		||||
						if dfs == nil {
 | 
			
		||||
							dfs = []int32{}
 | 
			
		||||
						}
 | 
			
		||||
						dst.setInt32Slice(dfs)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
 | 
			
		||||
					/*
 | 
			
		||||
						sfpp := src.toInt32Ptr()
 | 
			
		||||
						if *sfpp != nil {
 | 
			
		||||
							dfpp := dst.toInt32Ptr()
 | 
			
		||||
							if *dfpp == nil {
 | 
			
		||||
								*dfpp = Int32(**sfpp)
 | 
			
		||||
							} else {
 | 
			
		||||
								**dfpp = **sfpp
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					*/
 | 
			
		||||
					sfp := src.getInt32Ptr()
 | 
			
		||||
					if sfp != nil {
 | 
			
		||||
						dfp := dst.getInt32Ptr()
 | 
			
		||||
						if dfp == nil {
 | 
			
		||||
							dst.setInt32Ptr(*sfp)
 | 
			
		||||
						} else {
 | 
			
		||||
							*dfp = *sfp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toInt32(); v != 0 {
 | 
			
		||||
						*dst.toInt32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Int64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toInt64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toInt64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []int64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toInt64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toInt64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Int64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toInt64(); v != 0 {
 | 
			
		||||
						*dst.toInt64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Uint32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toUint32Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toUint32Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []uint32{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toUint32Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toUint32Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Uint32(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toUint32(); v != 0 {
 | 
			
		||||
						*dst.toUint32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Uint64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toUint64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toUint64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []uint64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toUint64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toUint64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Uint64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toUint64(); v != 0 {
 | 
			
		||||
						*dst.toUint64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Float32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toFloat32Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toFloat32Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []float32{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toFloat32Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toFloat32Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Float32(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toFloat32(); v != 0 {
 | 
			
		||||
						*dst.toFloat32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Float64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toFloat64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toFloat64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []float64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toFloat64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toFloat64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Float64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toFloat64(); v != 0 {
 | 
			
		||||
						*dst.toFloat64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toBoolSlice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toBoolSlice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []bool{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toBoolPtr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toBoolPtr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Bool(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toBool(); v {
 | 
			
		||||
						*dst.toBool() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toStringSlice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toStringSlice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []string{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toStringPtr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toStringPtr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = String(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toString(); v != "" {
 | 
			
		||||
						*dst.toString() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Slice:
 | 
			
		||||
			isProto3 := props.Prop[i].proto3
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer:
 | 
			
		||||
				panic("bad pointer in byte slice case in " + tf.Name())
 | 
			
		||||
			case tf.Elem().Kind() != reflect.Uint8:
 | 
			
		||||
				panic("bad element kind in byte slice case in " + tf.Name())
 | 
			
		||||
			case isSlice: // E.g., [][]byte
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sbsp := src.toBytesSlice()
 | 
			
		||||
					if *sbsp != nil {
 | 
			
		||||
						dbsp := dst.toBytesSlice()
 | 
			
		||||
						for _, sb := range *sbsp {
 | 
			
		||||
							if sb == nil {
 | 
			
		||||
								*dbsp = append(*dbsp, nil)
 | 
			
		||||
							} else {
 | 
			
		||||
								*dbsp = append(*dbsp, append([]byte{}, sb...))
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						if *dbsp == nil {
 | 
			
		||||
							*dbsp = [][]byte{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., []byte
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sbp := src.toBytes()
 | 
			
		||||
					if *sbp != nil {
 | 
			
		||||
						dbp := dst.toBytes()
 | 
			
		||||
						if !isProto3 || len(*sbp) > 0 {
 | 
			
		||||
							*dbp = append([]byte{}, *sbp...)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				mergeInfo := getMergeInfo(tf)
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					mergeInfo.merge(dst, src)
 | 
			
		||||
				}
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				mergeInfo := getMergeInfo(tf)
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sps := src.getPointerSlice()
 | 
			
		||||
					if sps != nil {
 | 
			
		||||
						dps := dst.getPointerSlice()
 | 
			
		||||
						for _, sp := range sps {
 | 
			
		||||
							var dp pointer
 | 
			
		||||
							if !sp.isNil() {
 | 
			
		||||
								dp = valToPointer(reflect.New(tf))
 | 
			
		||||
								mergeInfo.merge(dp, sp)
 | 
			
		||||
							}
 | 
			
		||||
							dps = append(dps, dp)
 | 
			
		||||
						}
 | 
			
		||||
						if dps == nil {
 | 
			
		||||
							dps = []pointer{}
 | 
			
		||||
						}
 | 
			
		||||
						dst.setPointerSlice(dps)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				mergeInfo := getMergeInfo(tf)
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sp := src.getPointer()
 | 
			
		||||
					if !sp.isNil() {
 | 
			
		||||
						dp := dst.getPointer()
 | 
			
		||||
						if dp.isNil() {
 | 
			
		||||
							dp = valToPointer(reflect.New(tf))
 | 
			
		||||
							dst.setPointer(dp)
 | 
			
		||||
						}
 | 
			
		||||
						mergeInfo.merge(dp, sp)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic("bad pointer or slice in map case in " + tf.Name())
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sm := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if sm.Len() == 0 {
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					dm := dst.asPointerTo(tf).Elem()
 | 
			
		||||
					if dm.IsNil() {
 | 
			
		||||
						dm.Set(reflect.MakeMap(tf))
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					switch tf.Elem().Kind() {
 | 
			
		||||
					case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							val = reflect.ValueOf(Clone(val.Interface().(Message)))
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					case reflect.Slice: // E.g. Bytes type (e.g., []byte)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					default: // Basic type (e.g., string)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic("bad pointer or slice in interface case in " + tf.Name())
 | 
			
		||||
			default: // E.g., interface{}
 | 
			
		||||
				// TODO: Make this faster?
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					su := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if !su.IsNil() {
 | 
			
		||||
						du := dst.asPointerTo(tf).Elem()
 | 
			
		||||
						typ := su.Elem().Type()
 | 
			
		||||
						if du.IsNil() || du.Elem().Type() != typ {
 | 
			
		||||
							du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
 | 
			
		||||
						}
 | 
			
		||||
						sv := su.Elem().Elem().Field(0)
 | 
			
		||||
						if sv.Kind() == reflect.Ptr && sv.IsNil() {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						dv := du.Elem().Elem().Field(0)
 | 
			
		||||
						if dv.Kind() == reflect.Ptr && dv.IsNil() {
 | 
			
		||||
							dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
 | 
			
		||||
						}
 | 
			
		||||
						switch sv.Type().Kind() {
 | 
			
		||||
						case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
							Merge(dv.Interface().(Message), sv.Interface().(Message))
 | 
			
		||||
						case reflect.Slice: // E.g. Bytes type (e.g., []byte)
 | 
			
		||||
							dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
 | 
			
		||||
						default: // Basic type (e.g., string)
 | 
			
		||||
							dv.Set(sv)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			panic(fmt.Sprintf("merger not found for type:%s", tf))
 | 
			
		||||
		}
 | 
			
		||||
		mi.fields = append(mi.fields, mfi)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mi.unrecognized = invalidField
 | 
			
		||||
	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
 | 
			
		||||
		if f.Type != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		mi.unrecognized = toField(&f)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atomic.StoreInt32(&mi.initialized, 1)
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,385 @@
 | 
			
		|||
// 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalMessage(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		// First read the message field to see if something is there.
 | 
			
		||||
		// The semantics of multiple submessages are weird.  Instead of
 | 
			
		||||
		// the last one winning (as it is for all other fields), multiple
 | 
			
		||||
		// submessages are merged.
 | 
			
		||||
		v := f // gogo: changed from v := f.getPointer()
 | 
			
		||||
		if v.isNil() {
 | 
			
		||||
			v = valToPointer(reflect.New(sub.typ))
 | 
			
		||||
			f.setPointer(v)
 | 
			
		||||
		}
 | 
			
		||||
		err := sub.unmarshal(v, b[:x])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if r, ok := err.(*RequiredNotSetError); ok {
 | 
			
		||||
				r.field = name + "." + r.field
 | 
			
		||||
			} else {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return b[x:], err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalMessageSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, 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 := valToPointer(reflect.New(sub.typ))
 | 
			
		||||
		err := sub.unmarshal(v, b[:x])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if r, ok := err.(*RequiredNotSetError); ok {
 | 
			
		||||
				r.field = name + "." + r.field
 | 
			
		||||
			} else {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		f.appendRef(v, sub.typ) // gogo: changed from f.appendPointer(v)
 | 
			
		||||
		return b[x:], err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalCustomPtr(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
 | 
			
		||||
		s.Set(reflect.New(sub.typ))
 | 
			
		||||
		m := s.Interface().(custom)
 | 
			
		||||
		if err := m.Unmarshal(b[:x]); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalCustomSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := reflect.New(sub.typ)
 | 
			
		||||
		c := m.Interface().(custom)
 | 
			
		||||
		if err := c.Unmarshal(b[:x]); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		v := valToPointer(m)
 | 
			
		||||
		f.appendRef(v, sub.typ)
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalCustom(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m := f.asPointerTo(sub.typ).Interface().(custom)
 | 
			
		||||
		if err := m.Unmarshal(b[:x]); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalTime(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := ×tamp{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		t, err := timestampFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		s := f.asPointerTo(sub.typ).Elem()
 | 
			
		||||
		s.Set(reflect.ValueOf(t))
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalTimePtr(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := ×tamp{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		t, err := timestampFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
 | 
			
		||||
		s.Set(reflect.ValueOf(&t))
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalTimePtrSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := ×tamp{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		t, err := timestampFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		slice := f.getSlice(reflect.PtrTo(sub.typ))
 | 
			
		||||
		newSlice := reflect.Append(slice, reflect.ValueOf(&t))
 | 
			
		||||
		slice.Set(newSlice)
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalTimeSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := ×tamp{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		t, err := timestampFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		slice := f.getSlice(sub.typ)
 | 
			
		||||
		newSlice := reflect.Append(slice, reflect.ValueOf(t))
 | 
			
		||||
		slice.Set(newSlice)
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalDurationPtr(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := &duration{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		d, err := durationFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		s := f.asPointerTo(reflect.PtrTo(sub.typ)).Elem()
 | 
			
		||||
		s.Set(reflect.ValueOf(&d))
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalDuration(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := &duration{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		d, err := durationFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		s := f.asPointerTo(sub.typ).Elem()
 | 
			
		||||
		s.Set(reflect.ValueOf(d))
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalDurationPtrSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := &duration{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		d, err := durationFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		slice := f.getSlice(reflect.PtrTo(sub.typ))
 | 
			
		||||
		newSlice := reflect.Append(slice, reflect.ValueOf(&d))
 | 
			
		||||
		slice.Set(newSlice)
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeUnmarshalDurationSlice(sub *unmarshalInfo, name string) unmarshaler {
 | 
			
		||||
	return func(b []byte, f pointer, w int) ([]byte, error) {
 | 
			
		||||
		if w != WireBytes {
 | 
			
		||||
			return nil, errInternalBadWireType
 | 
			
		||||
		}
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		if x > uint64(len(b)) {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		m := &duration{}
 | 
			
		||||
		if err := Unmarshal(b[:x], m); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		d, err := durationFromProto(m)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		slice := f.getSlice(sub.typ)
 | 
			
		||||
		newSlice := reflect.Append(slice, reflect.ValueOf(d))
 | 
			
		||||
		slice.Set(newSlice)
 | 
			
		||||
		return b[x:], nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,928 @@
 | 
			
		|||
// 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.
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
// Functions for writing the text protocol buffer format.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	newline         = []byte("\n")
 | 
			
		||||
	spaces          = []byte("                                        ")
 | 
			
		||||
	endBraceNewline = []byte("}\n")
 | 
			
		||||
	backslashN      = []byte{'\\', 'n'}
 | 
			
		||||
	backslashR      = []byte{'\\', 'r'}
 | 
			
		||||
	backslashT      = []byte{'\\', 't'}
 | 
			
		||||
	backslashDQ     = []byte{'\\', '"'}
 | 
			
		||||
	backslashBS     = []byte{'\\', '\\'}
 | 
			
		||||
	posInf          = []byte("inf")
 | 
			
		||||
	negInf          = []byte("-inf")
 | 
			
		||||
	nan             = []byte("nan")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type writer interface {
 | 
			
		||||
	io.Writer
 | 
			
		||||
	WriteByte(byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// textWriter is an io.Writer that tracks its indentation level.
 | 
			
		||||
type textWriter struct {
 | 
			
		||||
	ind      int
 | 
			
		||||
	complete bool // if the current position is a complete line
 | 
			
		||||
	compact  bool // whether to write out as a one-liner
 | 
			
		||||
	w        writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) WriteString(s string) (n int, err error) {
 | 
			
		||||
	if !strings.Contains(s, "\n") {
 | 
			
		||||
		if !w.compact && w.complete {
 | 
			
		||||
			w.writeIndent()
 | 
			
		||||
		}
 | 
			
		||||
		w.complete = false
 | 
			
		||||
		return io.WriteString(w.w, s)
 | 
			
		||||
	}
 | 
			
		||||
	// WriteString is typically called without newlines, so this
 | 
			
		||||
	// codepath and its copy are rare.  We copy to avoid
 | 
			
		||||
	// duplicating all of Write's logic here.
 | 
			
		||||
	return w.Write([]byte(s))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) Write(p []byte) (n int, err error) {
 | 
			
		||||
	newlines := bytes.Count(p, newline)
 | 
			
		||||
	if newlines == 0 {
 | 
			
		||||
		if !w.compact && w.complete {
 | 
			
		||||
			w.writeIndent()
 | 
			
		||||
		}
 | 
			
		||||
		n, err = w.w.Write(p)
 | 
			
		||||
		w.complete = false
 | 
			
		||||
		return n, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frags := bytes.SplitN(p, newline, newlines+1)
 | 
			
		||||
	if w.compact {
 | 
			
		||||
		for i, frag := range frags {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				if err := w.w.WriteByte(' '); err != nil {
 | 
			
		||||
					return n, err
 | 
			
		||||
				}
 | 
			
		||||
				n++
 | 
			
		||||
			}
 | 
			
		||||
			nn, err := w.w.Write(frag)
 | 
			
		||||
			n += nn
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return n, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return n, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, frag := range frags {
 | 
			
		||||
		if w.complete {
 | 
			
		||||
			w.writeIndent()
 | 
			
		||||
		}
 | 
			
		||||
		nn, err := w.w.Write(frag)
 | 
			
		||||
		n += nn
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return n, err
 | 
			
		||||
		}
 | 
			
		||||
		if i+1 < len(frags) {
 | 
			
		||||
			if err := w.w.WriteByte('\n'); err != nil {
 | 
			
		||||
				return n, err
 | 
			
		||||
			}
 | 
			
		||||
			n++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	w.complete = len(frags[len(frags)-1]) == 0
 | 
			
		||||
	return n, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) WriteByte(c byte) error {
 | 
			
		||||
	if w.compact && c == '\n' {
 | 
			
		||||
		c = ' '
 | 
			
		||||
	}
 | 
			
		||||
	if !w.compact && w.complete {
 | 
			
		||||
		w.writeIndent()
 | 
			
		||||
	}
 | 
			
		||||
	err := w.w.WriteByte(c)
 | 
			
		||||
	w.complete = c == '\n'
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) indent() { w.ind++ }
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) unindent() {
 | 
			
		||||
	if w.ind == 0 {
 | 
			
		||||
		log.Print("proto: textWriter unindented too far")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	w.ind--
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeName(w *textWriter, props *Properties) error {
 | 
			
		||||
	if _, err := w.WriteString(props.OrigName); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if props.Wire != "group" {
 | 
			
		||||
		return w.WriteByte(':')
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func requiresQuotes(u string) bool {
 | 
			
		||||
	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
 | 
			
		||||
	for _, ch := range u {
 | 
			
		||||
		switch {
 | 
			
		||||
		case ch == '.' || ch == '/' || ch == '_':
 | 
			
		||||
			continue
 | 
			
		||||
		case '0' <= ch && ch <= '9':
 | 
			
		||||
			continue
 | 
			
		||||
		case 'A' <= ch && ch <= 'Z':
 | 
			
		||||
			continue
 | 
			
		||||
		case 'a' <= ch && ch <= 'z':
 | 
			
		||||
			continue
 | 
			
		||||
		default:
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isAny reports whether sv is a google.protobuf.Any message
 | 
			
		||||
func isAny(sv reflect.Value) bool {
 | 
			
		||||
	type wkt interface {
 | 
			
		||||
		XXX_WellKnownType() string
 | 
			
		||||
	}
 | 
			
		||||
	t, ok := sv.Addr().Interface().(wkt)
 | 
			
		||||
	return ok && t.XXX_WellKnownType() == "Any"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeProto3Any writes an expanded google.protobuf.Any message.
 | 
			
		||||
//
 | 
			
		||||
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
 | 
			
		||||
// required messages are not linked in).
 | 
			
		||||
//
 | 
			
		||||
// It returns (true, error) when sv was written in expanded format or an error
 | 
			
		||||
// was encountered.
 | 
			
		||||
func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
 | 
			
		||||
	turl := sv.FieldByName("TypeUrl")
 | 
			
		||||
	val := sv.FieldByName("Value")
 | 
			
		||||
	if !turl.IsValid() || !val.IsValid() {
 | 
			
		||||
		return true, errors.New("proto: invalid google.protobuf.Any message")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, ok := val.Interface().([]byte)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return true, errors.New("proto: invalid google.protobuf.Any message")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts := strings.Split(turl.String(), "/")
 | 
			
		||||
	mt := MessageType(parts[len(parts)-1])
 | 
			
		||||
	if mt == nil {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	m := reflect.New(mt.Elem())
 | 
			
		||||
	if err := Unmarshal(b, m.Interface().(Message)); err != nil {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	w.Write([]byte("["))
 | 
			
		||||
	u := turl.String()
 | 
			
		||||
	if requiresQuotes(u) {
 | 
			
		||||
		writeString(w, u)
 | 
			
		||||
	} else {
 | 
			
		||||
		w.Write([]byte(u))
 | 
			
		||||
	}
 | 
			
		||||
	if w.compact {
 | 
			
		||||
		w.Write([]byte("]:<"))
 | 
			
		||||
	} else {
 | 
			
		||||
		w.Write([]byte("]: <\n"))
 | 
			
		||||
		w.ind++
 | 
			
		||||
	}
 | 
			
		||||
	if err := tm.writeStruct(w, m.Elem()); err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
	}
 | 
			
		||||
	if w.compact {
 | 
			
		||||
		w.Write([]byte("> "))
 | 
			
		||||
	} else {
 | 
			
		||||
		w.ind--
 | 
			
		||||
		w.Write([]byte(">\n"))
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		||||
	if tm.ExpandAny && isAny(sv) {
 | 
			
		||||
		if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	st := sv.Type()
 | 
			
		||||
	sprops := GetProperties(st)
 | 
			
		||||
	for i := 0; i < sv.NumField(); i++ {
 | 
			
		||||
		fv := sv.Field(i)
 | 
			
		||||
		props := sprops.Prop[i]
 | 
			
		||||
		name := st.Field(i).Name
 | 
			
		||||
 | 
			
		||||
		if name == "XXX_NoUnkeyedLiteral" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if strings.HasPrefix(name, "XXX_") {
 | 
			
		||||
			// There are two XXX_ fields:
 | 
			
		||||
			//   XXX_unrecognized []byte
 | 
			
		||||
			//   XXX_extensions   map[int32]proto.Extension
 | 
			
		||||
			// The first is handled here;
 | 
			
		||||
			// the second is handled at the bottom of this function.
 | 
			
		||||
			if name == "XXX_unrecognized" && !fv.IsNil() {
 | 
			
		||||
				if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if fv.Kind() == reflect.Ptr && fv.IsNil() {
 | 
			
		||||
			// Field not filled in. This could be an optional field or
 | 
			
		||||
			// a required field that wasn't filled in. Either way, there
 | 
			
		||||
			// isn't anything we can show for it.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if fv.Kind() == reflect.Slice && fv.IsNil() {
 | 
			
		||||
			// Repeated field that is empty, or a bytes field that is unused.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if props.Repeated && fv.Kind() == reflect.Slice {
 | 
			
		||||
			// Repeated field.
 | 
			
		||||
			for j := 0; j < fv.Len(); j++ {
 | 
			
		||||
				if err := writeName(w, props); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if !w.compact {
 | 
			
		||||
					if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				v := fv.Index(j)
 | 
			
		||||
				if v.Kind() == reflect.Ptr && v.IsNil() {
 | 
			
		||||
					// A nil message in a repeated field is not valid,
 | 
			
		||||
					// but we can handle that more gracefully than panicking.
 | 
			
		||||
					if _, err := w.Write([]byte("<nil>\n")); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				if len(props.Enum) > 0 {
 | 
			
		||||
					if err := tm.writeEnum(w, v, props); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				} else if err := tm.writeAny(w, v, props); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if fv.Kind() == reflect.Map {
 | 
			
		||||
			// Map fields are rendered as a repeated struct with key/value fields.
 | 
			
		||||
			keys := fv.MapKeys()
 | 
			
		||||
			sort.Sort(mapKeys(keys))
 | 
			
		||||
			for _, key := range keys {
 | 
			
		||||
				val := fv.MapIndex(key)
 | 
			
		||||
				if err := writeName(w, props); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if !w.compact {
 | 
			
		||||
					if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				// open struct
 | 
			
		||||
				if err := w.WriteByte('<'); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if !w.compact {
 | 
			
		||||
					if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				w.indent()
 | 
			
		||||
				// key
 | 
			
		||||
				if _, err := w.WriteString("key:"); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if !w.compact {
 | 
			
		||||
					if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				// nil values aren't legal, but we can avoid panicking because of them.
 | 
			
		||||
				if val.Kind() != reflect.Ptr || !val.IsNil() {
 | 
			
		||||
					// value
 | 
			
		||||
					if _, err := w.WriteString("value:"); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if !w.compact {
 | 
			
		||||
						if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
							return err
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if err := tm.writeAny(w, val, props.mvalprop); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				// close struct
 | 
			
		||||
				w.unindent()
 | 
			
		||||
				if err := w.WriteByte('>'); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
 | 
			
		||||
			// empty bytes field
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
 | 
			
		||||
			// proto3 non-repeated scalar field; skip if zero value
 | 
			
		||||
			if isProto3Zero(fv) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if fv.Kind() == reflect.Interface {
 | 
			
		||||
			// Check if it is a oneof.
 | 
			
		||||
			if st.Field(i).Tag.Get("protobuf_oneof") != "" {
 | 
			
		||||
				// fv is nil, or holds a pointer to generated struct.
 | 
			
		||||
				// That generated struct has exactly one field,
 | 
			
		||||
				// which has a protobuf struct tag.
 | 
			
		||||
				if fv.IsNil() {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				inner := fv.Elem().Elem() // interface -> *T -> T
 | 
			
		||||
				tag := inner.Type().Field(0).Tag.Get("protobuf")
 | 
			
		||||
				props = new(Properties) // Overwrite the outer props var, but not its pointee.
 | 
			
		||||
				props.Parse(tag)
 | 
			
		||||
				// Write the value in the oneof, not the oneof itself.
 | 
			
		||||
				fv = inner.Field(0)
 | 
			
		||||
 | 
			
		||||
				// Special case to cope with malformed messages gracefully:
 | 
			
		||||
				// If the value in the oneof is a nil pointer, don't panic
 | 
			
		||||
				// in writeAny.
 | 
			
		||||
				if fv.Kind() == reflect.Ptr && fv.IsNil() {
 | 
			
		||||
					// Use errors.New so writeAny won't render quotes.
 | 
			
		||||
					msg := errors.New("/* nil */")
 | 
			
		||||
					fv = reflect.ValueOf(&msg).Elem()
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := writeName(w, props); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if !w.compact {
 | 
			
		||||
			if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if len(props.Enum) > 0 {
 | 
			
		||||
			if err := tm.writeEnum(w, fv, props); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else if err := tm.writeAny(w, fv, props); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Extensions (the XXX_extensions field).
 | 
			
		||||
	pv := sv
 | 
			
		||||
	if pv.CanAddr() {
 | 
			
		||||
		pv = sv.Addr()
 | 
			
		||||
	} else {
 | 
			
		||||
		pv = reflect.New(sv.Type())
 | 
			
		||||
		pv.Elem().Set(sv)
 | 
			
		||||
	}
 | 
			
		||||
	if _, err := extendable(pv.Interface()); err == nil {
 | 
			
		||||
		if err := tm.writeExtensions(w, pv); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeAny writes an arbitrary field.
 | 
			
		||||
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
 | 
			
		||||
	v = reflect.Indirect(v)
 | 
			
		||||
 | 
			
		||||
	if props != nil {
 | 
			
		||||
		if len(props.CustomType) > 0 {
 | 
			
		||||
			custom, ok := v.Interface().(Marshaler)
 | 
			
		||||
			if ok {
 | 
			
		||||
				data, err := custom.Marshal()
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if err := writeString(w, string(data)); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		} else if len(props.CastType) > 0 {
 | 
			
		||||
			if _, ok := v.Interface().(interface {
 | 
			
		||||
				String() string
 | 
			
		||||
			}); ok {
 | 
			
		||||
				switch v.Kind() {
 | 
			
		||||
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
 | 
			
		||||
					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
					_, err := fmt.Fprintf(w, "%d", v.Interface())
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else if props.StdTime {
 | 
			
		||||
			t, ok := v.Interface().(time.Time)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface())
 | 
			
		||||
			}
 | 
			
		||||
			tproto, err := timestampProto(t)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			propsCopy := *props // Make a copy so that this is goroutine-safe
 | 
			
		||||
			propsCopy.StdTime = false
 | 
			
		||||
			err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy)
 | 
			
		||||
			return err
 | 
			
		||||
		} else if props.StdDuration {
 | 
			
		||||
			d, ok := v.Interface().(time.Duration)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface())
 | 
			
		||||
			}
 | 
			
		||||
			dproto := durationProto(d)
 | 
			
		||||
			propsCopy := *props // Make a copy so that this is goroutine-safe
 | 
			
		||||
			propsCopy.StdDuration = false
 | 
			
		||||
			err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Floats have special cases.
 | 
			
		||||
	if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
 | 
			
		||||
		x := v.Float()
 | 
			
		||||
		var b []byte
 | 
			
		||||
		switch {
 | 
			
		||||
		case math.IsInf(x, 1):
 | 
			
		||||
			b = posInf
 | 
			
		||||
		case math.IsInf(x, -1):
 | 
			
		||||
			b = negInf
 | 
			
		||||
		case math.IsNaN(x):
 | 
			
		||||
			b = nan
 | 
			
		||||
		}
 | 
			
		||||
		if b != nil {
 | 
			
		||||
			_, err := w.Write(b)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		// Other values are handled below.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We don't attempt to serialise every possible value type; only those
 | 
			
		||||
	// that can occur in protocol buffers.
 | 
			
		||||
	switch v.Kind() {
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		// Should only be a []byte; repeated fields are handled in writeStruct.
 | 
			
		||||
		if err := writeString(w, string(v.Bytes())); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		if err := writeString(w, v.String()); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		// Required/optional group/message.
 | 
			
		||||
		var bra, ket byte = '<', '>'
 | 
			
		||||
		if props != nil && props.Wire == "group" {
 | 
			
		||||
			bra, ket = '{', '}'
 | 
			
		||||
		}
 | 
			
		||||
		if err := w.WriteByte(bra); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if !w.compact {
 | 
			
		||||
			if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		w.indent()
 | 
			
		||||
		if v.CanAddr() {
 | 
			
		||||
			// Calling v.Interface on a struct causes the reflect package to
 | 
			
		||||
			// copy the entire struct. This is racy with the new Marshaler
 | 
			
		||||
			// since we atomically update the XXX_sizecache.
 | 
			
		||||
			//
 | 
			
		||||
			// Thus, we retrieve a pointer to the struct if possible to avoid
 | 
			
		||||
			// a race since v.Interface on the pointer doesn't copy the struct.
 | 
			
		||||
			//
 | 
			
		||||
			// If v is not addressable, then we are not worried about a race
 | 
			
		||||
			// since it implies that the binary Marshaler cannot possibly be
 | 
			
		||||
			// mutating this value.
 | 
			
		||||
			v = v.Addr()
 | 
			
		||||
		}
 | 
			
		||||
		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
 | 
			
		||||
			text, err := etm.MarshalText()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if _, err = w.Write(text); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if v.Kind() == reflect.Ptr {
 | 
			
		||||
				v = v.Elem()
 | 
			
		||||
			}
 | 
			
		||||
			if err := tm.writeStruct(w, v); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		w.unindent()
 | 
			
		||||
		if err := w.WriteByte(ket); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		_, err := fmt.Fprint(w, v.Interface())
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// equivalent to C's isprint.
 | 
			
		||||
func isprint(c byte) bool {
 | 
			
		||||
	return c >= 0x20 && c < 0x7f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeString writes a string in the protocol buffer text format.
 | 
			
		||||
// It is similar to strconv.Quote except we don't use Go escape sequences,
 | 
			
		||||
// we treat the string as a byte sequence, and we use octal escapes.
 | 
			
		||||
// These differences are to maintain interoperability with the other
 | 
			
		||||
// languages' implementations of the text format.
 | 
			
		||||
func writeString(w *textWriter, s string) error {
 | 
			
		||||
	// use WriteByte here to get any needed indent
 | 
			
		||||
	if err := w.WriteByte('"'); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Loop over the bytes, not the runes.
 | 
			
		||||
	for i := 0; i < len(s); i++ {
 | 
			
		||||
		var err error
 | 
			
		||||
		// Divergence from C++: we don't escape apostrophes.
 | 
			
		||||
		// There's no need to escape them, and the C++ parser
 | 
			
		||||
		// copes with a naked apostrophe.
 | 
			
		||||
		switch c := s[i]; c {
 | 
			
		||||
		case '\n':
 | 
			
		||||
			_, err = w.w.Write(backslashN)
 | 
			
		||||
		case '\r':
 | 
			
		||||
			_, err = w.w.Write(backslashR)
 | 
			
		||||
		case '\t':
 | 
			
		||||
			_, err = w.w.Write(backslashT)
 | 
			
		||||
		case '"':
 | 
			
		||||
			_, err = w.w.Write(backslashDQ)
 | 
			
		||||
		case '\\':
 | 
			
		||||
			_, err = w.w.Write(backslashBS)
 | 
			
		||||
		default:
 | 
			
		||||
			if isprint(c) {
 | 
			
		||||
				err = w.w.WriteByte(c)
 | 
			
		||||
			} else {
 | 
			
		||||
				_, err = fmt.Fprintf(w.w, "\\%03o", c)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return w.WriteByte('"')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
 | 
			
		||||
	if !w.compact {
 | 
			
		||||
		if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	b := NewBuffer(data)
 | 
			
		||||
	for b.index < len(b.buf) {
 | 
			
		||||
		x, err := b.DecodeVarint()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_, ferr := fmt.Fprintf(w, "/* %v */\n", err)
 | 
			
		||||
			return ferr
 | 
			
		||||
		}
 | 
			
		||||
		wire, tag := x&7, x>>3
 | 
			
		||||
		if wire == WireEndGroup {
 | 
			
		||||
			w.unindent()
 | 
			
		||||
			if _, werr := w.Write(endBraceNewline); werr != nil {
 | 
			
		||||
				return werr
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if _, ferr := fmt.Fprint(w, tag); ferr != nil {
 | 
			
		||||
			return ferr
 | 
			
		||||
		}
 | 
			
		||||
		if wire != WireStartGroup {
 | 
			
		||||
			if err = w.WriteByte(':'); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !w.compact || wire == WireStartGroup {
 | 
			
		||||
			if err = w.WriteByte(' '); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		switch wire {
 | 
			
		||||
		case WireBytes:
 | 
			
		||||
			buf, e := b.DecodeRawBytes(false)
 | 
			
		||||
			if e == nil {
 | 
			
		||||
				_, err = fmt.Fprintf(w, "%q", buf)
 | 
			
		||||
			} else {
 | 
			
		||||
				_, err = fmt.Fprintf(w, "/* %v */", e)
 | 
			
		||||
			}
 | 
			
		||||
		case WireFixed32:
 | 
			
		||||
			x, err = b.DecodeFixed32()
 | 
			
		||||
			err = writeUnknownInt(w, x, err)
 | 
			
		||||
		case WireFixed64:
 | 
			
		||||
			x, err = b.DecodeFixed64()
 | 
			
		||||
			err = writeUnknownInt(w, x, err)
 | 
			
		||||
		case WireStartGroup:
 | 
			
		||||
			err = w.WriteByte('{')
 | 
			
		||||
			w.indent()
 | 
			
		||||
		case WireVarint:
 | 
			
		||||
			x, err = b.DecodeVarint()
 | 
			
		||||
			err = writeUnknownInt(w, x, err)
 | 
			
		||||
		default:
 | 
			
		||||
			_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeUnknownInt(w *textWriter, x uint64, err error) error {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		_, err = fmt.Fprint(w, x)
 | 
			
		||||
	} else {
 | 
			
		||||
		_, err = fmt.Fprintf(w, "/* %v */", err)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type int32Slice []int32
 | 
			
		||||
 | 
			
		||||
func (s int32Slice) Len() int           { return len(s) }
 | 
			
		||||
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
 | 
			
		||||
func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 | 
			
		||||
 | 
			
		||||
// writeExtensions writes all the extensions in pv.
 | 
			
		||||
// pv is assumed to be a pointer to a protocol message struct that is extendable.
 | 
			
		||||
func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
 | 
			
		||||
	emap := extensionMaps[pv.Type().Elem()]
 | 
			
		||||
	e := pv.Interface().(Message)
 | 
			
		||||
 | 
			
		||||
	var m map[int32]Extension
 | 
			
		||||
	var mu sync.Locker
 | 
			
		||||
	if em, ok := e.(extensionsBytes); ok {
 | 
			
		||||
		eb := em.GetExtensions()
 | 
			
		||||
		var err error
 | 
			
		||||
		m, err = BytesToExtensionsMap(*eb)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		mu = notLocker{}
 | 
			
		||||
	} else if _, ok := e.(extendableProto); ok {
 | 
			
		||||
		ep, _ := extendable(e)
 | 
			
		||||
		m, mu = ep.extensionsRead()
 | 
			
		||||
		if m == nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Order the extensions by ID.
 | 
			
		||||
	// This isn't strictly necessary, but it will give us
 | 
			
		||||
	// canonical output, which will also make testing easier.
 | 
			
		||||
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	ids := make([]int32, 0, len(m))
 | 
			
		||||
	for id := range m {
 | 
			
		||||
		ids = append(ids, id)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(int32Slice(ids))
 | 
			
		||||
	mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	for _, extNum := range ids {
 | 
			
		||||
		ext := m[extNum]
 | 
			
		||||
		var desc *ExtensionDesc
 | 
			
		||||
		if emap != nil {
 | 
			
		||||
			desc = emap[extNum]
 | 
			
		||||
		}
 | 
			
		||||
		if desc == nil {
 | 
			
		||||
			// Unknown extension.
 | 
			
		||||
			if err := writeUnknownStruct(w, ext.enc); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pb, err := GetExtension(e, desc)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("failed getting extension: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Repeated extensions will appear as a slice.
 | 
			
		||||
		if !desc.repeated() {
 | 
			
		||||
			if err := tm.writeExtension(w, desc.Name, pb); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			v := reflect.ValueOf(pb)
 | 
			
		||||
			for i := 0; i < v.Len(); i++ {
 | 
			
		||||
				if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
 | 
			
		||||
	if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !w.compact {
 | 
			
		||||
		if err := w.WriteByte(' '); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *textWriter) writeIndent() {
 | 
			
		||||
	if !w.complete {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	remain := w.ind * 2
 | 
			
		||||
	for remain > 0 {
 | 
			
		||||
		n := remain
 | 
			
		||||
		if n > len(spaces) {
 | 
			
		||||
			n = len(spaces)
 | 
			
		||||
		}
 | 
			
		||||
		w.w.Write(spaces[:n])
 | 
			
		||||
		remain -= n
 | 
			
		||||
	}
 | 
			
		||||
	w.complete = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TextMarshaler is a configurable text format marshaler.
 | 
			
		||||
type TextMarshaler struct {
 | 
			
		||||
	Compact   bool // use compact text format (one line).
 | 
			
		||||
	ExpandAny bool // expand google.protobuf.Any messages of known types
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshal writes a given protocol buffer in text format.
 | 
			
		||||
// The only errors returned are from w.
 | 
			
		||||
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
 | 
			
		||||
	val := reflect.ValueOf(pb)
 | 
			
		||||
	if pb == nil || val.IsNil() {
 | 
			
		||||
		w.Write([]byte("<nil>"))
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	var bw *bufio.Writer
 | 
			
		||||
	ww, ok := w.(writer)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		bw = bufio.NewWriter(w)
 | 
			
		||||
		ww = bw
 | 
			
		||||
	}
 | 
			
		||||
	aw := &textWriter{
 | 
			
		||||
		w:        ww,
 | 
			
		||||
		complete: true,
 | 
			
		||||
		compact:  tm.Compact,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if etm, ok := pb.(encoding.TextMarshaler); ok {
 | 
			
		||||
		text, err := etm.MarshalText()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if _, err = aw.Write(text); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if bw != nil {
 | 
			
		||||
			return bw.Flush()
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	// Dereference the received pointer so we don't have outer < and >.
 | 
			
		||||
	v := reflect.Indirect(val)
 | 
			
		||||
	if err := tm.writeStruct(aw, v); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if bw != nil {
 | 
			
		||||
		return bw.Flush()
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Text is the same as Marshal, but returns the string directly.
 | 
			
		||||
func (tm *TextMarshaler) Text(pb Message) string {
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	tm.Marshal(&buf, pb)
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	defaultTextMarshaler = TextMarshaler{}
 | 
			
		||||
	compactTextMarshaler = TextMarshaler{Compact: true}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO: consider removing some of the Marshal functions below.
 | 
			
		||||
 | 
			
		||||
// MarshalText writes a given protocol buffer in text format.
 | 
			
		||||
// The only errors returned are from w.
 | 
			
		||||
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
 | 
			
		||||
 | 
			
		||||
// MarshalTextString is the same as MarshalText, but returns the string directly.
 | 
			
		||||
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
 | 
			
		||||
 | 
			
		||||
// CompactText writes a given protocol buffer in compact text format (one line).
 | 
			
		||||
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
 | 
			
		||||
 | 
			
		||||
// CompactTextString is the same as CompactText, but returns the string directly.
 | 
			
		||||
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
 | 
			
		||||
// http://github.com/gogo/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (tm *TextMarshaler) writeEnum(w *textWriter, v reflect.Value, props *Properties) error {
 | 
			
		||||
	m, ok := enumStringMaps[props.Enum]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if err := tm.writeAny(w, v, props); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	key := int32(0)
 | 
			
		||||
	if v.Kind() == reflect.Ptr {
 | 
			
		||||
		key = int32(v.Elem().Int())
 | 
			
		||||
	} else {
 | 
			
		||||
		key = int32(v.Int())
 | 
			
		||||
	}
 | 
			
		||||
	s, ok := m[key]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if err := tm.writeAny(w, v, props); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	_, err := fmt.Fprint(w, s)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2016 The Go Authors.  All rights reserved.
 | 
			
		||||
// https://github.com/golang/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
// contributors may be used to endorse or promote products derived from
 | 
			
		||||
// this software without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
// This file implements operations on google.protobuf.Timestamp.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Seconds field of the earliest valid Timestamp.
 | 
			
		||||
	// This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
 | 
			
		||||
	minValidSeconds = -62135596800
 | 
			
		||||
	// Seconds field just after the latest valid Timestamp.
 | 
			
		||||
	// This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
 | 
			
		||||
	maxValidSeconds = 253402300800
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// validateTimestamp determines whether a Timestamp is valid.
 | 
			
		||||
// A valid timestamp represents a time in the range
 | 
			
		||||
// [0001-01-01, 10000-01-01) and has a Nanos field
 | 
			
		||||
// in the range [0, 1e9).
 | 
			
		||||
//
 | 
			
		||||
// If the Timestamp is valid, validateTimestamp returns nil.
 | 
			
		||||
// Otherwise, it returns an error that describes
 | 
			
		||||
// the problem.
 | 
			
		||||
//
 | 
			
		||||
// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
 | 
			
		||||
func validateTimestamp(ts *timestamp) error {
 | 
			
		||||
	if ts == nil {
 | 
			
		||||
		return errors.New("timestamp: nil Timestamp")
 | 
			
		||||
	}
 | 
			
		||||
	if ts.Seconds < minValidSeconds {
 | 
			
		||||
		return fmt.Errorf("timestamp: %#v before 0001-01-01", ts)
 | 
			
		||||
	}
 | 
			
		||||
	if ts.Seconds >= maxValidSeconds {
 | 
			
		||||
		return fmt.Errorf("timestamp: %#v after 10000-01-01", ts)
 | 
			
		||||
	}
 | 
			
		||||
	if ts.Nanos < 0 || ts.Nanos >= 1e9 {
 | 
			
		||||
		return fmt.Errorf("timestamp: %#v: nanos not in range [0, 1e9)", ts)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TimestampFromProto converts a google.protobuf.Timestamp proto to a time.Time.
 | 
			
		||||
// It returns an error if the argument is invalid.
 | 
			
		||||
//
 | 
			
		||||
// Unlike most Go functions, if Timestamp returns an error, the first return value
 | 
			
		||||
// is not the zero time.Time. Instead, it is the value obtained from the
 | 
			
		||||
// time.Unix function when passed the contents of the Timestamp, in the UTC
 | 
			
		||||
// locale. This may or may not be a meaningful time; many invalid Timestamps
 | 
			
		||||
// do map to valid time.Times.
 | 
			
		||||
//
 | 
			
		||||
// A nil Timestamp returns an error. The first return value in that case is
 | 
			
		||||
// undefined.
 | 
			
		||||
func timestampFromProto(ts *timestamp) (time.Time, error) {
 | 
			
		||||
	// Don't return the zero value on error, because corresponds to a valid
 | 
			
		||||
	// timestamp. Instead return whatever time.Unix gives us.
 | 
			
		||||
	var t time.Time
 | 
			
		||||
	if ts == nil {
 | 
			
		||||
		t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
 | 
			
		||||
	} else {
 | 
			
		||||
		t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
 | 
			
		||||
	}
 | 
			
		||||
	return t, validateTimestamp(ts)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
 | 
			
		||||
// It returns an error if the resulting Timestamp is invalid.
 | 
			
		||||
func timestampProto(t time.Time) (*timestamp, error) {
 | 
			
		||||
	seconds := t.Unix()
 | 
			
		||||
	nanos := int32(t.Sub(time.Unix(seconds, 0)))
 | 
			
		||||
	ts := ×tamp{
 | 
			
		||||
		Seconds: seconds,
 | 
			
		||||
		Nanos:   nanos,
 | 
			
		||||
	}
 | 
			
		||||
	if err := validateTimestamp(ts); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return ts, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
// Protocol Buffers for Go with Gadgets
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2016, 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
 | 
			
		||||
 | 
			
		||||
type timestamp struct {
 | 
			
		||||
	Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
 | 
			
		||||
	Nanos   int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *timestamp) Reset()       { *m = timestamp{} }
 | 
			
		||||
func (*timestamp) ProtoMessage()  {}
 | 
			
		||||
func (*timestamp) String() string { return "timestamp<string>" }
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterType((*timestamp)(nil), "gogo.protobuf.proto.timestamp")
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
// 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")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,4 @@
 | 
			
		|||
Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
 | 
			
		||||
Copyright 2010 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,22 +35,39 @@
 | 
			
		|||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Clone returns a deep copy of a protocol buffer.
 | 
			
		||||
func Clone(pb Message) Message {
 | 
			
		||||
	in := reflect.ValueOf(pb)
 | 
			
		||||
func Clone(src Message) Message {
 | 
			
		||||
	in := reflect.ValueOf(src)
 | 
			
		||||
	if in.IsNil() {
 | 
			
		||||
		return pb
 | 
			
		||||
		return src
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	out := reflect.New(in.Type().Elem())
 | 
			
		||||
	// out is empty so a merge is a deep copy.
 | 
			
		||||
	mergeStruct(out.Elem(), in.Elem())
 | 
			
		||||
	return out.Interface().(Message)
 | 
			
		||||
	dst := out.Interface().(Message)
 | 
			
		||||
	Merge(dst, src)
 | 
			
		||||
	return dst
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Merger is the interface representing objects that can merge messages of the same type.
 | 
			
		||||
type Merger interface {
 | 
			
		||||
	// Merge merges src into this message.
 | 
			
		||||
	// Required and optional fields that are set in src will be set to that value in dst.
 | 
			
		||||
	// Elements of repeated fields will be appended.
 | 
			
		||||
	//
 | 
			
		||||
	// Merge may panic if called with a different argument type than the receiver.
 | 
			
		||||
	Merge(src Message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// generatedMerger is the custom merge method that generated protos will have.
 | 
			
		||||
// We must add this method since a generate Merge method will conflict with
 | 
			
		||||
// many existing protos that have a Merge data field already defined.
 | 
			
		||||
type generatedMerger interface {
 | 
			
		||||
	XXX_Merge(src Message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Merge merges src into dst.
 | 
			
		||||
| 
						 | 
				
			
			@ -58,17 +75,24 @@ func Clone(pb Message) Message {
 | 
			
		|||
// Elements of repeated fields will be appended.
 | 
			
		||||
// Merge panics if src and dst are not the same type, or if dst is nil.
 | 
			
		||||
func Merge(dst, src Message) {
 | 
			
		||||
	if m, ok := dst.(Merger); ok {
 | 
			
		||||
		m.Merge(src)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	in := reflect.ValueOf(src)
 | 
			
		||||
	out := reflect.ValueOf(dst)
 | 
			
		||||
	if out.IsNil() {
 | 
			
		||||
		panic("proto: nil destination")
 | 
			
		||||
	}
 | 
			
		||||
	if in.Type() != out.Type() {
 | 
			
		||||
		// Explicit test prior to mergeStruct so that mistyped nils will fail
 | 
			
		||||
		panic("proto: type mismatch")
 | 
			
		||||
		panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
 | 
			
		||||
	}
 | 
			
		||||
	if in.IsNil() {
 | 
			
		||||
		// Merging nil into non-nil is a quiet no-op
 | 
			
		||||
		return // Merge from nil src is a noop
 | 
			
		||||
	}
 | 
			
		||||
	if m, ok := dst.(generatedMerger); ok {
 | 
			
		||||
		m.XXX_Merge(src)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	mergeStruct(out.Elem(), in.Elem())
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) {
 | 
			
		|||
		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if emIn, ok := extendable(in.Addr().Interface()); ok {
 | 
			
		||||
	if emIn, err := extendable(in.Addr().Interface()); err == nil {
 | 
			
		||||
		emOut, _ := extendable(out.Addr().Interface())
 | 
			
		||||
		mIn, muIn := emIn.extensionsRead()
 | 
			
		||||
		if mIn != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,8 +39,6 @@ import (
 | 
			
		|||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// errOverflow is returned when an integer is too large to be represented.
 | 
			
		||||
| 
						 | 
				
			
			@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow")
 | 
			
		|||
// wire type is encountered. It does not get returned to user code.
 | 
			
		||||
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
 | 
			
		||||
 | 
			
		||||
// The fundamental decoders that interpret bytes on the wire.
 | 
			
		||||
// Those that take integer types all return uint64 and are
 | 
			
		||||
// therefore of type valueDecoder.
 | 
			
		||||
 | 
			
		||||
// DecodeVarint reads a varint-encoded integer from the slice.
 | 
			
		||||
// It returns the integer and the number of bytes consumed, or
 | 
			
		||||
// zero if there is not enough.
 | 
			
		||||
| 
						 | 
				
			
			@ -192,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
 | 
			
		|||
	if b&0x80 == 0 {
 | 
			
		||||
		goto done
 | 
			
		||||
	}
 | 
			
		||||
	// x -= 0x80 << 63 // Always zero.
 | 
			
		||||
 | 
			
		||||
	return 0, errOverflow
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -267,9 +260,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// These are not ValueDecoders: they produce an array of bytes or a string.
 | 
			
		||||
// bytes, embedded messages
 | 
			
		||||
 | 
			
		||||
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
 | 
			
		||||
// This is the format used for the bytes protocol buffer
 | 
			
		||||
// type and for embedded messages.
 | 
			
		||||
| 
						 | 
				
			
			@ -311,81 +301,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
 | 
			
		|||
	return string(buf), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
 | 
			
		||||
// If the protocol buffer has extensions, and the field matches, add it as an extension.
 | 
			
		||||
// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
 | 
			
		||||
func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
 | 
			
		||||
	oi := o.index
 | 
			
		||||
 | 
			
		||||
	err := o.skip(t, tag, wire)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !unrecField.IsValid() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptr := structPointer_Bytes(base, unrecField)
 | 
			
		||||
 | 
			
		||||
	// Add the skipped field to struct field
 | 
			
		||||
	obuf := o.buf
 | 
			
		||||
 | 
			
		||||
	o.buf = *ptr
 | 
			
		||||
	o.EncodeVarint(uint64(tag<<3 | wire))
 | 
			
		||||
	*ptr = append(o.buf, obuf[oi:o.index]...)
 | 
			
		||||
 | 
			
		||||
	o.buf = obuf
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
 | 
			
		||||
func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
 | 
			
		||||
 | 
			
		||||
	var u uint64
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch wire {
 | 
			
		||||
	case WireVarint:
 | 
			
		||||
		_, err = o.DecodeVarint()
 | 
			
		||||
	case WireFixed64:
 | 
			
		||||
		_, err = o.DecodeFixed64()
 | 
			
		||||
	case WireBytes:
 | 
			
		||||
		_, err = o.DecodeRawBytes(false)
 | 
			
		||||
	case WireFixed32:
 | 
			
		||||
		_, err = o.DecodeFixed32()
 | 
			
		||||
	case WireStartGroup:
 | 
			
		||||
		for {
 | 
			
		||||
			u, err = o.DecodeVarint()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			fwire := int(u & 0x7)
 | 
			
		||||
			if fwire == WireEndGroup {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			ftag := int(u >> 3)
 | 
			
		||||
			err = o.skip(t, ftag, fwire)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshaler is the interface representing objects that can
 | 
			
		||||
// unmarshal themselves.  The method should reset the receiver before
 | 
			
		||||
// decoding starts.  The argument points to data that may be
 | 
			
		||||
// unmarshal themselves.  The argument points to data that may be
 | 
			
		||||
// overwritten, so implementations should not keep references to the
 | 
			
		||||
// buffer.
 | 
			
		||||
// Unmarshal implementations should not clear the receiver.
 | 
			
		||||
// Any unmarshaled data should be merged into the receiver.
 | 
			
		||||
// Callers of Unmarshal that do not want to retain existing data
 | 
			
		||||
// should Reset the receiver before calling Unmarshal.
 | 
			
		||||
type Unmarshaler interface {
 | 
			
		||||
	Unmarshal([]byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newUnmarshaler is the interface representing objects that can
 | 
			
		||||
// unmarshal themselves. The semantics are identical to Unmarshaler.
 | 
			
		||||
//
 | 
			
		||||
// This exists to support protoc-gen-go generated messages.
 | 
			
		||||
// The proto package will stop type-asserting to this interface in the future.
 | 
			
		||||
//
 | 
			
		||||
// DO NOT DEPEND ON THIS.
 | 
			
		||||
type newUnmarshaler interface {
 | 
			
		||||
	XXX_Unmarshal([]byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshal parses the protocol buffer representation in buf and places the
 | 
			
		||||
// decoded result in pb.  If the struct underlying pb does not match
 | 
			
		||||
// the data in buf, the results can be unpredictable.
 | 
			
		||||
| 
						 | 
				
			
			@ -395,7 +333,13 @@ type Unmarshaler interface {
 | 
			
		|||
// to preserve and append to existing data.
 | 
			
		||||
func Unmarshal(buf []byte, pb Message) error {
 | 
			
		||||
	pb.Reset()
 | 
			
		||||
	return UnmarshalMerge(buf, pb)
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		return u.XXX_Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		return u.Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	return NewBuffer(buf).Unmarshal(pb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalMerge parses the protocol buffer representation in buf and
 | 
			
		||||
| 
						 | 
				
			
			@ -405,8 +349,16 @@ func Unmarshal(buf []byte, pb Message) error {
 | 
			
		|||
// UnmarshalMerge merges into existing data in pb.
 | 
			
		||||
// Most code should use Unmarshal instead.
 | 
			
		||||
func UnmarshalMerge(buf []byte, pb Message) error {
 | 
			
		||||
	// If the object can unmarshal itself, let it.
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		return u.XXX_Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		// NOTE: The history of proto have unfortunately been inconsistent
 | 
			
		||||
		// whether Unmarshaler should or should not implicitly clear itself.
 | 
			
		||||
		// Some implementations do, most do not.
 | 
			
		||||
		// Thus, calling this here may or may not do what people want.
 | 
			
		||||
		//
 | 
			
		||||
		// See https://github.com/golang/protobuf/issues/424
 | 
			
		||||
		return u.Unmarshal(buf)
 | 
			
		||||
	}
 | 
			
		||||
	return NewBuffer(buf).Unmarshal(pb)
 | 
			
		||||
| 
						 | 
				
			
			@ -422,12 +374,17 @@ func (p *Buffer) DecodeMessage(pb Message) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// DecodeGroup reads a tag-delimited group from the Buffer.
 | 
			
		||||
// StartGroup tag is already consumed. This function consumes
 | 
			
		||||
// EndGroup tag.
 | 
			
		||||
func (p *Buffer) DecodeGroup(pb Message) error {
 | 
			
		||||
	typ, base, err := getbase(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	b := p.buf[p.index:]
 | 
			
		||||
	x, y := findEndGroup(b)
 | 
			
		||||
	if x < 0 {
 | 
			
		||||
		return io.ErrUnexpectedEOF
 | 
			
		||||
	}
 | 
			
		||||
	return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
 | 
			
		||||
	err := Unmarshal(b[:x], pb)
 | 
			
		||||
	p.index += y
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unmarshal parses the protocol buffer representation in the
 | 
			
		||||
| 
						 | 
				
			
			@ -438,533 +395,33 @@ func (p *Buffer) DecodeGroup(pb Message) error {
 | 
			
		|||
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
 | 
			
		||||
func (p *Buffer) Unmarshal(pb Message) error {
 | 
			
		||||
	// If the object can unmarshal itself, let it.
 | 
			
		||||
	if u, ok := pb.(newUnmarshaler); ok {
 | 
			
		||||
		err := u.XXX_Unmarshal(p.buf[p.index:])
 | 
			
		||||
		p.index = len(p.buf)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if u, ok := pb.(Unmarshaler); ok {
 | 
			
		||||
		// NOTE: The history of proto have unfortunately been inconsistent
 | 
			
		||||
		// whether Unmarshaler should or should not implicitly clear itself.
 | 
			
		||||
		// Some implementations do, most do not.
 | 
			
		||||
		// Thus, calling this here may or may not do what people want.
 | 
			
		||||
		//
 | 
			
		||||
		// See https://github.com/golang/protobuf/issues/424
 | 
			
		||||
		err := u.Unmarshal(p.buf[p.index:])
 | 
			
		||||
		p.index = len(p.buf)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	typ, base, err := getbase(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
 | 
			
		||||
 | 
			
		||||
	if collectStats {
 | 
			
		||||
		stats.Decode++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// unmarshalType does the work of unmarshaling a structure.
 | 
			
		||||
func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
 | 
			
		||||
	var state errorState
 | 
			
		||||
	required, reqFields := prop.reqCount, uint64(0)
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	for err == nil && o.index < len(o.buf) {
 | 
			
		||||
		oi := o.index
 | 
			
		||||
		var u uint64
 | 
			
		||||
		u, err = o.DecodeVarint()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		wire := int(u & 0x7)
 | 
			
		||||
		if wire == WireEndGroup {
 | 
			
		||||
			if is_group {
 | 
			
		||||
				if required > 0 {
 | 
			
		||||
					// Not enough information to determine the exact field.
 | 
			
		||||
					// (See below.)
 | 
			
		||||
					return &RequiredNotSetError{"{Unknown}"}
 | 
			
		||||
				}
 | 
			
		||||
				return nil // input is satisfied
 | 
			
		||||
			}
 | 
			
		||||
			return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
 | 
			
		||||
		}
 | 
			
		||||
		tag := int(u >> 3)
 | 
			
		||||
		if tag <= 0 {
 | 
			
		||||
			return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
 | 
			
		||||
		}
 | 
			
		||||
		fieldnum, ok := prop.decoderTags.get(tag)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			// Maybe it's an extension?
 | 
			
		||||
			if prop.extendable {
 | 
			
		||||
				if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
 | 
			
		||||
					if err = o.skip(st, tag, wire); err == nil {
 | 
			
		||||
						extmap := e.extensionsWrite()
 | 
			
		||||
						ext := extmap[int32(tag)] // may be missing
 | 
			
		||||
						ext.enc = append(ext.enc, o.buf[oi:o.index]...)
 | 
			
		||||
						extmap[int32(tag)] = ext
 | 
			
		||||
					}
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// Maybe it's a oneof?
 | 
			
		||||
			if prop.oneofUnmarshaler != nil {
 | 
			
		||||
				m := structPointer_Interface(base, st).(Message)
 | 
			
		||||
				// First return value indicates whether tag is a oneof field.
 | 
			
		||||
				ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
 | 
			
		||||
				if err == ErrInternalBadWireType {
 | 
			
		||||
					// Map the error to something more descriptive.
 | 
			
		||||
					// Do the formatting here to save generated code space.
 | 
			
		||||
					err = fmt.Errorf("bad wiretype for oneof field in %T", m)
 | 
			
		||||
				}
 | 
			
		||||
				if ok {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		p := prop.Prop[fieldnum]
 | 
			
		||||
 | 
			
		||||
		if p.dec == nil {
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		dec := p.dec
 | 
			
		||||
		if wire != WireStartGroup && wire != p.WireType {
 | 
			
		||||
			if wire == WireBytes && p.packedDec != nil {
 | 
			
		||||
				// a packable field
 | 
			
		||||
				dec = p.packedDec
 | 
			
		||||
			} else {
 | 
			
		||||
				err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		decErr := dec(o, p, base)
 | 
			
		||||
		if decErr != nil && !state.shouldContinue(decErr, p) {
 | 
			
		||||
			err = decErr
 | 
			
		||||
		}
 | 
			
		||||
		if err == nil && p.Required {
 | 
			
		||||
			// Successfully decoded a required field.
 | 
			
		||||
			if tag <= 64 {
 | 
			
		||||
				// use bitmap for fields 1-64 to catch field reuse.
 | 
			
		||||
				var mask uint64 = 1 << uint64(tag-1)
 | 
			
		||||
				if reqFields&mask == 0 {
 | 
			
		||||
					// new required field
 | 
			
		||||
					reqFields |= mask
 | 
			
		||||
					required--
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				// This is imprecise. It can be fooled by a required field
 | 
			
		||||
				// with a tag > 64 that is encoded twice; that's very rare.
 | 
			
		||||
				// A fully correct implementation would require allocating
 | 
			
		||||
				// a data structure, which we would like to avoid.
 | 
			
		||||
				required--
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if is_group {
 | 
			
		||||
			return io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		if state.err != nil {
 | 
			
		||||
			return state.err
 | 
			
		||||
		}
 | 
			
		||||
		if required > 0 {
 | 
			
		||||
			// Not enough information to determine the exact field. If we use extra
 | 
			
		||||
			// CPU, we could determine the field only if the missing required field
 | 
			
		||||
			// has a tag <= 64 and we check reqFields.
 | 
			
		||||
			return &RequiredNotSetError{"{Unknown}"}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Individual type decoders
 | 
			
		||||
// For each,
 | 
			
		||||
//	u is the decoded value,
 | 
			
		||||
//	v is a pointer to the field (pointer) in the struct
 | 
			
		||||
 | 
			
		||||
// Sizes of the pools to allocate inside the Buffer.
 | 
			
		||||
// The goal is modest amortization and allocation
 | 
			
		||||
// on at least 16-byte boundaries.
 | 
			
		||||
const (
 | 
			
		||||
	boolPoolSize   = 16
 | 
			
		||||
	uint32PoolSize = 8
 | 
			
		||||
	uint64PoolSize = 4
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Decode a bool.
 | 
			
		||||
func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if len(o.bools) == 0 {
 | 
			
		||||
		o.bools = make([]bool, boolPoolSize)
 | 
			
		||||
	}
 | 
			
		||||
	o.bools[0] = u != 0
 | 
			
		||||
	*structPointer_Bool(base, p.field) = &o.bools[0]
 | 
			
		||||
	o.bools = o.bools[1:]
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*structPointer_BoolVal(base, p.field) = u != 0
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode an int32.
 | 
			
		||||
func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode an int64.
 | 
			
		||||
func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	word64_Set(structPointer_Word64(base, p.field), o, u)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a string.
 | 
			
		||||
func (o *Buffer) dec_string(p *Properties, base structPointer) error {
 | 
			
		||||
	s, err := o.DecodeStringBytes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*structPointer_String(base, p.field) = &s
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
 | 
			
		||||
	s, err := o.DecodeStringBytes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*structPointer_StringVal(base, p.field) = s
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of bytes ([]byte).
 | 
			
		||||
func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
 | 
			
		||||
	b, err := o.DecodeRawBytes(true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*structPointer_Bytes(base, p.field) = b
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of bools ([]bool).
 | 
			
		||||
func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	v := structPointer_BoolSlice(base, p.field)
 | 
			
		||||
	*v = append(*v, u != 0)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of bools ([]bool) in packed format.
 | 
			
		||||
func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
 | 
			
		||||
	v := structPointer_BoolSlice(base, p.field)
 | 
			
		||||
 | 
			
		||||
	nn, err := o.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	nb := int(nn) // number of bytes of encoded bools
 | 
			
		||||
	fin := o.index + nb
 | 
			
		||||
	if fin < o.index {
 | 
			
		||||
		return errOverflow
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	y := *v
 | 
			
		||||
	for o.index < fin {
 | 
			
		||||
		u, err := p.valDec(o)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		y = append(y, u != 0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*v = y
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of int32s ([]int32).
 | 
			
		||||
func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	structPointer_Word32Slice(base, p.field).Append(uint32(u))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of int32s ([]int32) in packed format.
 | 
			
		||||
func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
 | 
			
		||||
	v := structPointer_Word32Slice(base, p.field)
 | 
			
		||||
 | 
			
		||||
	nn, err := o.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	nb := int(nn) // number of bytes of encoded int32s
 | 
			
		||||
 | 
			
		||||
	fin := o.index + nb
 | 
			
		||||
	if fin < o.index {
 | 
			
		||||
		return errOverflow
 | 
			
		||||
	}
 | 
			
		||||
	for o.index < fin {
 | 
			
		||||
		u, err := p.valDec(o)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		v.Append(uint32(u))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of int64s ([]int64).
 | 
			
		||||
func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
 | 
			
		||||
	u, err := p.valDec(o)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	structPointer_Word64Slice(base, p.field).Append(u)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of int64s ([]int64) in packed format.
 | 
			
		||||
func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
 | 
			
		||||
	v := structPointer_Word64Slice(base, p.field)
 | 
			
		||||
 | 
			
		||||
	nn, err := o.DecodeVarint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	nb := int(nn) // number of bytes of encoded int64s
 | 
			
		||||
 | 
			
		||||
	fin := o.index + nb
 | 
			
		||||
	if fin < o.index {
 | 
			
		||||
		return errOverflow
 | 
			
		||||
	}
 | 
			
		||||
	for o.index < fin {
 | 
			
		||||
		u, err := p.valDec(o)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		v.Append(u)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of strings ([]string).
 | 
			
		||||
func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
 | 
			
		||||
	s, err := o.DecodeStringBytes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	v := structPointer_StringSlice(base, p.field)
 | 
			
		||||
	*v = append(*v, s)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of slice of bytes ([][]byte).
 | 
			
		||||
func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
 | 
			
		||||
	b, err := o.DecodeRawBytes(true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	v := structPointer_BytesSlice(base, p.field)
 | 
			
		||||
	*v = append(*v, b)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a map field.
 | 
			
		||||
func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
 | 
			
		||||
	raw, err := o.DecodeRawBytes(false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	oi := o.index       // index at the end of this map entry
 | 
			
		||||
	o.index -= len(raw) // move buffer back to start of map entry
 | 
			
		||||
 | 
			
		||||
	mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
 | 
			
		||||
	if mptr.Elem().IsNil() {
 | 
			
		||||
		mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
 | 
			
		||||
	}
 | 
			
		||||
	v := mptr.Elem() // map[K]V
 | 
			
		||||
 | 
			
		||||
	// Prepare addressable doubly-indirect placeholders for the key and value types.
 | 
			
		||||
	// See enc_new_map for why.
 | 
			
		||||
	keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
 | 
			
		||||
	keybase := toStructPointer(keyptr.Addr())                  // **K
 | 
			
		||||
 | 
			
		||||
	var valbase structPointer
 | 
			
		||||
	var valptr reflect.Value
 | 
			
		||||
	switch p.mtype.Elem().Kind() {
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		// []byte
 | 
			
		||||
		var dummy []byte
 | 
			
		||||
		valptr = reflect.ValueOf(&dummy)  // *[]byte
 | 
			
		||||
		valbase = toStructPointer(valptr) // *[]byte
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		// message; valptr is **Msg; need to allocate the intermediate pointer
 | 
			
		||||
		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
 | 
			
		||||
		valptr.Set(reflect.New(valptr.Type().Elem()))
 | 
			
		||||
		valbase = toStructPointer(valptr)
 | 
			
		||||
	default:
 | 
			
		||||
		// everything else
 | 
			
		||||
		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
 | 
			
		||||
		valbase = toStructPointer(valptr.Addr())                   // **V
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Decode.
 | 
			
		||||
	// This parses a restricted wire format, namely the encoding of a message
 | 
			
		||||
	// with two fields. See enc_new_map for the format.
 | 
			
		||||
	for o.index < oi {
 | 
			
		||||
		// tagcode for key and value properties are always a single byte
 | 
			
		||||
		// because they have tags 1 and 2.
 | 
			
		||||
		tagcode := o.buf[o.index]
 | 
			
		||||
		o.index++
 | 
			
		||||
		switch tagcode {
 | 
			
		||||
		case p.mkeyprop.tagcode[0]:
 | 
			
		||||
			if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		case p.mvalprop.tagcode[0]:
 | 
			
		||||
			if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			// TODO: Should we silently skip this instead?
 | 
			
		||||
			return fmt.Errorf("proto: bad map data tag %d", raw[0])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	keyelem, valelem := keyptr.Elem(), valptr.Elem()
 | 
			
		||||
	if !keyelem.IsValid() {
 | 
			
		||||
		keyelem = reflect.Zero(p.mtype.Key())
 | 
			
		||||
	}
 | 
			
		||||
	if !valelem.IsValid() {
 | 
			
		||||
		valelem = reflect.Zero(p.mtype.Elem())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetMapIndex(keyelem, valelem)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a group.
 | 
			
		||||
func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
 | 
			
		||||
	bas := structPointer_GetStructPointer(base, p.field)
 | 
			
		||||
	if structPointer_IsNil(bas) {
 | 
			
		||||
		// allocate new nested message
 | 
			
		||||
		bas = toStructPointer(reflect.New(p.stype))
 | 
			
		||||
		structPointer_SetStructPointer(base, p.field, bas)
 | 
			
		||||
	}
 | 
			
		||||
	return o.unmarshalType(p.stype, p.sprop, true, bas)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode an embedded message.
 | 
			
		||||
func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
 | 
			
		||||
	raw, e := o.DecodeRawBytes(false)
 | 
			
		||||
	if e != nil {
 | 
			
		||||
		return e
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bas := structPointer_GetStructPointer(base, p.field)
 | 
			
		||||
	if structPointer_IsNil(bas) {
 | 
			
		||||
		// allocate new nested message
 | 
			
		||||
		bas = toStructPointer(reflect.New(p.stype))
 | 
			
		||||
		structPointer_SetStructPointer(base, p.field, bas)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the object can unmarshal itself, let it.
 | 
			
		||||
	if p.isUnmarshaler {
 | 
			
		||||
		iv := structPointer_Interface(bas, p.stype)
 | 
			
		||||
		return iv.(Unmarshaler).Unmarshal(raw)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obuf := o.buf
 | 
			
		||||
	oi := o.index
 | 
			
		||||
	o.buf = raw
 | 
			
		||||
	o.index = 0
 | 
			
		||||
 | 
			
		||||
	err = o.unmarshalType(p.stype, p.sprop, false, bas)
 | 
			
		||||
	o.buf = obuf
 | 
			
		||||
	o.index = oi
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of embedded messages.
 | 
			
		||||
func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
 | 
			
		||||
	return o.dec_slice_struct(p, false, base)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of embedded groups.
 | 
			
		||||
func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
 | 
			
		||||
	return o.dec_slice_struct(p, true, base)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode a slice of structs ([]*struct).
 | 
			
		||||
func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
 | 
			
		||||
	v := reflect.New(p.stype)
 | 
			
		||||
	bas := toStructPointer(v)
 | 
			
		||||
	structPointer_StructPointerSlice(base, p.field).Append(bas)
 | 
			
		||||
 | 
			
		||||
	if is_group {
 | 
			
		||||
		err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw, err := o.DecodeRawBytes(false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the object can unmarshal itself, let it.
 | 
			
		||||
	if p.isUnmarshaler {
 | 
			
		||||
		iv := v.Interface()
 | 
			
		||||
		return iv.(Unmarshaler).Unmarshal(raw)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obuf := o.buf
 | 
			
		||||
	oi := o.index
 | 
			
		||||
	o.buf = raw
 | 
			
		||||
	o.index = 0
 | 
			
		||||
 | 
			
		||||
	err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
 | 
			
		||||
 | 
			
		||||
	o.buf = obuf
 | 
			
		||||
	o.index = oi
 | 
			
		||||
 | 
			
		||||
	// Slow workaround for messages that aren't Unmarshalers.
 | 
			
		||||
	// This includes some hand-coded .pb.go files and
 | 
			
		||||
	// bootstrap protos.
 | 
			
		||||
	// TODO: fix all of those and then add Unmarshal to
 | 
			
		||||
	// the Message interface. Then:
 | 
			
		||||
	// The cast above and code below can be deleted.
 | 
			
		||||
	// The old unmarshaler can be deleted.
 | 
			
		||||
	// Clients can call Unmarshal directly (can already do that, actually).
 | 
			
		||||
	var info InternalMessageInfo
 | 
			
		||||
	err := info.Unmarshal(pb, p.buf[p.index:])
 | 
			
		||||
	p.index = len(p.buf)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
// 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) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,350 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2017 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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type generatedDiscarder interface {
 | 
			
		||||
	XXX_DiscardUnknown()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DiscardUnknown recursively discards all unknown fields from this message
 | 
			
		||||
// and all embedded messages.
 | 
			
		||||
//
 | 
			
		||||
// When unmarshaling a message with unrecognized fields, the tags and values
 | 
			
		||||
// of such fields are preserved in the Message. This allows a later call to
 | 
			
		||||
// marshal to be able to produce a message that continues to have those
 | 
			
		||||
// unrecognized fields. To avoid this, DiscardUnknown is used to
 | 
			
		||||
// explicitly clear the unknown fields after unmarshaling.
 | 
			
		||||
//
 | 
			
		||||
// For proto2 messages, the unknown fields of message extensions are only
 | 
			
		||||
// discarded from messages that have been accessed via GetExtension.
 | 
			
		||||
func DiscardUnknown(m Message) {
 | 
			
		||||
	if m, ok := m.(generatedDiscarder); ok {
 | 
			
		||||
		m.XXX_DiscardUnknown()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
 | 
			
		||||
	// but the master branch has no implementation for InternalMessageInfo,
 | 
			
		||||
	// so it would be more work to replicate that approach.
 | 
			
		||||
	discardLegacy(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DiscardUnknown recursively discards all unknown fields.
 | 
			
		||||
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
 | 
			
		||||
	di := atomicLoadDiscardInfo(&a.discard)
 | 
			
		||||
	if di == nil {
 | 
			
		||||
		di = getDiscardInfo(reflect.TypeOf(m).Elem())
 | 
			
		||||
		atomicStoreDiscardInfo(&a.discard, di)
 | 
			
		||||
	}
 | 
			
		||||
	di.discard(toPointer(&m))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type discardInfo struct {
 | 
			
		||||
	typ reflect.Type
 | 
			
		||||
 | 
			
		||||
	initialized int32 // 0: only typ is valid, 1: everything is valid
 | 
			
		||||
	lock        sync.Mutex
 | 
			
		||||
 | 
			
		||||
	fields       []discardFieldInfo
 | 
			
		||||
	unrecognized field
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type discardFieldInfo struct {
 | 
			
		||||
	field   field // Offset of field, guaranteed to be valid
 | 
			
		||||
	discard func(src pointer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	discardInfoMap  = map[reflect.Type]*discardInfo{}
 | 
			
		||||
	discardInfoLock sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getDiscardInfo(t reflect.Type) *discardInfo {
 | 
			
		||||
	discardInfoLock.Lock()
 | 
			
		||||
	defer discardInfoLock.Unlock()
 | 
			
		||||
	di := discardInfoMap[t]
 | 
			
		||||
	if di == nil {
 | 
			
		||||
		di = &discardInfo{typ: t}
 | 
			
		||||
		discardInfoMap[t] = di
 | 
			
		||||
	}
 | 
			
		||||
	return di
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (di *discardInfo) discard(src pointer) {
 | 
			
		||||
	if src.isNil() {
 | 
			
		||||
		return // Nothing to do.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if atomic.LoadInt32(&di.initialized) == 0 {
 | 
			
		||||
		di.computeDiscardInfo()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, fi := range di.fields {
 | 
			
		||||
		sfp := src.offset(fi.field)
 | 
			
		||||
		fi.discard(sfp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For proto2 messages, only discard unknown fields in message extensions
 | 
			
		||||
	// that have been accessed via GetExtension.
 | 
			
		||||
	if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
 | 
			
		||||
		// Ignore lock since DiscardUnknown is not concurrency safe.
 | 
			
		||||
		emm, _ := em.extensionsRead()
 | 
			
		||||
		for _, mx := range emm {
 | 
			
		||||
			if m, ok := mx.value.(Message); ok {
 | 
			
		||||
				DiscardUnknown(m)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if di.unrecognized.IsValid() {
 | 
			
		||||
		*src.offset(di.unrecognized).toBytes() = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (di *discardInfo) computeDiscardInfo() {
 | 
			
		||||
	di.lock.Lock()
 | 
			
		||||
	defer di.lock.Unlock()
 | 
			
		||||
	if di.initialized != 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := di.typ
 | 
			
		||||
	n := t.NumField()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dfi := discardFieldInfo{field: toField(&f)}
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				di := getDiscardInfo(tf)
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					sps := src.getPointerSlice()
 | 
			
		||||
					for _, sp := range sps {
 | 
			
		||||
						if !sp.isNil() {
 | 
			
		||||
							di.discard(sp)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				di := getDiscardInfo(tf)
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					sp := src.getPointer()
 | 
			
		||||
					if !sp.isNil() {
 | 
			
		||||
						di.discard(sp)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
 | 
			
		||||
					dfi.discard = func(src pointer) {
 | 
			
		||||
						sm := src.asPointerTo(tf).Elem()
 | 
			
		||||
						if sm.Len() == 0 {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							DiscardUnknown(val.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					dfi.discard = func(pointer) {} // Noop
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
 | 
			
		||||
			default: // E.g., interface{}
 | 
			
		||||
				// TODO: Make this faster?
 | 
			
		||||
				dfi.discard = func(src pointer) {
 | 
			
		||||
					su := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if !su.IsNil() {
 | 
			
		||||
						sv := su.Elem().Elem().Field(0)
 | 
			
		||||
						if sv.Kind() == reflect.Ptr && sv.IsNil() {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						switch sv.Type().Kind() {
 | 
			
		||||
						case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
							DiscardUnknown(sv.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		di.fields = append(di.fields, dfi)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	di.unrecognized = invalidField
 | 
			
		||||
	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
 | 
			
		||||
		if f.Type != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		di.unrecognized = toField(&f)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atomic.StoreInt32(&di.initialized, 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func discardLegacy(m Message) {
 | 
			
		||||
	v := reflect.ValueOf(m)
 | 
			
		||||
	if v.Kind() != reflect.Ptr || v.IsNil() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	v = v.Elem()
 | 
			
		||||
	if v.Kind() != reflect.Struct {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := v.Type()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < v.NumField(); i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		vf := v.Field(i)
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				for j := 0; j < vf.Len(); j++ {
 | 
			
		||||
					discardLegacy(vf.Index(j).Interface().(Message))
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				discardLegacy(vf.Interface().(Message))
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				tv := vf.Type().Elem()
 | 
			
		||||
				if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
 | 
			
		||||
					for _, key := range vf.MapKeys() {
 | 
			
		||||
						val := vf.MapIndex(key)
 | 
			
		||||
						discardLegacy(val.Interface().(Message))
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
 | 
			
		||||
			default: // E.g., test_proto.isCommunique_Union interface
 | 
			
		||||
				if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
 | 
			
		||||
					vf = vf.Elem() // E.g., *test_proto.Communique_Msg
 | 
			
		||||
					if !vf.IsNil() {
 | 
			
		||||
						vf = vf.Elem()   // E.g., test_proto.Communique_Msg
 | 
			
		||||
						vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
 | 
			
		||||
						if vf.Kind() == reflect.Ptr {
 | 
			
		||||
							discardLegacy(vf.Interface().(Message))
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
 | 
			
		||||
		if vf.Type() != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		vf.Set(reflect.ValueOf([]byte(nil)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// For proto2 messages, only discard unknown fields in message extensions
 | 
			
		||||
	// that have been accessed via GetExtension.
 | 
			
		||||
	if em, err := extendable(m); err == nil {
 | 
			
		||||
		// Ignore lock since discardLegacy is not concurrency safe.
 | 
			
		||||
		emm, _ := em.extensionsRead()
 | 
			
		||||
		for _, mx := range emm {
 | 
			
		||||
			if m, ok := mx.value.(Message); ok {
 | 
			
		||||
				discardLegacy(m)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool {
 | 
			
		|||
				// set/unset mismatch
 | 
			
		||||
				return false
 | 
			
		||||
			}
 | 
			
		||||
			b1, ok := f1.Interface().(raw)
 | 
			
		||||
			if ok {
 | 
			
		||||
				b2 := f2.Interface().(raw)
 | 
			
		||||
				// RawMessage
 | 
			
		||||
				if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
 | 
			
		||||
					return false
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			f1, f2 = f1.Elem(), f2.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if !equalAny(f1, f2, sprop.Prop[i]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
 | 
			
		|||
 | 
			
		||||
	u1 := uf.Bytes()
 | 
			
		||||
	u2 := v2.FieldByName("XXX_unrecognized").Bytes()
 | 
			
		||||
	if !bytes.Equal(u1, u2) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
	return bytes.Equal(u1, u2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// v1 and v2 are known to have the same type.
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +246,17 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 | 
			
		|||
			return false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m1, m2 := e1.value, e2.value
 | 
			
		||||
		m1 := extensionAsLegacyType(e1.value)
 | 
			
		||||
		m2 := extensionAsLegacyType(e2.value)
 | 
			
		||||
 | 
			
		||||
		if m1 == nil && m2 == nil {
 | 
			
		||||
			// Both have only encoded form.
 | 
			
		||||
			if bytes.Equal(e1.enc, e2.enc) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			// The bytes are different, but the extensions might still be
 | 
			
		||||
			// equal. We need to decode them to compare.
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if m1 != nil && m2 != nil {
 | 
			
		||||
			// Both are unencoded.
 | 
			
		||||
| 
						 | 
				
			
			@ -276,8 +273,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 | 
			
		|||
			desc = m[extNum]
 | 
			
		||||
		}
 | 
			
		||||
		if desc == nil {
 | 
			
		||||
			// If both have only encoded form and the bytes are the same,
 | 
			
		||||
			// it is handled above. We get here when the bytes are different.
 | 
			
		||||
			// We don't know how to decode it, so just compare them as byte
 | 
			
		||||
			// slices.
 | 
			
		||||
			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
 | 
			
		||||
			continue
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		if m1 == nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ package proto
 | 
			
		|||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"sync"
 | 
			
		||||
| 
						 | 
				
			
			@ -91,14 +92,29 @@ func (n notLocker) Unlock() {}
 | 
			
		|||
// extendable returns the extendableProto interface for the given generated proto message.
 | 
			
		||||
// If the proto message has the old extension format, it returns a wrapper that implements
 | 
			
		||||
// the extendableProto interface.
 | 
			
		||||
func extendable(p interface{}) (extendableProto, bool) {
 | 
			
		||||
	if ep, ok := p.(extendableProto); ok {
 | 
			
		||||
		return ep, ok
 | 
			
		||||
func extendable(p interface{}) (extendableProto, error) {
 | 
			
		||||
	switch p := p.(type) {
 | 
			
		||||
	case extendableProto:
 | 
			
		||||
		if isNilPtr(p) {
 | 
			
		||||
			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
 | 
			
		||||
		}
 | 
			
		||||
		return p, nil
 | 
			
		||||
	case extendableProtoV1:
 | 
			
		||||
		if isNilPtr(p) {
 | 
			
		||||
			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
 | 
			
		||||
		}
 | 
			
		||||
		return extensionAdapter{p}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if ep, ok := p.(extendableProtoV1); ok {
 | 
			
		||||
		return extensionAdapter{ep}, ok
 | 
			
		||||
	}
 | 
			
		||||
	return nil, false
 | 
			
		||||
	// Don't allocate a specific error containing %T:
 | 
			
		||||
	// this is the hot path for Clone and MarshalText.
 | 
			
		||||
	return nil, errNotExtendable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
 | 
			
		||||
 | 
			
		||||
func isNilPtr(x interface{}) bool {
 | 
			
		||||
	v := reflect.ValueOf(x)
 | 
			
		||||
	return v.Kind() == reflect.Ptr && v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// XXX_InternalExtensions is an internal representation of proto extensions.
 | 
			
		||||
| 
						 | 
				
			
			@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
 | 
			
		|||
	return e.p.extensionMap, &e.p.mu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
 | 
			
		||||
var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
 | 
			
		||||
 | 
			
		||||
// ExtensionDesc represents an extension specification.
 | 
			
		||||
// Used in generated code from the protocol compiler.
 | 
			
		||||
type ExtensionDesc struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -172,15 +185,31 @@ 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
 | 
			
		||||
	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.
 | 
			
		||||
	value interface{}
 | 
			
		||||
	enc   []byte
 | 
			
		||||
 | 
			
		||||
	// enc is the raw bytes for the extension field.
 | 
			
		||||
	enc []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetRawExtension is for testing only.
 | 
			
		||||
func SetRawExtension(base Message, id int32, b []byte) {
 | 
			
		||||
	epb, ok := extendable(base)
 | 
			
		||||
	if !ok {
 | 
			
		||||
	epb, err := extendable(base)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	extmap := epb.extensionsWrite()
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +234,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
 | 
			
		|||
		pbi = ea.extendableProtoV1
 | 
			
		||||
	}
 | 
			
		||||
	if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
 | 
			
		||||
		return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
 | 
			
		||||
		return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
 | 
			
		||||
	}
 | 
			
		||||
	// Check the range.
 | 
			
		||||
	if !isExtensionField(pb, extension.Field) {
 | 
			
		||||
| 
						 | 
				
			
			@ -250,85 +279,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
 | 
			
		|||
	return prop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// encode encodes any unmarshaled (unencoded) extensions in e.
 | 
			
		||||
func encodeExtensions(e *XXX_InternalExtensions) error {
 | 
			
		||||
	m, mu := e.extensionsRead()
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return nil // fast path
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	return encodeExtensionsMap(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// encode encodes any unmarshaled (unencoded) extensions in e.
 | 
			
		||||
func encodeExtensionsMap(m map[int32]Extension) error {
 | 
			
		||||
	for k, e := range m {
 | 
			
		||||
		if e.value == nil || e.desc == nil {
 | 
			
		||||
			// Extension is only in its encoded form.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// We don't skip extensions that have an encoded form set,
 | 
			
		||||
		// because the extension value may have been mutated after
 | 
			
		||||
		// the last time this function was called.
 | 
			
		||||
 | 
			
		||||
		et := reflect.TypeOf(e.desc.ExtensionType)
 | 
			
		||||
		props := extensionProperties(e.desc)
 | 
			
		||||
 | 
			
		||||
		p := NewBuffer(nil)
 | 
			
		||||
		// If e.value has type T, the encoder expects a *struct{ X T }.
 | 
			
		||||
		// Pass a *T with a zero field and hope it all works out.
 | 
			
		||||
		x := reflect.New(et)
 | 
			
		||||
		x.Elem().Set(reflect.ValueOf(e.value))
 | 
			
		||||
		if err := props.enc(p, props, toStructPointer(x)); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		e.enc = p.buf
 | 
			
		||||
		m[k] = e
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func extensionsSize(e *XXX_InternalExtensions) (n int) {
 | 
			
		||||
	m, mu := e.extensionsRead()
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	return extensionsMapSize(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func extensionsMapSize(m map[int32]Extension) (n int) {
 | 
			
		||||
	for _, e := range m {
 | 
			
		||||
		if e.value == nil || e.desc == nil {
 | 
			
		||||
			// Extension is only in its encoded form.
 | 
			
		||||
			n += len(e.enc)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// We don't skip extensions that have an encoded form set,
 | 
			
		||||
		// because the extension value may have been mutated after
 | 
			
		||||
		// the last time this function was called.
 | 
			
		||||
 | 
			
		||||
		et := reflect.TypeOf(e.desc.ExtensionType)
 | 
			
		||||
		props := extensionProperties(e.desc)
 | 
			
		||||
 | 
			
		||||
		// If e.value has type T, the encoder expects a *struct{ X T }.
 | 
			
		||||
		// Pass a *T with a zero field and hope it all works out.
 | 
			
		||||
		x := reflect.New(et)
 | 
			
		||||
		x.Elem().Set(reflect.ValueOf(e.value))
 | 
			
		||||
		n += props.size(props, toStructPointer(x))
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasExtension returns whether the given extension is present in pb.
 | 
			
		||||
func HasExtension(pb Message, extension *ExtensionDesc) bool {
 | 
			
		||||
	// TODO: Check types, field numbers, etc.?
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	extmap, mu := epb.extensionsRead()
 | 
			
		||||
| 
						 | 
				
			
			@ -336,15 +291,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
 | 
			
		|||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	_, ok = extmap[extension.Field]
 | 
			
		||||
	_, ok := extmap[extension.Field]
 | 
			
		||||
	mu.Unlock()
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearExtension removes the given extension from pb.
 | 
			
		||||
func ClearExtension(pb Message, extension *ExtensionDesc) {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Check types, field numbers, etc.?
 | 
			
		||||
| 
						 | 
				
			
			@ -352,16 +307,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
 | 
			
		|||
	delete(extmap, extension.Field)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExtension parses and returns the given extension of pb.
 | 
			
		||||
// If the extension is not present and has no default value it returns ErrMissingExtension.
 | 
			
		||||
// GetExtension retrieves a proto2 extended field from pb.
 | 
			
		||||
//
 | 
			
		||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
 | 
			
		||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
 | 
			
		||||
// If the field is not present, then the default value is returned (if one is specified),
 | 
			
		||||
// otherwise ErrMissingExtension is reported.
 | 
			
		||||
//
 | 
			
		||||
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
 | 
			
		||||
// then GetExtension returns the raw encoded bytes of the field extension.
 | 
			
		||||
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, errors.New("proto: not an extendable proto")
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := checkExtensionTypes(epb, extension); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	if extension.ExtendedType != nil {
 | 
			
		||||
		// can only check type if this is a complete descriptor
 | 
			
		||||
		if err := checkExtensionTypes(epb, extension); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	emap, mu := epb.extensionsRead()
 | 
			
		||||
| 
						 | 
				
			
			@ -385,7 +350,12 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		|||
			// descriptors with the same field number.
 | 
			
		||||
			return nil, errors.New("proto: descriptor conflict")
 | 
			
		||||
		}
 | 
			
		||||
		return e.value, nil
 | 
			
		||||
		return extensionAsLegacyType(e.value), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if extension.ExtensionType == nil {
 | 
			
		||||
		// incomplete descriptor
 | 
			
		||||
		return e.enc, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v, err := decodeExtension(e.enc, extension)
 | 
			
		||||
| 
						 | 
				
			
			@ -395,16 +365,21 @@ 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 = v
 | 
			
		||||
	e.value = extensionAsStorageType(v)
 | 
			
		||||
	e.desc = extension
 | 
			
		||||
	e.enc = nil
 | 
			
		||||
	emap[extension.Field] = e
 | 
			
		||||
	return e.value, nil
 | 
			
		||||
	return extensionAsLegacyType(e.value), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// defaultExtensionValue returns the default value for extension.
 | 
			
		||||
// If no default for an extension is defined ErrMissingExtension is returned.
 | 
			
		||||
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	if extension.ExtensionType == nil {
 | 
			
		||||
		// incomplete descriptor, so no default
 | 
			
		||||
		return nil, ErrMissingExtension
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
	props := extensionProperties(extension)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -439,31 +414,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
 | 
			
		|||
 | 
			
		||||
// decodeExtension decodes an extension encoded in b.
 | 
			
		||||
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		||||
	o := NewBuffer(b)
 | 
			
		||||
 | 
			
		||||
	t := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
 | 
			
		||||
	props := extensionProperties(extension)
 | 
			
		||||
	unmarshal := typeUnmarshaler(t, extension.Tag)
 | 
			
		||||
 | 
			
		||||
	// t is a pointer to a struct, pointer to basic type or a slice.
 | 
			
		||||
	// Allocate a "field" to store the pointer/slice itself; the
 | 
			
		||||
	// pointer/slice will be stored here. We pass
 | 
			
		||||
	// the address of this field to props.dec.
 | 
			
		||||
	// This passes a zero field and a *t and lets props.dec
 | 
			
		||||
	// interpret it as a *struct{ x t }.
 | 
			
		||||
	// Allocate space to store the pointer/slice.
 | 
			
		||||
	value := reflect.New(t).Elem()
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		// Discard wire type and field number varint. It isn't needed.
 | 
			
		||||
		if _, err := o.DecodeVarint(); err != nil {
 | 
			
		||||
		x, n := decodeVarint(b)
 | 
			
		||||
		if n == 0 {
 | 
			
		||||
			return nil, io.ErrUnexpectedEOF
 | 
			
		||||
		}
 | 
			
		||||
		b = b[n:]
 | 
			
		||||
		wire := int(x) & 7
 | 
			
		||||
 | 
			
		||||
		b, err = unmarshal(b, valToPointer(value.Addr()), wire)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if o.index >= len(o.buf) {
 | 
			
		||||
		if len(b) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -473,9 +445,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 | 
			
		|||
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
 | 
			
		||||
// The returned slice has the same length as es; missing extensions will appear as nil elements.
 | 
			
		||||
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, errors.New("proto: not an extendable proto")
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	extensions = make([]interface{}, len(es))
 | 
			
		||||
	for i, e := range es {
 | 
			
		||||
| 
						 | 
				
			
			@ -494,9 +466,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
 | 
			
		|||
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
 | 
			
		||||
// just the Field field, which defines the extension's field number.
 | 
			
		||||
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	registeredExtensions := RegisteredExtensions(pb)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -523,16 +495,16 @@ 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 {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return errors.New("proto: not an extendable proto")
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := checkExtensionTypes(epb, extension); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	typ := reflect.TypeOf(extension.ExtensionType)
 | 
			
		||||
	if typ != reflect.TypeOf(value) {
 | 
			
		||||
		return errors.New("proto: bad extension value type")
 | 
			
		||||
		return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
 | 
			
		||||
	}
 | 
			
		||||
	// nil extension values need to be caught early, because the
 | 
			
		||||
	// encoder can't distinguish an ErrNil due to a nil extension
 | 
			
		||||
| 
						 | 
				
			
			@ -544,14 +516,14 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	extmap := epb.extensionsWrite()
 | 
			
		||||
	extmap[extension.Field] = Extension{desc: extension, value: value}
 | 
			
		||||
	extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClearAllExtensions clears all extensions from pb.
 | 
			
		||||
func ClearAllExtensions(pb Message) {
 | 
			
		||||
	epb, ok := extendable(pb)
 | 
			
		||||
	if !ok {
 | 
			
		||||
	epb, err := extendable(pb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	m := epb.extensionsWrite()
 | 
			
		||||
| 
						 | 
				
			
			@ -585,3 +557,51 @@ 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -273,6 +273,67 @@ 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Message is implemented by generated protocol buffer messages.
 | 
			
		||||
type Message interface {
 | 
			
		||||
	Reset()
 | 
			
		||||
| 
						 | 
				
			
			@ -280,26 +341,6 @@ 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;
 | 
			
		||||
| 
						 | 
				
			
			@ -309,16 +350,7 @@ type Buffer struct {
 | 
			
		|||
	buf   []byte // encode/decode byte stream
 | 
			
		||||
	index int    // read point
 | 
			
		||||
 | 
			
		||||
	// pools of basic types to amortize allocation.
 | 
			
		||||
	bools   []bool
 | 
			
		||||
	uint32s []uint32
 | 
			
		||||
	uint64s []uint64
 | 
			
		||||
 | 
			
		||||
	// extra pools, only used with pointer_reflect.go
 | 
			
		||||
	int32s   []int32
 | 
			
		||||
	int64s   []int64
 | 
			
		||||
	float32s []float32
 | 
			
		||||
	float64s []float64
 | 
			
		||||
	deterministic bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBuffer allocates a new Buffer and initializes its internal data to
 | 
			
		||||
| 
						 | 
				
			
			@ -343,6 +375,30 @@ func (p *Buffer) SetBuf(s []byte) {
 | 
			
		|||
// Bytes returns the contents of the Buffer.
 | 
			
		||||
func (p *Buffer) Bytes() []byte { return p.buf }
 | 
			
		||||
 | 
			
		||||
// SetDeterministic sets whether to use deterministic serialization.
 | 
			
		||||
//
 | 
			
		||||
// Deterministic serialization guarantees that for a given binary, equal
 | 
			
		||||
// messages will always be serialized to the same bytes. This implies:
 | 
			
		||||
//
 | 
			
		||||
//   - Repeated serialization of a message will return the same bytes.
 | 
			
		||||
//   - Different processes of the same binary (which may be executing on
 | 
			
		||||
//     different machines) will serialize equal messages to the same bytes.
 | 
			
		||||
//
 | 
			
		||||
// Note that the deterministic serialization is NOT canonical across
 | 
			
		||||
// languages. It is not guaranteed to remain stable over time. It is unstable
 | 
			
		||||
// across different builds with schema changes due to unknown fields.
 | 
			
		||||
// Users who need canonical serialization (e.g., persistent storage in a
 | 
			
		||||
// canonical form, fingerprinting, etc.) should define their own
 | 
			
		||||
// canonicalization specification and implement their own serializer rather
 | 
			
		||||
// than relying on this API.
 | 
			
		||||
//
 | 
			
		||||
// If deterministic serialization is requested, map entries will be sorted
 | 
			
		||||
// by keys in lexographical order. This is an implementation detail and
 | 
			
		||||
// subject to change.
 | 
			
		||||
func (p *Buffer) SetDeterministic(deterministic bool) {
 | 
			
		||||
	p.deterministic = deterministic
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Helper routines for simplifying the creation of optional fields of basic type.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -831,22 +887,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
 | 
			
		|||
	return sf, false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mapKeys returns a sort.Interface to be used for sorting the map keys.
 | 
			
		||||
// Map fields may have key types of non-float scalars, strings and enums.
 | 
			
		||||
// The easiest way to sort them in some deterministic order is to use fmt.
 | 
			
		||||
// If this turns out to be inefficient we can always consider other options,
 | 
			
		||||
// such as doing a Schwartzian transform.
 | 
			
		||||
 | 
			
		||||
func mapKeys(vs []reflect.Value) sort.Interface {
 | 
			
		||||
	s := mapKeySorter{
 | 
			
		||||
		vs: vs,
 | 
			
		||||
		// default Less function: textual comparison
 | 
			
		||||
		less: func(a, b reflect.Value) bool {
 | 
			
		||||
			return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	s := mapKeySorter{vs: vs}
 | 
			
		||||
 | 
			
		||||
	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
 | 
			
		||||
	// numeric keys are sorted numerically.
 | 
			
		||||
	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
 | 
			
		||||
	if len(vs) == 0 {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -855,6 +901,12 @@ func mapKeys(vs []reflect.Value) sort.Interface {
 | 
			
		|||
		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
 | 
			
		||||
	case reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s
 | 
			
		||||
| 
						 | 
				
			
			@ -895,3 +947,13 @@ const ProtoPackageIsVersion2 = 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.
 | 
			
		||||
// This type is not subject to any compatibility guarantee.
 | 
			
		||||
type InternalMessageInfo struct {
 | 
			
		||||
	marshal   *marshalInfo
 | 
			
		||||
	unmarshal *unmarshalInfo
 | 
			
		||||
	merge     *mergeInfo
 | 
			
		||||
	discard   *discardInfo
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,12 +36,7 @@ package proto
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 | 
			
		||||
| 
						 | 
				
			
			@ -94,10 +89,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Has(pb Message) bool {
 | 
			
		||||
	if ms.find(pb) != nil {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
	return ms.find(pb) != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *messageSet) Unmarshal(pb Message) error {
 | 
			
		||||
| 
						 | 
				
			
			@ -147,50 +139,9 @@ func skipVarint(buf []byte) []byte {
 | 
			
		|||
	return buf[i+1:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
	var m map[int32]Extension
 | 
			
		||||
	switch exts := exts.(type) {
 | 
			
		||||
	case *XXX_InternalExtensions:
 | 
			
		||||
		if err := encodeExtensions(exts); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		m, _ = exts.extensionsRead()
 | 
			
		||||
	case map[int32]Extension:
 | 
			
		||||
		if err := encodeExtensionsMap(exts); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		m = exts
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, errors.New("proto: not an extension map")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Sort extension IDs to provide a deterministic encoding.
 | 
			
		||||
	// See also enc_map in encode.go.
 | 
			
		||||
	ids := make([]int, 0, len(m))
 | 
			
		||||
	for id := range m {
 | 
			
		||||
		ids = append(ids, int(id))
 | 
			
		||||
	}
 | 
			
		||||
	sort.Ints(ids)
 | 
			
		||||
 | 
			
		||||
	ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
 | 
			
		||||
	for _, id := range ids {
 | 
			
		||||
		e := m[int32(id)]
 | 
			
		||||
		// Remove the wire type and field number varint, as well as the length varint.
 | 
			
		||||
		msg := skipVarint(skipVarint(e.enc))
 | 
			
		||||
 | 
			
		||||
		ms.Item = append(ms.Item, &_MessageSet_Item{
 | 
			
		||||
			TypeId:  Int32(int32(id)),
 | 
			
		||||
			Message: msg,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return Marshal(ms)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
 | 
			
		||||
// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 | 
			
		||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
 | 
			
		||||
// 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 {
 | 
			
		||||
	var m map[int32]Extension
 | 
			
		||||
	switch exts := exts.(type) {
 | 
			
		||||
	case *XXX_InternalExtensions:
 | 
			
		||||
| 
						 | 
				
			
			@ -228,84 +179,3 @@ 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:
 | 
			
		||||
		m, _ = exts.extensionsRead()
 | 
			
		||||
	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]
 | 
			
		||||
		if i > 0 {
 | 
			
		||||
			b.WriteByte(',')
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		msd, ok := messageSetMap[id]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			// Unknown type; we can't render it, so skip it.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		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,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,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 appengine js
 | 
			
		||||
// +build purego appengine js
 | 
			
		||||
 | 
			
		||||
// This file contains an implementation of proto field accesses using package reflect.
 | 
			
		||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
 | 
			
		||||
| 
						 | 
				
			
			@ -38,32 +38,13 @@
 | 
			
		|||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A structPointer is a pointer to a struct.
 | 
			
		||||
type structPointer struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
const unsafeAllowed = false
 | 
			
		||||
 | 
			
		||||
// toStructPointer returns a structPointer equivalent to the given reflect value.
 | 
			
		||||
// The reflect value must itself be a pointer to a struct.
 | 
			
		||||
func toStructPointer(v reflect.Value) structPointer {
 | 
			
		||||
	return structPointer{v}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsNil reports whether p is nil.
 | 
			
		||||
func structPointer_IsNil(p structPointer) bool {
 | 
			
		||||
	return p.v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interface returns the struct pointer as an interface value.
 | 
			
		||||
func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
 | 
			
		||||
	return p.v.Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A field identifies a field in a struct, accessible from a structPointer.
 | 
			
		||||
// A field identifies a field in a struct, accessible from a pointer.
 | 
			
		||||
// In this implementation, a field is identified by the sequence of field indices
 | 
			
		||||
// passed to reflect's FieldByIndex.
 | 
			
		||||
type field []int
 | 
			
		||||
| 
						 | 
				
			
			@ -76,409 +57,304 @@ func toField(f *reflect.StructField) field {
 | 
			
		|||
// invalidField is an invalid field identifier.
 | 
			
		||||
var invalidField = field(nil)
 | 
			
		||||
 | 
			
		||||
// zeroField is a noop when calling pointer.offset.
 | 
			
		||||
var zeroField = field([]int{})
 | 
			
		||||
 | 
			
		||||
// IsValid reports whether the field identifier is valid.
 | 
			
		||||
func (f field) IsValid() bool { return f != nil }
 | 
			
		||||
 | 
			
		||||
// field returns the given field in the struct as a reflect value.
 | 
			
		||||
func structPointer_field(p structPointer, f field) reflect.Value {
 | 
			
		||||
	// Special case: an extension map entry with a value of type T
 | 
			
		||||
	// passes a *T to the struct-handling code with a zero field,
 | 
			
		||||
	// expecting that it will be treated as equivalent to *struct{ X T },
 | 
			
		||||
	// which has the same memory layout. We have to handle that case
 | 
			
		||||
	// specially, because reflect will panic if we call FieldByIndex on a
 | 
			
		||||
	// non-struct.
 | 
			
		||||
	if f == nil {
 | 
			
		||||
		return p.v.Elem()
 | 
			
		||||
// The pointer type is for the table-driven decoder.
 | 
			
		||||
// The implementation here uses a reflect.Value of pointer type to
 | 
			
		||||
// create a generic pointer. In pointer_unsafe.go we use unsafe
 | 
			
		||||
// instead of reflect to implement the same (but faster) interface.
 | 
			
		||||
type pointer struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toPointer converts an interface of pointer type to a pointer
 | 
			
		||||
// that points to the same target.
 | 
			
		||||
func toPointer(i *Message) pointer {
 | 
			
		||||
	return pointer{v: reflect.ValueOf(*i)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// toAddrPointer converts an interface to a pointer that points to
 | 
			
		||||
// the interface data.
 | 
			
		||||
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
 | 
			
		||||
	v := reflect.ValueOf(*i)
 | 
			
		||||
	u := reflect.New(v.Type())
 | 
			
		||||
	u.Elem().Set(v)
 | 
			
		||||
	if deref {
 | 
			
		||||
		u = u.Elem()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p.v.Elem().FieldByIndex(f)
 | 
			
		||||
	return pointer{v: u}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ifield returns the given field in the struct as an interface value.
 | 
			
		||||
func structPointer_ifield(p structPointer, f field) interface{} {
 | 
			
		||||
	return structPointer_field(p, f).Addr().Interface()
 | 
			
		||||
// valToPointer converts v to a pointer.  v must be of pointer type.
 | 
			
		||||
func valToPointer(v reflect.Value) pointer {
 | 
			
		||||
	return pointer{v: v}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bytes returns the address of a []byte field in the struct.
 | 
			
		||||
func structPointer_Bytes(p structPointer, f field) *[]byte {
 | 
			
		||||
	return structPointer_ifield(p, f).(*[]byte)
 | 
			
		||||
// offset converts from a pointer to a structure to a pointer to
 | 
			
		||||
// one of its fields.
 | 
			
		||||
func (p pointer) offset(f field) pointer {
 | 
			
		||||
	return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BytesSlice returns the address of a [][]byte field in the struct.
 | 
			
		||||
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
 | 
			
		||||
	return structPointer_ifield(p, f).(*[][]byte)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bool returns the address of a *bool field in the struct.
 | 
			
		||||
func structPointer_Bool(p structPointer, f field) **bool {
 | 
			
		||||
	return structPointer_ifield(p, f).(**bool)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolVal returns the address of a bool field in the struct.
 | 
			
		||||
func structPointer_BoolVal(p structPointer, f field) *bool {
 | 
			
		||||
	return structPointer_ifield(p, f).(*bool)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolSlice returns the address of a []bool field in the struct.
 | 
			
		||||
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
 | 
			
		||||
	return structPointer_ifield(p, f).(*[]bool)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the address of a *string field in the struct.
 | 
			
		||||
func structPointer_String(p structPointer, f field) **string {
 | 
			
		||||
	return structPointer_ifield(p, f).(**string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringVal returns the address of a string field in the struct.
 | 
			
		||||
func structPointer_StringVal(p structPointer, f field) *string {
 | 
			
		||||
	return structPointer_ifield(p, f).(*string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringSlice returns the address of a []string field in the struct.
 | 
			
		||||
func structPointer_StringSlice(p structPointer, f field) *[]string {
 | 
			
		||||
	return structPointer_ifield(p, f).(*[]string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extensions returns the address of an extension map field in the struct.
 | 
			
		||||
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
 | 
			
		||||
	return structPointer_ifield(p, f).(*XXX_InternalExtensions)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtMap returns the address of an extension map field in the struct.
 | 
			
		||||
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 | 
			
		||||
	return structPointer_ifield(p, f).(*map[int32]Extension)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAt returns the reflect.Value for a pointer to a field in the struct.
 | 
			
		||||
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 | 
			
		||||
	return structPointer_field(p, f).Addr()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetStructPointer writes a *struct field in the struct.
 | 
			
		||||
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
 | 
			
		||||
	structPointer_field(p, f).Set(q.v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStructPointer reads a *struct field in the struct.
 | 
			
		||||
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
 | 
			
		||||
	return structPointer{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StructPointerSlice the address of a []*struct field in the struct.
 | 
			
		||||
func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
 | 
			
		||||
	return structPointerSlice{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A structPointerSlice represents the address of a slice of pointers to structs
 | 
			
		||||
// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
 | 
			
		||||
type structPointerSlice struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p structPointerSlice) Len() int                  { return p.v.Len() }
 | 
			
		||||
func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
 | 
			
		||||
func (p structPointerSlice) Append(q structPointer) {
 | 
			
		||||
	p.v.Set(reflect.Append(p.v, q.v))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	int32Type   = reflect.TypeOf(int32(0))
 | 
			
		||||
	uint32Type  = reflect.TypeOf(uint32(0))
 | 
			
		||||
	float32Type = reflect.TypeOf(float32(0))
 | 
			
		||||
	int64Type   = reflect.TypeOf(int64(0))
 | 
			
		||||
	uint64Type  = reflect.TypeOf(uint64(0))
 | 
			
		||||
	float64Type = reflect.TypeOf(float64(0))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
 | 
			
		||||
// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
 | 
			
		||||
type word32 struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsNil reports whether p is nil.
 | 
			
		||||
func word32_IsNil(p word32) bool {
 | 
			
		||||
func (p pointer) isNil() bool {
 | 
			
		||||
	return p.v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets p to point at a newly allocated word with bits set to x.
 | 
			
		||||
func word32_Set(p word32, o *Buffer, x uint32) {
 | 
			
		||||
	t := p.v.Type().Elem()
 | 
			
		||||
	switch t {
 | 
			
		||||
	case int32Type:
 | 
			
		||||
		if len(o.int32s) == 0 {
 | 
			
		||||
			o.int32s = make([]int32, uint32PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.int32s[0] = int32(x)
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.int32s[0]))
 | 
			
		||||
		o.int32s = o.int32s[1:]
 | 
			
		||||
		return
 | 
			
		||||
	case uint32Type:
 | 
			
		||||
		if len(o.uint32s) == 0 {
 | 
			
		||||
			o.uint32s = make([]uint32, uint32PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.uint32s[0] = x
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.uint32s[0]))
 | 
			
		||||
		o.uint32s = o.uint32s[1:]
 | 
			
		||||
		return
 | 
			
		||||
	case float32Type:
 | 
			
		||||
		if len(o.float32s) == 0 {
 | 
			
		||||
			o.float32s = make([]float32, uint32PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.float32s[0] = math.Float32frombits(x)
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.float32s[0]))
 | 
			
		||||
		o.float32s = o.float32s[1:]
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// must be enum
 | 
			
		||||
	p.v.Set(reflect.New(t))
 | 
			
		||||
	p.v.Elem().SetInt(int64(int32(x)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets the bits pointed at by p, as a uint32.
 | 
			
		||||
func word32_Get(p word32) uint32 {
 | 
			
		||||
	elem := p.v.Elem()
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		return uint32(elem.Int())
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		return uint32(elem.Uint())
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		return math.Float32bits(float32(elem.Float()))
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
 | 
			
		||||
func structPointer_Word32(p structPointer, f field) word32 {
 | 
			
		||||
	return word32{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A word32Val represents a field of type int32, uint32, float32, or enum.
 | 
			
		||||
// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
 | 
			
		||||
type word32Val struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets *p to x.
 | 
			
		||||
func word32Val_Set(p word32Val, x uint32) {
 | 
			
		||||
	switch p.v.Type() {
 | 
			
		||||
	case int32Type:
 | 
			
		||||
		p.v.SetInt(int64(x))
 | 
			
		||||
		return
 | 
			
		||||
	case uint32Type:
 | 
			
		||||
		p.v.SetUint(uint64(x))
 | 
			
		||||
		return
 | 
			
		||||
	case float32Type:
 | 
			
		||||
		p.v.SetFloat(float64(math.Float32frombits(x)))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// must be enum
 | 
			
		||||
	p.v.SetInt(int64(int32(x)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets the bits pointed at by p, as a uint32.
 | 
			
		||||
func word32Val_Get(p word32Val) uint32 {
 | 
			
		||||
	elem := p.v
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		return uint32(elem.Int())
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		return uint32(elem.Uint())
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		return math.Float32bits(float32(elem.Float()))
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
 | 
			
		||||
func structPointer_Word32Val(p structPointer, f field) word32Val {
 | 
			
		||||
	return word32Val{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A word32Slice is a slice of 32-bit values.
 | 
			
		||||
// That is, v.Type() is []int32, []uint32, []float32, or []enum.
 | 
			
		||||
type word32Slice struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word32Slice) Append(x uint32) {
 | 
			
		||||
	n, m := p.v.Len(), p.v.Cap()
 | 
			
		||||
// grow updates the slice s in place to make it one element longer.
 | 
			
		||||
// s must be addressable.
 | 
			
		||||
// Returns the (addressable) new element.
 | 
			
		||||
func grow(s reflect.Value) reflect.Value {
 | 
			
		||||
	n, m := s.Len(), s.Cap()
 | 
			
		||||
	if n < m {
 | 
			
		||||
		p.v.SetLen(n + 1)
 | 
			
		||||
		s.SetLen(n + 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		t := p.v.Type().Elem()
 | 
			
		||||
		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
 | 
			
		||||
		s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
 | 
			
		||||
	}
 | 
			
		||||
	elem := p.v.Index(n)
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		elem.SetInt(int64(int32(x)))
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		elem.SetUint(uint64(x))
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		elem.SetFloat(float64(math.Float32frombits(x)))
 | 
			
		||||
	return s.Index(n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toInt64() *int64 {
 | 
			
		||||
	return p.v.Interface().(*int64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Ptr() **int64 {
 | 
			
		||||
	return p.v.Interface().(**int64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Slice() *[]int64 {
 | 
			
		||||
	return p.v.Interface().(*[]int64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var int32ptr = reflect.TypeOf((*int32)(nil))
 | 
			
		||||
 | 
			
		||||
func (p pointer) toInt32() *int32 {
 | 
			
		||||
	return p.v.Convert(int32ptr).Interface().(*int32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The toInt32Ptr/Slice methods don't work because of enums.
 | 
			
		||||
// Instead, we must use set/get methods for the int32ptr/slice case.
 | 
			
		||||
/*
 | 
			
		||||
	func (p pointer) toInt32Ptr() **int32 {
 | 
			
		||||
		return p.v.Interface().(**int32)
 | 
			
		||||
}
 | 
			
		||||
	func (p pointer) toInt32Slice() *[]int32 {
 | 
			
		||||
		return p.v.Interface().(*[]int32)
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
func (p pointer) getInt32Ptr() *int32 {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		return p.v.Elem().Interface().(*int32)
 | 
			
		||||
	}
 | 
			
		||||
	// an enum
 | 
			
		||||
	return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setInt32Ptr(v int32) {
 | 
			
		||||
	// Allocate value in a *int32. Possibly convert that to a *enum.
 | 
			
		||||
	// Then assign it to a **int32 or **enum.
 | 
			
		||||
	// Note: we can convert *int32 to *enum, but we can't convert
 | 
			
		||||
	// **int32 to **enum!
 | 
			
		||||
	p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word32Slice) Len() int {
 | 
			
		||||
	return p.v.Len()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word32Slice) Index(i int) uint32 {
 | 
			
		||||
	elem := p.v.Index(i)
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		return uint32(elem.Int())
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		return uint32(elem.Uint())
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		return math.Float32bits(float32(elem.Float()))
 | 
			
		||||
// getInt32Slice copies []int32 from p as a new slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) getInt32Slice() []int32 {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		return p.v.Elem().Interface().([]int32)
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
	// an enum
 | 
			
		||||
	// Allocate a []int32, then assign []enum's values into it.
 | 
			
		||||
	// Note: we can't convert []enum to []int32.
 | 
			
		||||
	slice := p.v.Elem()
 | 
			
		||||
	s := make([]int32, slice.Len())
 | 
			
		||||
	for i := 0; i < slice.Len(); i++ {
 | 
			
		||||
		s[i] = int32(slice.Index(i).Int())
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
 | 
			
		||||
func structPointer_Word32Slice(p structPointer, f field) word32Slice {
 | 
			
		||||
	return word32Slice{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// word64 is like word32 but for 64-bit values.
 | 
			
		||||
type word64 struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64_Set(p word64, o *Buffer, x uint64) {
 | 
			
		||||
	t := p.v.Type().Elem()
 | 
			
		||||
	switch t {
 | 
			
		||||
	case int64Type:
 | 
			
		||||
		if len(o.int64s) == 0 {
 | 
			
		||||
			o.int64s = make([]int64, uint64PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.int64s[0] = int64(x)
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.int64s[0]))
 | 
			
		||||
		o.int64s = o.int64s[1:]
 | 
			
		||||
		return
 | 
			
		||||
	case uint64Type:
 | 
			
		||||
		if len(o.uint64s) == 0 {
 | 
			
		||||
			o.uint64s = make([]uint64, uint64PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.uint64s[0] = x
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.uint64s[0]))
 | 
			
		||||
		o.uint64s = o.uint64s[1:]
 | 
			
		||||
		return
 | 
			
		||||
	case float64Type:
 | 
			
		||||
		if len(o.float64s) == 0 {
 | 
			
		||||
			o.float64s = make([]float64, uint64PoolSize)
 | 
			
		||||
		}
 | 
			
		||||
		o.float64s[0] = math.Float64frombits(x)
 | 
			
		||||
		p.v.Set(reflect.ValueOf(&o.float64s[0]))
 | 
			
		||||
		o.float64s = o.float64s[1:]
 | 
			
		||||
// setInt32Slice copies []int32 into p as a new slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) setInt32Slice(v []int32) {
 | 
			
		||||
	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
 | 
			
		||||
		// raw int32 type
 | 
			
		||||
		p.v.Elem().Set(reflect.ValueOf(v))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64_IsNil(p word64) bool {
 | 
			
		||||
	return p.v.IsNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64_Get(p word64) uint64 {
 | 
			
		||||
	elem := p.v.Elem()
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int64:
 | 
			
		||||
		return uint64(elem.Int())
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
		return elem.Uint()
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		return math.Float64bits(elem.Float())
 | 
			
		||||
	// an enum
 | 
			
		||||
	// Allocate a []enum, then assign []int32's values into it.
 | 
			
		||||
	// Note: we can't convert []enum to []int32.
 | 
			
		||||
	slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
 | 
			
		||||
	for i, x := range v {
 | 
			
		||||
		slice.Index(i).SetInt(int64(x))
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
	p.v.Elem().Set(slice)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) appendInt32Slice(v int32) {
 | 
			
		||||
	grow(p.v.Elem()).SetInt(int64(v))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64(p structPointer, f field) word64 {
 | 
			
		||||
	return word64{structPointer_field(p, f)}
 | 
			
		||||
func (p pointer) toUint64() *uint64 {
 | 
			
		||||
	return p.v.Interface().(*uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Ptr() **uint64 {
 | 
			
		||||
	return p.v.Interface().(**uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Slice() *[]uint64 {
 | 
			
		||||
	return p.v.Interface().(*[]uint64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32() *uint32 {
 | 
			
		||||
	return p.v.Interface().(*uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Ptr() **uint32 {
 | 
			
		||||
	return p.v.Interface().(**uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Slice() *[]uint32 {
 | 
			
		||||
	return p.v.Interface().(*[]uint32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBool() *bool {
 | 
			
		||||
	return p.v.Interface().(*bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolPtr() **bool {
 | 
			
		||||
	return p.v.Interface().(**bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolSlice() *[]bool {
 | 
			
		||||
	return p.v.Interface().(*[]bool)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64() *float64 {
 | 
			
		||||
	return p.v.Interface().(*float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Ptr() **float64 {
 | 
			
		||||
	return p.v.Interface().(**float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Slice() *[]float64 {
 | 
			
		||||
	return p.v.Interface().(*[]float64)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32() *float32 {
 | 
			
		||||
	return p.v.Interface().(*float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Ptr() **float32 {
 | 
			
		||||
	return p.v.Interface().(**float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Slice() *[]float32 {
 | 
			
		||||
	return p.v.Interface().(*[]float32)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toString() *string {
 | 
			
		||||
	return p.v.Interface().(*string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringPtr() **string {
 | 
			
		||||
	return p.v.Interface().(**string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringSlice() *[]string {
 | 
			
		||||
	return p.v.Interface().(*[]string)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytes() *[]byte {
 | 
			
		||||
	return p.v.Interface().(*[]byte)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytesSlice() *[][]byte {
 | 
			
		||||
	return p.v.Interface().(*[][]byte)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
 | 
			
		||||
	return p.v.Interface().(*XXX_InternalExtensions)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toOldExtensions() *map[int32]Extension {
 | 
			
		||||
	return p.v.Interface().(*map[int32]Extension)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) getPointer() pointer {
 | 
			
		||||
	return pointer{v: p.v.Elem()}
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setPointer(q pointer) {
 | 
			
		||||
	p.v.Elem().Set(q.v)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) appendPointer(q pointer) {
 | 
			
		||||
	grow(p.v.Elem()).Set(q.v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// word64Val is like word32Val but for 64-bit values.
 | 
			
		||||
type word64Val struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
// getPointerSlice copies []*T from p as a new []pointer.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) getPointerSlice() []pointer {
 | 
			
		||||
	if p.v.IsNil() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	n := p.v.Elem().Len()
 | 
			
		||||
	s := make([]pointer, n)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		s[i] = pointer{v: p.v.Elem().Index(i)}
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
 | 
			
		||||
	switch p.v.Type() {
 | 
			
		||||
	case int64Type:
 | 
			
		||||
		p.v.SetInt(int64(x))
 | 
			
		||||
		return
 | 
			
		||||
	case uint64Type:
 | 
			
		||||
		p.v.SetUint(x)
 | 
			
		||||
		return
 | 
			
		||||
	case float64Type:
 | 
			
		||||
		p.v.SetFloat(math.Float64frombits(x))
 | 
			
		||||
// setPointerSlice copies []pointer into p as a new []*T.
 | 
			
		||||
// This behavior differs from the implementation in pointer_unsafe.go.
 | 
			
		||||
func (p pointer) setPointerSlice(v []pointer) {
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64Val_Get(p word64Val) uint64 {
 | 
			
		||||
	elem := p.v
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int64:
 | 
			
		||||
		return uint64(elem.Int())
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
		return elem.Uint()
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		return math.Float64bits(elem.Float())
 | 
			
		||||
	s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
 | 
			
		||||
	for _, p := range v {
 | 
			
		||||
		s = reflect.Append(s, p.v)
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
	p.v.Elem().Set(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64Val(p structPointer, f field) word64Val {
 | 
			
		||||
	return word64Val{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type word64Slice struct {
 | 
			
		||||
	v reflect.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word64Slice) Append(x uint64) {
 | 
			
		||||
	n, m := p.v.Len(), p.v.Cap()
 | 
			
		||||
	if n < m {
 | 
			
		||||
		p.v.SetLen(n + 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		t := p.v.Type().Elem()
 | 
			
		||||
		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
 | 
			
		||||
	}
 | 
			
		||||
	elem := p.v.Index(n)
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int64:
 | 
			
		||||
		elem.SetInt(int64(int64(x)))
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
		elem.SetUint(uint64(x))
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		elem.SetFloat(float64(math.Float64frombits(x)))
 | 
			
		||||
// getInterfacePointer returns a pointer that points to the
 | 
			
		||||
// interface data of the interface pointed by p.
 | 
			
		||||
func (p pointer) getInterfacePointer() pointer {
 | 
			
		||||
	if p.v.Elem().IsNil() {
 | 
			
		||||
		return pointer{v: p.v.Elem()}
 | 
			
		||||
	}
 | 
			
		||||
	return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word64Slice) Len() int {
 | 
			
		||||
	return p.v.Len()
 | 
			
		||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
 | 
			
		||||
	// TODO: check that p.v.Type().Elem() == t?
 | 
			
		||||
	return p.v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p word64Slice) Index(i int) uint64 {
 | 
			
		||||
	elem := p.v.Index(i)
 | 
			
		||||
	switch elem.Kind() {
 | 
			
		||||
	case reflect.Int64:
 | 
			
		||||
		return uint64(elem.Int())
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
		return uint64(elem.Uint())
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		return math.Float64bits(float64(elem.Float()))
 | 
			
		||||
	}
 | 
			
		||||
	panic("unreachable")
 | 
			
		||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
 | 
			
		||||
	atomicLock.Lock()
 | 
			
		||||
	defer atomicLock.Unlock()
 | 
			
		||||
	*p = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64Slice(p structPointer, f field) word64Slice {
 | 
			
		||||
	return word64Slice{structPointer_field(p, f)}
 | 
			
		||||
}
 | 
			
		||||
var atomicLock sync.Mutex
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,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 !appengine,!js
 | 
			
		||||
// +build !purego,!appengine,!js
 | 
			
		||||
 | 
			
		||||
// This file contains the implementation of the proto field accesses using package unsafe.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,38 +37,13 @@ package proto
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NOTE: These type_Foo functions would more idiomatically be methods,
 | 
			
		||||
// but Go does not allow methods on pointer types, and we must preserve
 | 
			
		||||
// some pointer type for the garbage collector. We use these
 | 
			
		||||
// funcs with clunky names as our poor approximation to methods.
 | 
			
		||||
//
 | 
			
		||||
// An alternative would be
 | 
			
		||||
//	type structPointer struct { p unsafe.Pointer }
 | 
			
		||||
// but that does not registerize as well.
 | 
			
		||||
const unsafeAllowed = true
 | 
			
		||||
 | 
			
		||||
// A structPointer is a pointer to a struct.
 | 
			
		||||
type structPointer unsafe.Pointer
 | 
			
		||||
 | 
			
		||||
// toStructPointer returns a structPointer equivalent to the given reflect value.
 | 
			
		||||
func toStructPointer(v reflect.Value) structPointer {
 | 
			
		||||
	return structPointer(unsafe.Pointer(v.Pointer()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsNil reports whether p is nil.
 | 
			
		||||
func structPointer_IsNil(p structPointer) bool {
 | 
			
		||||
	return p == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interface returns the struct pointer, assumed to have element type t,
 | 
			
		||||
// as an interface value.
 | 
			
		||||
func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
 | 
			
		||||
	return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A field identifies a field in a struct, accessible from a structPointer.
 | 
			
		||||
// A field identifies a field in a struct, accessible from a pointer.
 | 
			
		||||
// In this implementation, a field is identified by its byte offset from the start of the struct.
 | 
			
		||||
type field uintptr
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,191 +55,259 @@ func toField(f *reflect.StructField) field {
 | 
			
		|||
// invalidField is an invalid field identifier.
 | 
			
		||||
const invalidField = ^field(0)
 | 
			
		||||
 | 
			
		||||
// zeroField is a noop when calling pointer.offset.
 | 
			
		||||
const zeroField = field(0)
 | 
			
		||||
 | 
			
		||||
// IsValid reports whether the field identifier is valid.
 | 
			
		||||
func (f field) IsValid() bool {
 | 
			
		||||
	return f != ^field(0)
 | 
			
		||||
	return f != invalidField
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bytes returns the address of a []byte field in the struct.
 | 
			
		||||
func structPointer_Bytes(p structPointer, f field) *[]byte {
 | 
			
		||||
	return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
// The pointer type below is for the new table-driven encoder/decoder.
 | 
			
		||||
// The implementation here uses unsafe.Pointer to create a generic pointer.
 | 
			
		||||
// In pointer_reflect.go we use reflect instead of unsafe to implement
 | 
			
		||||
// the same (but slower) interface.
 | 
			
		||||
type pointer struct {
 | 
			
		||||
	p unsafe.Pointer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BytesSlice returns the address of a [][]byte field in the struct.
 | 
			
		||||
func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
 | 
			
		||||
	return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
// size of pointer
 | 
			
		||||
var ptrSize = unsafe.Sizeof(uintptr(0))
 | 
			
		||||
 | 
			
		||||
// toPointer converts an interface of pointer type to a pointer
 | 
			
		||||
// that points to the same target.
 | 
			
		||||
func toPointer(i *Message) pointer {
 | 
			
		||||
	// Super-tricky - read pointer out of data word of interface value.
 | 
			
		||||
	// Saves ~25ns over the equivalent:
 | 
			
		||||
	// return valToPointer(reflect.ValueOf(*i))
 | 
			
		||||
	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bool returns the address of a *bool field in the struct.
 | 
			
		||||
func structPointer_Bool(p structPointer, f field) **bool {
 | 
			
		||||
	return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolVal returns the address of a bool field in the struct.
 | 
			
		||||
func structPointer_BoolVal(p structPointer, f field) *bool {
 | 
			
		||||
	return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoolSlice returns the address of a []bool field in the struct.
 | 
			
		||||
func structPointer_BoolSlice(p structPointer, f field) *[]bool {
 | 
			
		||||
	return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the address of a *string field in the struct.
 | 
			
		||||
func structPointer_String(p structPointer, f field) **string {
 | 
			
		||||
	return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringVal returns the address of a string field in the struct.
 | 
			
		||||
func structPointer_StringVal(p structPointer, f field) *string {
 | 
			
		||||
	return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringSlice returns the address of a []string field in the struct.
 | 
			
		||||
func structPointer_StringSlice(p structPointer, f field) *[]string {
 | 
			
		||||
	return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtMap returns the address of an extension map field in the struct.
 | 
			
		||||
func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
 | 
			
		||||
	return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 | 
			
		||||
	return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAt returns the reflect.Value for a pointer to a field in the struct.
 | 
			
		||||
func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 | 
			
		||||
	return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetStructPointer writes a *struct field in the struct.
 | 
			
		||||
func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
 | 
			
		||||
	*(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStructPointer reads a *struct field in the struct.
 | 
			
		||||
func structPointer_GetStructPointer(p structPointer, f field) structPointer {
 | 
			
		||||
	return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StructPointerSlice the address of a []*struct field in the struct.
 | 
			
		||||
func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
 | 
			
		||||
	return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
 | 
			
		||||
type structPointerSlice []structPointer
 | 
			
		||||
 | 
			
		||||
func (v *structPointerSlice) Len() int                  { return len(*v) }
 | 
			
		||||
func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
 | 
			
		||||
func (v *structPointerSlice) Append(p structPointer)    { *v = append(*v, p) }
 | 
			
		||||
 | 
			
		||||
// A word32 is the address of a "pointer to 32-bit value" field.
 | 
			
		||||
type word32 **uint32
 | 
			
		||||
 | 
			
		||||
// IsNil reports whether *v is nil.
 | 
			
		||||
func word32_IsNil(p word32) bool {
 | 
			
		||||
	return *p == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets *v to point at a newly allocated word set to x.
 | 
			
		||||
func word32_Set(p word32, o *Buffer, x uint32) {
 | 
			
		||||
	if len(o.uint32s) == 0 {
 | 
			
		||||
		o.uint32s = make([]uint32, uint32PoolSize)
 | 
			
		||||
// toAddrPointer converts an interface to a pointer that points to
 | 
			
		||||
// the interface data.
 | 
			
		||||
func toAddrPointer(i *interface{}, isptr, deref bool) (p 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]}
 | 
			
		||||
	}
 | 
			
		||||
	o.uint32s[0] = x
 | 
			
		||||
	*p = &o.uint32s[0]
 | 
			
		||||
	o.uint32s = o.uint32s[1:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets the value pointed at by *v.
 | 
			
		||||
func word32_Get(p word32) uint32 {
 | 
			
		||||
	return **p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
 | 
			
		||||
func structPointer_Word32(p structPointer, f field) word32 {
 | 
			
		||||
	return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A word32Val is the address of a 32-bit value field.
 | 
			
		||||
type word32Val *uint32
 | 
			
		||||
 | 
			
		||||
// Set sets *p to x.
 | 
			
		||||
func word32Val_Set(p word32Val, x uint32) {
 | 
			
		||||
	*p = x
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets the value pointed at by p.
 | 
			
		||||
func word32Val_Get(p word32Val) uint32 {
 | 
			
		||||
	return *p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
 | 
			
		||||
func structPointer_Word32Val(p structPointer, f field) word32Val {
 | 
			
		||||
	return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A word32Slice is a slice of 32-bit values.
 | 
			
		||||
type word32Slice []uint32
 | 
			
		||||
 | 
			
		||||
func (v *word32Slice) Append(x uint32)    { *v = append(*v, x) }
 | 
			
		||||
func (v *word32Slice) Len() int           { return len(*v) }
 | 
			
		||||
func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
 | 
			
		||||
 | 
			
		||||
// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
 | 
			
		||||
func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
 | 
			
		||||
	return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// word64 is like word32 but for 64-bit values.
 | 
			
		||||
type word64 **uint64
 | 
			
		||||
 | 
			
		||||
func word64_Set(p word64, o *Buffer, x uint64) {
 | 
			
		||||
	if len(o.uint64s) == 0 {
 | 
			
		||||
		o.uint64s = make([]uint64, uint64PoolSize)
 | 
			
		||||
	if deref {
 | 
			
		||||
		p.p = *(*unsafe.Pointer)(p.p)
 | 
			
		||||
	}
 | 
			
		||||
	o.uint64s[0] = x
 | 
			
		||||
	*p = &o.uint64s[0]
 | 
			
		||||
	o.uint64s = o.uint64s[1:]
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64_IsNil(p word64) bool {
 | 
			
		||||
	return *p == nil
 | 
			
		||||
// valToPointer converts v to a pointer. v must be of pointer type.
 | 
			
		||||
func valToPointer(v reflect.Value) pointer {
 | 
			
		||||
	return pointer{p: unsafe.Pointer(v.Pointer())}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64_Get(p word64) uint64 {
 | 
			
		||||
	return **p
 | 
			
		||||
// offset converts from a pointer to a structure to a pointer to
 | 
			
		||||
// one of its fields.
 | 
			
		||||
func (p pointer) offset(f field) pointer {
 | 
			
		||||
	// For safety, we should panic if !f.IsValid, however calling panic causes
 | 
			
		||||
	// this to no longer be inlineable, which is a serious performance cost.
 | 
			
		||||
	/*
 | 
			
		||||
		if !f.IsValid() {
 | 
			
		||||
			panic("invalid field")
 | 
			
		||||
		}
 | 
			
		||||
	*/
 | 
			
		||||
	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64(p structPointer, f field) word64 {
 | 
			
		||||
	return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 | 
			
		||||
func (p pointer) isNil() bool {
 | 
			
		||||
	return p.p == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// word64Val is like word32Val but for 64-bit values.
 | 
			
		||||
type word64Val *uint64
 | 
			
		||||
 | 
			
		||||
func word64Val_Set(p word64Val, o *Buffer, x uint64) {
 | 
			
		||||
	*p = x
 | 
			
		||||
func (p pointer) toInt64() *int64 {
 | 
			
		||||
	return (*int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Ptr() **int64 {
 | 
			
		||||
	return (**int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt64Slice() *[]int64 {
 | 
			
		||||
	return (*[]int64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toInt32() *int32 {
 | 
			
		||||
	return (*int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func word64Val_Get(p word64Val) uint64 {
 | 
			
		||||
	return *p
 | 
			
		||||
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
 | 
			
		||||
/*
 | 
			
		||||
	func (p pointer) toInt32Ptr() **int32 {
 | 
			
		||||
		return (**int32)(p.p)
 | 
			
		||||
	}
 | 
			
		||||
	func (p pointer) toInt32Slice() *[]int32 {
 | 
			
		||||
		return (*[]int32)(p.p)
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
func (p pointer) getInt32Ptr() *int32 {
 | 
			
		||||
	return *(**int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) setInt32Ptr(v int32) {
 | 
			
		||||
	*(**int32)(p.p) = &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64Val(p structPointer, f field) word64Val {
 | 
			
		||||
	return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
 | 
			
		||||
// getInt32Slice loads a []int32 from p.
 | 
			
		||||
// The value returned is aliased with the original slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) getInt32Slice() []int32 {
 | 
			
		||||
	return *(*[]int32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// word64Slice is like word32Slice but for 64-bit values.
 | 
			
		||||
type word64Slice []uint64
 | 
			
		||||
 | 
			
		||||
func (v *word64Slice) Append(x uint64)    { *v = append(*v, x) }
 | 
			
		||||
func (v *word64Slice) Len() int           { return len(*v) }
 | 
			
		||||
func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
 | 
			
		||||
 | 
			
		||||
func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
 | 
			
		||||
	return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 | 
			
		||||
// setInt32Slice stores a []int32 to p.
 | 
			
		||||
// The value set is aliased with the input slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) setInt32Slice(v []int32) {
 | 
			
		||||
	*(*[]int32)(p.p) = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
 | 
			
		||||
func (p pointer) appendInt32Slice(v int32) {
 | 
			
		||||
	s := (*[]int32)(p.p)
 | 
			
		||||
	*s = append(*s, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p pointer) toUint64() *uint64 {
 | 
			
		||||
	return (*uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Ptr() **uint64 {
 | 
			
		||||
	return (**uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint64Slice() *[]uint64 {
 | 
			
		||||
	return (*[]uint64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32() *uint32 {
 | 
			
		||||
	return (*uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Ptr() **uint32 {
 | 
			
		||||
	return (**uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toUint32Slice() *[]uint32 {
 | 
			
		||||
	return (*[]uint32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBool() *bool {
 | 
			
		||||
	return (*bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolPtr() **bool {
 | 
			
		||||
	return (**bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBoolSlice() *[]bool {
 | 
			
		||||
	return (*[]bool)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64() *float64 {
 | 
			
		||||
	return (*float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Ptr() **float64 {
 | 
			
		||||
	return (**float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat64Slice() *[]float64 {
 | 
			
		||||
	return (*[]float64)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32() *float32 {
 | 
			
		||||
	return (*float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Ptr() **float32 {
 | 
			
		||||
	return (**float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toFloat32Slice() *[]float32 {
 | 
			
		||||
	return (*[]float32)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toString() *string {
 | 
			
		||||
	return (*string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringPtr() **string {
 | 
			
		||||
	return (**string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toStringSlice() *[]string {
 | 
			
		||||
	return (*[]string)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytes() *[]byte {
 | 
			
		||||
	return (*[]byte)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toBytesSlice() *[][]byte {
 | 
			
		||||
	return (*[][]byte)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
 | 
			
		||||
	return (*XXX_InternalExtensions)(p.p)
 | 
			
		||||
}
 | 
			
		||||
func (p pointer) toOldExtensions() *map[int32]Extension {
 | 
			
		||||
	return (*map[int32]Extension)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPointerSlice loads []*T from p as a []pointer.
 | 
			
		||||
// The value returned is aliased with the original slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) getPointerSlice() []pointer {
 | 
			
		||||
	// Super-tricky - p should point to a []*T where T is a
 | 
			
		||||
	// message type. We load it as []pointer.
 | 
			
		||||
	return *(*[]pointer)(p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPointerSlice stores []pointer into p as a []*T.
 | 
			
		||||
// The value set is aliased with the input slice.
 | 
			
		||||
// This behavior differs from the implementation in pointer_reflect.go.
 | 
			
		||||
func (p pointer) setPointerSlice(v []pointer) {
 | 
			
		||||
	// Super-tricky - p should point to a []*T where T is a
 | 
			
		||||
	// message type. We store it as []pointer.
 | 
			
		||||
	*(*[]pointer)(p.p) = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getPointer loads the pointer at p and returns it.
 | 
			
		||||
func (p pointer) getPointer() pointer {
 | 
			
		||||
	return pointer{p: *(*unsafe.Pointer)(p.p)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPointer stores the pointer q at p.
 | 
			
		||||
func (p pointer) setPointer(q pointer) {
 | 
			
		||||
	*(*unsafe.Pointer)(p.p) = q.p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// append q to the slice pointed to by p.
 | 
			
		||||
func (p pointer) appendPointer(q pointer) {
 | 
			
		||||
	s := (*[]unsafe.Pointer)(p.p)
 | 
			
		||||
	*s = append(*s, q.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getInterfacePointer returns a pointer that points to the
 | 
			
		||||
// interface data of the interface pointed by p.
 | 
			
		||||
func (p pointer) getInterfacePointer() pointer {
 | 
			
		||||
	// Super-tricky - read pointer out of data word of interface value.
 | 
			
		||||
	return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// asPointerTo returns a reflect.Value that is a pointer to an
 | 
			
		||||
// object of type t stored at p.
 | 
			
		||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
 | 
			
		||||
	return reflect.NewAt(t, p.p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
 | 
			
		||||
	return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
 | 
			
		||||
	return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
 | 
			
		||||
	return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
 | 
			
		||||
	return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
 | 
			
		||||
}
 | 
			
		||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
 | 
			
		||||
	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,42 +58,6 @@ const (
 | 
			
		|||
	WireFixed32    = 5
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const startSize = 10 // initial slice/string sizes
 | 
			
		||||
 | 
			
		||||
// Encoders are defined in encode.go
 | 
			
		||||
// An encoder outputs the full representation of a field, including its
 | 
			
		||||
// tag and encoder type.
 | 
			
		||||
type encoder func(p *Buffer, prop *Properties, base structPointer) error
 | 
			
		||||
 | 
			
		||||
// A valueEncoder encodes a single integer in a particular encoding.
 | 
			
		||||
type valueEncoder func(o *Buffer, x uint64) error
 | 
			
		||||
 | 
			
		||||
// Sizers are defined in encode.go
 | 
			
		||||
// A sizer returns the encoded size of a field, including its tag and encoder
 | 
			
		||||
// type.
 | 
			
		||||
type sizer func(prop *Properties, base structPointer) int
 | 
			
		||||
 | 
			
		||||
// A valueSizer returns the encoded size of a single integer in a particular
 | 
			
		||||
// encoding.
 | 
			
		||||
type valueSizer func(x uint64) int
 | 
			
		||||
 | 
			
		||||
// Decoders are defined in decode.go
 | 
			
		||||
// A decoder creates a value from its wire representation.
 | 
			
		||||
// Unrecognized subelements are saved in unrec.
 | 
			
		||||
type decoder func(p *Buffer, prop *Properties, base structPointer) error
 | 
			
		||||
 | 
			
		||||
// A valueDecoder decodes a single integer in a particular encoding.
 | 
			
		||||
type valueDecoder func(o *Buffer) (x uint64, err error)
 | 
			
		||||
 | 
			
		||||
// A oneofMarshaler does the marshaling for all oneof fields in a message.
 | 
			
		||||
type oneofMarshaler func(Message, *Buffer) error
 | 
			
		||||
 | 
			
		||||
// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
 | 
			
		||||
type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
 | 
			
		||||
 | 
			
		||||
// A oneofSizer does the sizing for all oneof fields in a message.
 | 
			
		||||
type oneofSizer func(Message) int
 | 
			
		||||
 | 
			
		||||
// tagMap is an optimization over map[int]int for typical protocol buffer
 | 
			
		||||
// use-cases. Encoded protocol buffers are often in tag order with small tag
 | 
			
		||||
// numbers.
 | 
			
		||||
| 
						 | 
				
			
			@ -140,13 +104,6 @@ type StructProperties struct {
 | 
			
		|||
	decoderTags      tagMap         // map from proto tag to struct field number
 | 
			
		||||
	decoderOrigNames map[string]int // map from original name to struct field number
 | 
			
		||||
	order            []int          // list of struct field numbers in tag order
 | 
			
		||||
	unrecField       field          // field id of the XXX_unrecognized []byte field
 | 
			
		||||
	extendable       bool           // is this an extendable proto
 | 
			
		||||
 | 
			
		||||
	oneofMarshaler   oneofMarshaler
 | 
			
		||||
	oneofUnmarshaler oneofUnmarshaler
 | 
			
		||||
	oneofSizer       oneofSizer
 | 
			
		||||
	stype            reflect.Type
 | 
			
		||||
 | 
			
		||||
	// OneofTypes contains information about the oneof fields in this message.
 | 
			
		||||
	// It is keyed by the original name of a field.
 | 
			
		||||
| 
						 | 
				
			
			@ -182,41 +139,24 @@ 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; set for []byte only
 | 
			
		||||
	proto3   bool   // whether this is known to be a proto3 field
 | 
			
		||||
	oneof    bool   // whether this is a oneof field
 | 
			
		||||
 | 
			
		||||
	Default    string // default value
 | 
			
		||||
	HasDefault bool   // whether an explicit default was provided
 | 
			
		||||
	def_uint64 uint64
 | 
			
		||||
 | 
			
		||||
	enc           encoder
 | 
			
		||||
	valEnc        valueEncoder // set for bool and numeric types only
 | 
			
		||||
	field         field
 | 
			
		||||
	tagcode       []byte // encoding of EncodeVarint((Tag<<3)|WireType)
 | 
			
		||||
	tagbuf        [8]byte
 | 
			
		||||
	stype         reflect.Type      // set for struct types only
 | 
			
		||||
	sprop         *StructProperties // set for struct types only
 | 
			
		||||
	isMarshaler   bool
 | 
			
		||||
	isUnmarshaler bool
 | 
			
		||||
	stype reflect.Type      // set for struct types only
 | 
			
		||||
	sprop *StructProperties // set for struct types only
 | 
			
		||||
 | 
			
		||||
	mtype    reflect.Type // set for map types only
 | 
			
		||||
	mkeyprop *Properties  // set for map types only
 | 
			
		||||
	mvalprop *Properties  // set for map types only
 | 
			
		||||
 | 
			
		||||
	size    sizer
 | 
			
		||||
	valSize valueSizer // set for bool and numeric types only
 | 
			
		||||
 | 
			
		||||
	dec    decoder
 | 
			
		||||
	valDec valueDecoder // set for bool and numeric types only
 | 
			
		||||
 | 
			
		||||
	// If this is a packable field, this will be the decoder for the packed version of the field.
 | 
			
		||||
	packedDec decoder
 | 
			
		||||
	mtype      reflect.Type // set for map types only
 | 
			
		||||
	MapKeyProp *Properties  // set for map types only
 | 
			
		||||
	MapValProp *Properties  // set for map types only
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String formats the properties in the protobuf struct field tag style.
 | 
			
		||||
func (p *Properties) String() string {
 | 
			
		||||
	s := p.Wire
 | 
			
		||||
	s = ","
 | 
			
		||||
	s += ","
 | 
			
		||||
	s += strconv.Itoa(p.Tag)
 | 
			
		||||
	if p.Required {
 | 
			
		||||
		s += ",req"
 | 
			
		||||
| 
						 | 
				
			
			@ -262,29 +202,14 @@ func (p *Properties) Parse(s string) {
 | 
			
		|||
	switch p.Wire {
 | 
			
		||||
	case "varint":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
		p.valEnc = (*Buffer).EncodeVarint
 | 
			
		||||
		p.valDec = (*Buffer).DecodeVarint
 | 
			
		||||
		p.valSize = sizeVarint
 | 
			
		||||
	case "fixed32":
 | 
			
		||||
		p.WireType = WireFixed32
 | 
			
		||||
		p.valEnc = (*Buffer).EncodeFixed32
 | 
			
		||||
		p.valDec = (*Buffer).DecodeFixed32
 | 
			
		||||
		p.valSize = sizeFixed32
 | 
			
		||||
	case "fixed64":
 | 
			
		||||
		p.WireType = WireFixed64
 | 
			
		||||
		p.valEnc = (*Buffer).EncodeFixed64
 | 
			
		||||
		p.valDec = (*Buffer).DecodeFixed64
 | 
			
		||||
		p.valSize = sizeFixed64
 | 
			
		||||
	case "zigzag32":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
		p.valEnc = (*Buffer).EncodeZigzag32
 | 
			
		||||
		p.valDec = (*Buffer).DecodeZigzag32
 | 
			
		||||
		p.valSize = sizeZigzag32
 | 
			
		||||
	case "zigzag64":
 | 
			
		||||
		p.WireType = WireVarint
 | 
			
		||||
		p.valEnc = (*Buffer).EncodeZigzag64
 | 
			
		||||
		p.valDec = (*Buffer).DecodeZigzag64
 | 
			
		||||
		p.valSize = sizeZigzag64
 | 
			
		||||
	case "bytes", "group":
 | 
			
		||||
		p.WireType = WireBytes
 | 
			
		||||
		// no numeric converter for non-numeric types
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +224,7 @@ func (p *Properties) Parse(s string) {
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
outer:
 | 
			
		||||
	for i := 2; i < len(fields); i++ {
 | 
			
		||||
		f := fields[i]
 | 
			
		||||
		switch {
 | 
			
		||||
| 
						 | 
				
			
			@ -326,256 +252,41 @@ func (p *Properties) Parse(s string) {
 | 
			
		|||
			if i+1 < len(fields) {
 | 
			
		||||
				// Commas aren't escaped, and def is always last.
 | 
			
		||||
				p.Default += "," + strings.Join(fields[i+1:], ",")
 | 
			
		||||
				break
 | 
			
		||||
				break outer
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func logNoSliceEnc(t1, t2 reflect.Type) {
 | 
			
		||||
	fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
 | 
			
		||||
 | 
			
		||||
// Initialize the fields for encoding and decoding.
 | 
			
		||||
func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
 | 
			
		||||
	p.enc = nil
 | 
			
		||||
	p.dec = nil
 | 
			
		||||
	p.size = nil
 | 
			
		||||
 | 
			
		||||
// setFieldProps initializes the field properties for submessages and maps.
 | 
			
		||||
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
 | 
			
		||||
	switch t1 := typ; t1.Kind() {
 | 
			
		||||
	default:
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
 | 
			
		||||
 | 
			
		||||
	// proto3 scalar types
 | 
			
		||||
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_bool
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_bool
 | 
			
		||||
		p.size = size_proto3_bool
 | 
			
		||||
	case reflect.Int32:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_int32
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_int32
 | 
			
		||||
		p.size = size_proto3_int32
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_uint32
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_int32 // can reuse
 | 
			
		||||
		p.size = size_proto3_uint32
 | 
			
		||||
	case reflect.Int64, reflect.Uint64:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_int64
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_int64
 | 
			
		||||
		p.size = size_proto3_int64
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_int32
 | 
			
		||||
		p.size = size_proto3_uint32
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_int64
 | 
			
		||||
		p.size = size_proto3_int64
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		p.enc = (*Buffer).enc_proto3_string
 | 
			
		||||
		p.dec = (*Buffer).dec_proto3_string
 | 
			
		||||
		p.size = size_proto3_string
 | 
			
		||||
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		switch t2 := t1.Elem(); t2.Kind() {
 | 
			
		||||
		default:
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
 | 
			
		||||
			break
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			p.enc = (*Buffer).enc_bool
 | 
			
		||||
			p.dec = (*Buffer).dec_bool
 | 
			
		||||
			p.size = size_bool
 | 
			
		||||
		case reflect.Int32:
 | 
			
		||||
			p.enc = (*Buffer).enc_int32
 | 
			
		||||
			p.dec = (*Buffer).dec_int32
 | 
			
		||||
			p.size = size_int32
 | 
			
		||||
		case reflect.Uint32:
 | 
			
		||||
			p.enc = (*Buffer).enc_uint32
 | 
			
		||||
			p.dec = (*Buffer).dec_int32 // can reuse
 | 
			
		||||
			p.size = size_uint32
 | 
			
		||||
		case reflect.Int64, reflect.Uint64:
 | 
			
		||||
			p.enc = (*Buffer).enc_int64
 | 
			
		||||
			p.dec = (*Buffer).dec_int64
 | 
			
		||||
			p.size = size_int64
 | 
			
		||||
		case reflect.Float32:
 | 
			
		||||
			p.enc = (*Buffer).enc_uint32 // can just treat them as bits
 | 
			
		||||
			p.dec = (*Buffer).dec_int32
 | 
			
		||||
			p.size = size_uint32
 | 
			
		||||
		case reflect.Float64:
 | 
			
		||||
			p.enc = (*Buffer).enc_int64 // can just treat them as bits
 | 
			
		||||
			p.dec = (*Buffer).dec_int64
 | 
			
		||||
			p.size = size_int64
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			p.enc = (*Buffer).enc_string
 | 
			
		||||
			p.dec = (*Buffer).dec_string
 | 
			
		||||
			p.size = size_string
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
		if t1.Elem().Kind() == reflect.Struct {
 | 
			
		||||
			p.stype = t1.Elem()
 | 
			
		||||
			p.isMarshaler = isMarshaler(t1)
 | 
			
		||||
			p.isUnmarshaler = isUnmarshaler(t1)
 | 
			
		||||
			if p.Wire == "bytes" {
 | 
			
		||||
				p.enc = (*Buffer).enc_struct_message
 | 
			
		||||
				p.dec = (*Buffer).dec_struct_message
 | 
			
		||||
				p.size = size_struct_message
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_struct_group
 | 
			
		||||
				p.dec = (*Buffer).dec_struct_group
 | 
			
		||||
				p.size = size_struct_group
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		switch t2 := t1.Elem(); t2.Kind() {
 | 
			
		||||
		default:
 | 
			
		||||
			logNoSliceEnc(t1, t2)
 | 
			
		||||
			break
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			if p.Packed {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_packed_bool
 | 
			
		||||
				p.size = size_slice_packed_bool
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_bool
 | 
			
		||||
				p.size = size_slice_bool
 | 
			
		||||
			}
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_bool
 | 
			
		||||
			p.packedDec = (*Buffer).dec_slice_packed_bool
 | 
			
		||||
		case reflect.Int32:
 | 
			
		||||
			if p.Packed {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_packed_int32
 | 
			
		||||
				p.size = size_slice_packed_int32
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_int32
 | 
			
		||||
				p.size = size_slice_int32
 | 
			
		||||
			}
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_int32
 | 
			
		||||
			p.packedDec = (*Buffer).dec_slice_packed_int32
 | 
			
		||||
		case reflect.Uint32:
 | 
			
		||||
			if p.Packed {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_packed_uint32
 | 
			
		||||
				p.size = size_slice_packed_uint32
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_uint32
 | 
			
		||||
				p.size = size_slice_uint32
 | 
			
		||||
			}
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_int32
 | 
			
		||||
			p.packedDec = (*Buffer).dec_slice_packed_int32
 | 
			
		||||
		case reflect.Int64, reflect.Uint64:
 | 
			
		||||
			if p.Packed {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_packed_int64
 | 
			
		||||
				p.size = size_slice_packed_int64
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_int64
 | 
			
		||||
				p.size = size_slice_int64
 | 
			
		||||
			}
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_int64
 | 
			
		||||
			p.packedDec = (*Buffer).dec_slice_packed_int64
 | 
			
		||||
		case reflect.Uint8:
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_byte
 | 
			
		||||
			if p.proto3 {
 | 
			
		||||
				p.enc = (*Buffer).enc_proto3_slice_byte
 | 
			
		||||
				p.size = size_proto3_slice_byte
 | 
			
		||||
			} else {
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_byte
 | 
			
		||||
				p.size = size_slice_byte
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Float32, reflect.Float64:
 | 
			
		||||
			switch t2.Bits() {
 | 
			
		||||
			case 32:
 | 
			
		||||
				// can just treat them as bits
 | 
			
		||||
				if p.Packed {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_packed_uint32
 | 
			
		||||
					p.size = size_slice_packed_uint32
 | 
			
		||||
				} else {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_uint32
 | 
			
		||||
					p.size = size_slice_uint32
 | 
			
		||||
				}
 | 
			
		||||
				p.dec = (*Buffer).dec_slice_int32
 | 
			
		||||
				p.packedDec = (*Buffer).dec_slice_packed_int32
 | 
			
		||||
			case 64:
 | 
			
		||||
				// can just treat them as bits
 | 
			
		||||
				if p.Packed {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_packed_int64
 | 
			
		||||
					p.size = size_slice_packed_int64
 | 
			
		||||
				} else {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_int64
 | 
			
		||||
					p.size = size_slice_int64
 | 
			
		||||
				}
 | 
			
		||||
				p.dec = (*Buffer).dec_slice_int64
 | 
			
		||||
				p.packedDec = (*Buffer).dec_slice_packed_int64
 | 
			
		||||
			default:
 | 
			
		||||
				logNoSliceEnc(t1, t2)
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			p.enc = (*Buffer).enc_slice_string
 | 
			
		||||
			p.dec = (*Buffer).dec_slice_string
 | 
			
		||||
			p.size = size_slice_string
 | 
			
		||||
		case reflect.Ptr:
 | 
			
		||||
			switch t3 := t2.Elem(); t3.Kind() {
 | 
			
		||||
			default:
 | 
			
		||||
				fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
 | 
			
		||||
				break
 | 
			
		||||
			case reflect.Struct:
 | 
			
		||||
				p.stype = t2.Elem()
 | 
			
		||||
				p.isMarshaler = isMarshaler(t2)
 | 
			
		||||
				p.isUnmarshaler = isUnmarshaler(t2)
 | 
			
		||||
				if p.Wire == "bytes" {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_struct_message
 | 
			
		||||
					p.dec = (*Buffer).dec_slice_struct_message
 | 
			
		||||
					p.size = size_slice_struct_message
 | 
			
		||||
				} else {
 | 
			
		||||
					p.enc = (*Buffer).enc_slice_struct_group
 | 
			
		||||
					p.dec = (*Buffer).dec_slice_struct_group
 | 
			
		||||
					p.size = size_slice_struct_group
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Slice:
 | 
			
		||||
			switch t2.Elem().Kind() {
 | 
			
		||||
			default:
 | 
			
		||||
				fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
 | 
			
		||||
				break
 | 
			
		||||
			case reflect.Uint8:
 | 
			
		||||
				p.enc = (*Buffer).enc_slice_slice_byte
 | 
			
		||||
				p.dec = (*Buffer).dec_slice_slice_byte
 | 
			
		||||
				p.size = size_slice_slice_byte
 | 
			
		||||
			}
 | 
			
		||||
		if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
 | 
			
		||||
			p.stype = t2.Elem()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case reflect.Map:
 | 
			
		||||
		p.enc = (*Buffer).enc_new_map
 | 
			
		||||
		p.dec = (*Buffer).dec_new_map
 | 
			
		||||
		p.size = size_new_map
 | 
			
		||||
 | 
			
		||||
		p.mtype = t1
 | 
			
		||||
		p.mkeyprop = &Properties{}
 | 
			
		||||
		p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
 | 
			
		||||
		p.mvalprop = &Properties{}
 | 
			
		||||
		p.MapKeyProp = &Properties{}
 | 
			
		||||
		p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
 | 
			
		||||
		p.MapValProp = &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),
 | 
			
		||||
			// so we need encoders for the pointer to this type.
 | 
			
		||||
			vtype = reflect.PtrTo(vtype)
 | 
			
		||||
		}
 | 
			
		||||
		p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
 | 
			
		||||
		p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// precalculate tag code
 | 
			
		||||
	wire := p.WireType
 | 
			
		||||
	if p.Packed {
 | 
			
		||||
		wire = WireBytes
 | 
			
		||||
	}
 | 
			
		||||
	x := uint32(p.Tag)<<3 | uint32(wire)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for i = 0; x > 127; i++ {
 | 
			
		||||
		p.tagbuf[i] = 0x80 | uint8(x&0x7F)
 | 
			
		||||
		x >>= 7
 | 
			
		||||
	}
 | 
			
		||||
	p.tagbuf[i] = uint8(x)
 | 
			
		||||
	p.tagcode = p.tagbuf[0 : i+1]
 | 
			
		||||
 | 
			
		||||
	if p.stype != nil {
 | 
			
		||||
		if lockGetProp {
 | 
			
		||||
			p.sprop = GetProperties(p.stype)
 | 
			
		||||
| 
						 | 
				
			
			@ -586,32 +297,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	marshalerType   = reflect.TypeOf((*Marshaler)(nil)).Elem()
 | 
			
		||||
	unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
 | 
			
		||||
	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// isMarshaler reports whether type t implements Marshaler.
 | 
			
		||||
func isMarshaler(t reflect.Type) bool {
 | 
			
		||||
	// We're checking for (likely) pointer-receiver methods
 | 
			
		||||
	// so if t is not a pointer, something is very wrong.
 | 
			
		||||
	// The calls above only invoke isMarshaler on pointer types.
 | 
			
		||||
	if t.Kind() != reflect.Ptr {
 | 
			
		||||
		panic("proto: misuse of isMarshaler")
 | 
			
		||||
	}
 | 
			
		||||
	return t.Implements(marshalerType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isUnmarshaler reports whether type t implements Unmarshaler.
 | 
			
		||||
func isUnmarshaler(t reflect.Type) bool {
 | 
			
		||||
	// We're checking for (likely) pointer-receiver methods
 | 
			
		||||
	// so if t is not a pointer, something is very wrong.
 | 
			
		||||
	// The calls above only invoke isUnmarshaler on pointer types.
 | 
			
		||||
	if t.Kind() != reflect.Ptr {
 | 
			
		||||
		panic("proto: misuse of isUnmarshaler")
 | 
			
		||||
	}
 | 
			
		||||
	return t.Implements(unmarshalerType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init populates the properties from a protocol buffer struct tag.
 | 
			
		||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
 | 
			
		||||
	p.init(typ, name, tag, f, true)
 | 
			
		||||
| 
						 | 
				
			
			@ -621,14 +309,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
 | 
			
		|||
	// "bytes,49,opt,def=hello!"
 | 
			
		||||
	p.Name = name
 | 
			
		||||
	p.OrigName = name
 | 
			
		||||
	if f != nil {
 | 
			
		||||
		p.field = toField(f)
 | 
			
		||||
	}
 | 
			
		||||
	if tag == "" {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	p.Parse(tag)
 | 
			
		||||
	p.setEncAndDec(typ, f, lockGetProp)
 | 
			
		||||
	p.setFieldProps(typ, f, lockGetProp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
| 
						 | 
				
			
			@ -649,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties {
 | 
			
		|||
	sprop, ok := propertiesMap[t]
 | 
			
		||||
	propertiesMu.RUnlock()
 | 
			
		||||
	if ok {
 | 
			
		||||
		if collectStats {
 | 
			
		||||
			stats.Chit++
 | 
			
		||||
		}
 | 
			
		||||
		return sprop
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -664,23 +346,14 @@ func GetProperties(t reflect.Type) *StructProperties {
 | 
			
		|||
// 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.
 | 
			
		||||
	propertiesMap[t] = prop
 | 
			
		||||
 | 
			
		||||
	// build properties
 | 
			
		||||
	prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
 | 
			
		||||
		reflect.PtrTo(t).Implements(extendableProtoV1Type)
 | 
			
		||||
	prop.unrecField = invalidField
 | 
			
		||||
	prop.Prop = make([]*Properties, t.NumField())
 | 
			
		||||
	prop.order = make([]int, t.NumField())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -690,17 +363,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 | 
			
		|||
		name := f.Name
 | 
			
		||||
		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
 | 
			
		||||
 | 
			
		||||
		if f.Name == "XXX_InternalExtensions" { // special case
 | 
			
		||||
			p.enc = (*Buffer).enc_exts
 | 
			
		||||
			p.dec = nil // not needed
 | 
			
		||||
			p.size = size_exts
 | 
			
		||||
		} else if f.Name == "XXX_extensions" { // special case
 | 
			
		||||
			p.enc = (*Buffer).enc_map
 | 
			
		||||
			p.dec = nil // not needed
 | 
			
		||||
			p.size = size_map
 | 
			
		||||
		} else if f.Name == "XXX_unrecognized" { // special case
 | 
			
		||||
			prop.unrecField = toField(&f)
 | 
			
		||||
		}
 | 
			
		||||
		oneof := f.Tag.Get("protobuf_oneof") // special case
 | 
			
		||||
		if oneof != "" {
 | 
			
		||||
			// Oneof fields don't use the traditional protobuf tag.
 | 
			
		||||
| 
						 | 
				
			
			@ -715,9 +377,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 | 
			
		|||
			}
 | 
			
		||||
			print("\n")
 | 
			
		||||
		}
 | 
			
		||||
		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
 | 
			
		||||
			fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Re-order prop.order.
 | 
			
		||||
| 
						 | 
				
			
			@ -728,8 +387,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 | 
			
		|||
	}
 | 
			
		||||
	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
 | 
			
		||||
		var oots []interface{}
 | 
			
		||||
		prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
 | 
			
		||||
		prop.stype = t
 | 
			
		||||
		_, _, _, oots = om.XXX_OneofFuncs()
 | 
			
		||||
 | 
			
		||||
		// Interpret oneof metadata.
 | 
			
		||||
		prop.OneofTypes = make(map[string]*OneofProperties)
 | 
			
		||||
| 
						 | 
				
			
			@ -779,30 +437,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 | 
			
		|||
	return prop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return the Properties object for the x[0]'th field of the structure.
 | 
			
		||||
func propByIndex(t reflect.Type, x []int) *Properties {
 | 
			
		||||
	if len(x) != 1 {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	prop := GetProperties(t)
 | 
			
		||||
	return prop.Prop[x[0]]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the address and type of a pointer to a struct from an interface.
 | 
			
		||||
func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
 | 
			
		||||
	if pb == nil {
 | 
			
		||||
		err = ErrNil
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// get the reflect type of the pointer to the struct.
 | 
			
		||||
	t = reflect.TypeOf(pb)
 | 
			
		||||
	// get the address of the struct.
 | 
			
		||||
	value := reflect.ValueOf(pb)
 | 
			
		||||
	b = toStructPointer(value)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A global registry of enum types.
 | 
			
		||||
// The generated code will register the generated maps by calling RegisterEnum.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -826,20 +460,42 @@ func EnumValueMap(enumType string) map[string]int32 {
 | 
			
		|||
// A registry of all linked message types.
 | 
			
		||||
// The string is a fully-qualified proto name ("pkg.Message").
 | 
			
		||||
var (
 | 
			
		||||
	protoTypes    = make(map[string]reflect.Type)
 | 
			
		||||
	revProtoTypes = make(map[reflect.Type]string)
 | 
			
		||||
	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers
 | 
			
		||||
	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types
 | 
			
		||||
	revProtoTypes  = make(map[reflect.Type]string)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RegisterType is called from generated code and maps from the fully qualified
 | 
			
		||||
// proto name to the type (pointer to struct) of the protocol buffer.
 | 
			
		||||
func RegisterType(x Message, name string) {
 | 
			
		||||
	if _, ok := protoTypes[name]; ok {
 | 
			
		||||
	if _, ok := protoTypedNils[name]; ok {
 | 
			
		||||
		// TODO: Some day, make this a panic.
 | 
			
		||||
		log.Printf("proto: duplicate proto type registered: %s", name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := reflect.TypeOf(x)
 | 
			
		||||
	protoTypes[name] = t
 | 
			
		||||
	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
 | 
			
		||||
		// Generated code always calls RegisterType with nil x.
 | 
			
		||||
		// This check is just for extra safety.
 | 
			
		||||
		protoTypedNils[name] = x
 | 
			
		||||
	} else {
 | 
			
		||||
		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
 | 
			
		||||
	}
 | 
			
		||||
	revProtoTypes[t] = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterMapType is called from generated code and maps from the fully qualified
 | 
			
		||||
// proto name to the native map type of the proto map definition.
 | 
			
		||||
func RegisterMapType(x interface{}, name string) {
 | 
			
		||||
	if reflect.TypeOf(x).Kind() != reflect.Map {
 | 
			
		||||
		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := protoMapTypes[name]; ok {
 | 
			
		||||
		log.Printf("proto: duplicate proto type registered: %s", name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := reflect.TypeOf(x)
 | 
			
		||||
	protoMapTypes[name] = t
 | 
			
		||||
	revProtoTypes[t] = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -855,7 +511,14 @@ func MessageName(x Message) string {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// MessageType returns the message type (pointer to struct) for a named message.
 | 
			
		||||
func MessageType(name string) reflect.Type { return protoTypes[name] }
 | 
			
		||||
// The type is not guaranteed to implement proto.Message if the name refers to a
 | 
			
		||||
// map entry.
 | 
			
		||||
func MessageType(name string) reflect.Type {
 | 
			
		||||
	if t, ok := protoTypedNils[name]; ok {
 | 
			
		||||
		return reflect.TypeOf(t)
 | 
			
		||||
	}
 | 
			
		||||
	return protoMapTypes[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A registry of all linked proto files.
 | 
			
		||||
var (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,654 @@
 | 
			
		|||
// Go support for Protocol Buffers - Google's data interchange format
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2016 The Go Authors.  All rights reserved.
 | 
			
		||||
// https://github.com/golang/protobuf
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
// contributors may be used to endorse or promote products derived from
 | 
			
		||||
// this software without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
package proto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Merge merges the src message into dst.
 | 
			
		||||
// This assumes that dst and src of the same type and are non-nil.
 | 
			
		||||
func (a *InternalMessageInfo) Merge(dst, src Message) {
 | 
			
		||||
	mi := atomicLoadMergeInfo(&a.merge)
 | 
			
		||||
	if mi == nil {
 | 
			
		||||
		mi = getMergeInfo(reflect.TypeOf(dst).Elem())
 | 
			
		||||
		atomicStoreMergeInfo(&a.merge, mi)
 | 
			
		||||
	}
 | 
			
		||||
	mi.merge(toPointer(&dst), toPointer(&src))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mergeInfo struct {
 | 
			
		||||
	typ reflect.Type
 | 
			
		||||
 | 
			
		||||
	initialized int32 // 0: only typ is valid, 1: everything is valid
 | 
			
		||||
	lock        sync.Mutex
 | 
			
		||||
 | 
			
		||||
	fields       []mergeFieldInfo
 | 
			
		||||
	unrecognized field // Offset of XXX_unrecognized
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mergeFieldInfo struct {
 | 
			
		||||
	field field // Offset of field, guaranteed to be valid
 | 
			
		||||
 | 
			
		||||
	// isPointer reports whether the value in the field is a pointer.
 | 
			
		||||
	// This is true for the following situations:
 | 
			
		||||
	//	* Pointer to struct
 | 
			
		||||
	//	* Pointer to basic type (proto2 only)
 | 
			
		||||
	//	* Slice (first value in slice header is a pointer)
 | 
			
		||||
	//	* String (first value in string header is a pointer)
 | 
			
		||||
	isPointer bool
 | 
			
		||||
 | 
			
		||||
	// basicWidth reports the width of the field assuming that it is directly
 | 
			
		||||
	// embedded in the struct (as is the case for basic types in proto3).
 | 
			
		||||
	// The possible values are:
 | 
			
		||||
	// 	0: invalid
 | 
			
		||||
	//	1: bool
 | 
			
		||||
	//	4: int32, uint32, float32
 | 
			
		||||
	//	8: int64, uint64, float64
 | 
			
		||||
	basicWidth int
 | 
			
		||||
 | 
			
		||||
	// Where dst and src are pointers to the types being merged.
 | 
			
		||||
	merge func(dst, src pointer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mergeInfoMap  = map[reflect.Type]*mergeInfo{}
 | 
			
		||||
	mergeInfoLock sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getMergeInfo(t reflect.Type) *mergeInfo {
 | 
			
		||||
	mergeInfoLock.Lock()
 | 
			
		||||
	defer mergeInfoLock.Unlock()
 | 
			
		||||
	mi := mergeInfoMap[t]
 | 
			
		||||
	if mi == nil {
 | 
			
		||||
		mi = &mergeInfo{typ: t}
 | 
			
		||||
		mergeInfoMap[t] = mi
 | 
			
		||||
	}
 | 
			
		||||
	return mi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// merge merges src into dst assuming they are both of type *mi.typ.
 | 
			
		||||
func (mi *mergeInfo) merge(dst, src pointer) {
 | 
			
		||||
	if dst.isNil() {
 | 
			
		||||
		panic("proto: nil destination")
 | 
			
		||||
	}
 | 
			
		||||
	if src.isNil() {
 | 
			
		||||
		return // Nothing to do.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if atomic.LoadInt32(&mi.initialized) == 0 {
 | 
			
		||||
		mi.computeMergeInfo()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, fi := range mi.fields {
 | 
			
		||||
		sfp := src.offset(fi.field)
 | 
			
		||||
 | 
			
		||||
		// As an optimization, we can avoid the merge function call cost
 | 
			
		||||
		// if we know for sure that the source will have no effect
 | 
			
		||||
		// by checking if it is the zero value.
 | 
			
		||||
		if unsafeAllowed {
 | 
			
		||||
			if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if fi.basicWidth > 0 {
 | 
			
		||||
				switch {
 | 
			
		||||
				case fi.basicWidth == 1 && !*sfp.toBool():
 | 
			
		||||
					continue
 | 
			
		||||
				case fi.basicWidth == 4 && *sfp.toUint32() == 0:
 | 
			
		||||
					continue
 | 
			
		||||
				case fi.basicWidth == 8 && *sfp.toUint64() == 0:
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dfp := dst.offset(fi.field)
 | 
			
		||||
		fi.merge(dfp, sfp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: Make this faster?
 | 
			
		||||
	out := dst.asPointerTo(mi.typ).Elem()
 | 
			
		||||
	in := src.asPointerTo(mi.typ).Elem()
 | 
			
		||||
	if emIn, err := extendable(in.Addr().Interface()); err == nil {
 | 
			
		||||
		emOut, _ := extendable(out.Addr().Interface())
 | 
			
		||||
		mIn, muIn := emIn.extensionsRead()
 | 
			
		||||
		if mIn != nil {
 | 
			
		||||
			mOut := emOut.extensionsWrite()
 | 
			
		||||
			muIn.Lock()
 | 
			
		||||
			mergeExtension(mOut, mIn)
 | 
			
		||||
			muIn.Unlock()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if mi.unrecognized.IsValid() {
 | 
			
		||||
		if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
 | 
			
		||||
			*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mi *mergeInfo) computeMergeInfo() {
 | 
			
		||||
	mi.lock.Lock()
 | 
			
		||||
	defer mi.lock.Unlock()
 | 
			
		||||
	if mi.initialized != 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	t := mi.typ
 | 
			
		||||
	n := t.NumField()
 | 
			
		||||
 | 
			
		||||
	props := GetProperties(t)
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		f := t.Field(i)
 | 
			
		||||
		if strings.HasPrefix(f.Name, "XXX_") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mfi := mergeFieldInfo{field: toField(&f)}
 | 
			
		||||
		tf := f.Type
 | 
			
		||||
 | 
			
		||||
		// As an optimization, we can avoid the merge function call cost
 | 
			
		||||
		// if we know for sure that the source will have no effect
 | 
			
		||||
		// by checking if it is the zero value.
 | 
			
		||||
		if unsafeAllowed {
 | 
			
		||||
			switch tf.Kind() {
 | 
			
		||||
			case reflect.Ptr, reflect.Slice, reflect.String:
 | 
			
		||||
				// As a special case, we assume slices and strings are pointers
 | 
			
		||||
				// since we know that the first field in the SliceSlice or
 | 
			
		||||
				// StringHeader is a data pointer.
 | 
			
		||||
				mfi.isPointer = true
 | 
			
		||||
			case reflect.Bool:
 | 
			
		||||
				mfi.basicWidth = 1
 | 
			
		||||
			case reflect.Int32, reflect.Uint32, reflect.Float32:
 | 
			
		||||
				mfi.basicWidth = 4
 | 
			
		||||
			case reflect.Int64, reflect.Uint64, reflect.Float64:
 | 
			
		||||
				mfi.basicWidth = 8
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Unwrap tf to get at its most basic type.
 | 
			
		||||
		var isPointer, isSlice bool
 | 
			
		||||
		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
 | 
			
		||||
			isSlice = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if tf.Kind() == reflect.Ptr {
 | 
			
		||||
			isPointer = true
 | 
			
		||||
			tf = tf.Elem()
 | 
			
		||||
		}
 | 
			
		||||
		if isPointer && isSlice && tf.Kind() != reflect.Struct {
 | 
			
		||||
			panic("both pointer and slice for basic type in " + tf.Name())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch tf.Kind() {
 | 
			
		||||
		case reflect.Int32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
 | 
			
		||||
					/*
 | 
			
		||||
						sfsp := src.toInt32Slice()
 | 
			
		||||
						if *sfsp != nil {
 | 
			
		||||
							dfsp := dst.toInt32Slice()
 | 
			
		||||
							*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
							if *dfsp == nil {
 | 
			
		||||
								*dfsp = []int64{}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					*/
 | 
			
		||||
					sfs := src.getInt32Slice()
 | 
			
		||||
					if sfs != nil {
 | 
			
		||||
						dfs := dst.getInt32Slice()
 | 
			
		||||
						dfs = append(dfs, sfs...)
 | 
			
		||||
						if dfs == nil {
 | 
			
		||||
							dfs = []int32{}
 | 
			
		||||
						}
 | 
			
		||||
						dst.setInt32Slice(dfs)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
 | 
			
		||||
					/*
 | 
			
		||||
						sfpp := src.toInt32Ptr()
 | 
			
		||||
						if *sfpp != nil {
 | 
			
		||||
							dfpp := dst.toInt32Ptr()
 | 
			
		||||
							if *dfpp == nil {
 | 
			
		||||
								*dfpp = Int32(**sfpp)
 | 
			
		||||
							} else {
 | 
			
		||||
								**dfpp = **sfpp
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					*/
 | 
			
		||||
					sfp := src.getInt32Ptr()
 | 
			
		||||
					if sfp != nil {
 | 
			
		||||
						dfp := dst.getInt32Ptr()
 | 
			
		||||
						if dfp == nil {
 | 
			
		||||
							dst.setInt32Ptr(*sfp)
 | 
			
		||||
						} else {
 | 
			
		||||
							*dfp = *sfp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., int32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toInt32(); v != 0 {
 | 
			
		||||
						*dst.toInt32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Int64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toInt64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toInt64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []int64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toInt64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toInt64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Int64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., int64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toInt64(); v != 0 {
 | 
			
		||||
						*dst.toInt64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Uint32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toUint32Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toUint32Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []uint32{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toUint32Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toUint32Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Uint32(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., uint32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toUint32(); v != 0 {
 | 
			
		||||
						*dst.toUint32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Uint64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toUint64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toUint64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []uint64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toUint64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toUint64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Uint64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., uint64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toUint64(); v != 0 {
 | 
			
		||||
						*dst.toUint64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Float32:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toFloat32Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toFloat32Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []float32{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toFloat32Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toFloat32Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Float32(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., float32
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toFloat32(); v != 0 {
 | 
			
		||||
						*dst.toFloat32() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Float64:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toFloat64Slice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toFloat64Slice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []float64{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toFloat64Ptr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toFloat64Ptr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Float64(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., float64
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toFloat64(); v != 0 {
 | 
			
		||||
						*dst.toFloat64() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toBoolSlice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toBoolSlice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []bool{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toBoolPtr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toBoolPtr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = Bool(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., bool
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toBool(); v {
 | 
			
		||||
						*dst.toBool() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isSlice: // E.g., []string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfsp := src.toStringSlice()
 | 
			
		||||
					if *sfsp != nil {
 | 
			
		||||
						dfsp := dst.toStringSlice()
 | 
			
		||||
						*dfsp = append(*dfsp, *sfsp...)
 | 
			
		||||
						if *dfsp == nil {
 | 
			
		||||
							*dfsp = []string{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case isPointer: // E.g., *string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sfpp := src.toStringPtr()
 | 
			
		||||
					if *sfpp != nil {
 | 
			
		||||
						dfpp := dst.toStringPtr()
 | 
			
		||||
						if *dfpp == nil {
 | 
			
		||||
							*dfpp = String(**sfpp)
 | 
			
		||||
						} else {
 | 
			
		||||
							**dfpp = **sfpp
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., string
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					if v := *src.toString(); v != "" {
 | 
			
		||||
						*dst.toString() = v
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Slice:
 | 
			
		||||
			isProto3 := props.Prop[i].proto3
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer:
 | 
			
		||||
				panic("bad pointer in byte slice case in " + tf.Name())
 | 
			
		||||
			case tf.Elem().Kind() != reflect.Uint8:
 | 
			
		||||
				panic("bad element kind in byte slice case in " + tf.Name())
 | 
			
		||||
			case isSlice: // E.g., [][]byte
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sbsp := src.toBytesSlice()
 | 
			
		||||
					if *sbsp != nil {
 | 
			
		||||
						dbsp := dst.toBytesSlice()
 | 
			
		||||
						for _, sb := range *sbsp {
 | 
			
		||||
							if sb == nil {
 | 
			
		||||
								*dbsp = append(*dbsp, nil)
 | 
			
		||||
							} else {
 | 
			
		||||
								*dbsp = append(*dbsp, append([]byte{}, sb...))
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						if *dbsp == nil {
 | 
			
		||||
							*dbsp = [][]byte{}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., []byte
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sbp := src.toBytes()
 | 
			
		||||
					if *sbp != nil {
 | 
			
		||||
						dbp := dst.toBytes()
 | 
			
		||||
						if !isProto3 || len(*sbp) > 0 {
 | 
			
		||||
							*dbp = append([]byte{}, *sbp...)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Struct:
 | 
			
		||||
			switch {
 | 
			
		||||
			case !isPointer:
 | 
			
		||||
				panic(fmt.Sprintf("message field %s without pointer", tf))
 | 
			
		||||
			case isSlice: // E.g., []*pb.T
 | 
			
		||||
				mi := getMergeInfo(tf)
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sps := src.getPointerSlice()
 | 
			
		||||
					if sps != nil {
 | 
			
		||||
						dps := dst.getPointerSlice()
 | 
			
		||||
						for _, sp := range sps {
 | 
			
		||||
							var dp pointer
 | 
			
		||||
							if !sp.isNil() {
 | 
			
		||||
								dp = valToPointer(reflect.New(tf))
 | 
			
		||||
								mi.merge(dp, sp)
 | 
			
		||||
							}
 | 
			
		||||
							dps = append(dps, dp)
 | 
			
		||||
						}
 | 
			
		||||
						if dps == nil {
 | 
			
		||||
							dps = []pointer{}
 | 
			
		||||
						}
 | 
			
		||||
						dst.setPointerSlice(dps)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			default: // E.g., *pb.T
 | 
			
		||||
				mi := getMergeInfo(tf)
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sp := src.getPointer()
 | 
			
		||||
					if !sp.isNil() {
 | 
			
		||||
						dp := dst.getPointer()
 | 
			
		||||
						if dp.isNil() {
 | 
			
		||||
							dp = valToPointer(reflect.New(tf))
 | 
			
		||||
							dst.setPointer(dp)
 | 
			
		||||
						}
 | 
			
		||||
						mi.merge(dp, sp)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Map:
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic("bad pointer or slice in map case in " + tf.Name())
 | 
			
		||||
			default: // E.g., map[K]V
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					sm := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if sm.Len() == 0 {
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					dm := dst.asPointerTo(tf).Elem()
 | 
			
		||||
					if dm.IsNil() {
 | 
			
		||||
						dm.Set(reflect.MakeMap(tf))
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					switch tf.Elem().Kind() {
 | 
			
		||||
					case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							val = reflect.ValueOf(Clone(val.Interface().(Message)))
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					case reflect.Slice: // E.g. Bytes type (e.g., []byte)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					default: // Basic type (e.g., string)
 | 
			
		||||
						for _, key := range sm.MapKeys() {
 | 
			
		||||
							val := sm.MapIndex(key)
 | 
			
		||||
							dm.SetMapIndex(key, val)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case reflect.Interface:
 | 
			
		||||
			// Must be oneof field.
 | 
			
		||||
			switch {
 | 
			
		||||
			case isPointer || isSlice:
 | 
			
		||||
				panic("bad pointer or slice in interface case in " + tf.Name())
 | 
			
		||||
			default: // E.g., interface{}
 | 
			
		||||
				// TODO: Make this faster?
 | 
			
		||||
				mfi.merge = func(dst, src pointer) {
 | 
			
		||||
					su := src.asPointerTo(tf).Elem()
 | 
			
		||||
					if !su.IsNil() {
 | 
			
		||||
						du := dst.asPointerTo(tf).Elem()
 | 
			
		||||
						typ := su.Elem().Type()
 | 
			
		||||
						if du.IsNil() || du.Elem().Type() != typ {
 | 
			
		||||
							du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
 | 
			
		||||
						}
 | 
			
		||||
						sv := su.Elem().Elem().Field(0)
 | 
			
		||||
						if sv.Kind() == reflect.Ptr && sv.IsNil() {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						dv := du.Elem().Elem().Field(0)
 | 
			
		||||
						if dv.Kind() == reflect.Ptr && dv.IsNil() {
 | 
			
		||||
							dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
 | 
			
		||||
						}
 | 
			
		||||
						switch sv.Type().Kind() {
 | 
			
		||||
						case reflect.Ptr: // Proto struct (e.g., *T)
 | 
			
		||||
							Merge(dv.Interface().(Message), sv.Interface().(Message))
 | 
			
		||||
						case reflect.Slice: // E.g. Bytes type (e.g., []byte)
 | 
			
		||||
							dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
 | 
			
		||||
						default: // Basic type (e.g., string)
 | 
			
		||||
							dv.Set(sv)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			panic(fmt.Sprintf("merger not found for type:%s", tf))
 | 
			
		||||
		}
 | 
			
		||||
		mi.fields = append(mi.fields, mfi)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mi.unrecognized = invalidField
 | 
			
		||||
	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
 | 
			
		||||
		if f.Type != reflect.TypeOf([]byte{}) {
 | 
			
		||||
			panic("expected XXX_unrecognized to be of type []byte")
 | 
			
		||||
		}
 | 
			
		||||
		mi.unrecognized = toField(&f)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atomic.StoreInt32(&mi.initialized, 1)
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -50,7 +50,6 @@ import (
 | 
			
		|||
var (
 | 
			
		||||
	newline         = []byte("\n")
 | 
			
		||||
	spaces          = []byte("                                        ")
 | 
			
		||||
	gtNewline       = []byte(">\n")
 | 
			
		||||
	endBraceNewline = []byte("}\n")
 | 
			
		||||
	backslashN      = []byte{'\\', 'n'}
 | 
			
		||||
	backslashR      = []byte{'\\', 'r'}
 | 
			
		||||
| 
						 | 
				
			
			@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// raw is the interface satisfied by RawMessage.
 | 
			
		||||
type raw interface {
 | 
			
		||||
	Bytes() []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func requiresQuotes(u string) bool {
 | 
			
		||||
	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
 | 
			
		||||
	for _, ch := range u {
 | 
			
		||||
| 
						 | 
				
			
			@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
		props := sprops.Prop[i]
 | 
			
		||||
		name := st.Field(i).Name
 | 
			
		||||
 | 
			
		||||
		if name == "XXX_NoUnkeyedLiteral" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if strings.HasPrefix(name, "XXX_") {
 | 
			
		||||
			// There are two XXX_ fields:
 | 
			
		||||
			//   XXX_unrecognized []byte
 | 
			
		||||
| 
						 | 
				
			
			@ -355,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
 | 
			
		||||
				if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
							return err
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if err := tm.writeAny(w, val, props.mvalprop); err != nil {
 | 
			
		||||
					if err := tm.writeAny(w, val, props.MapValProp); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if b, ok := fv.Interface().(raw); ok {
 | 
			
		||||
			if err := writeRaw(w, b.Bytes()); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Enums have a String method, so writeAny will work fine.
 | 
			
		||||
		if err := tm.writeAny(w, fv, props); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
 | 
			
		||||
	// Extensions (the XXX_extensions field).
 | 
			
		||||
	pv := sv.Addr()
 | 
			
		||||
	if _, ok := extendable(pv.Interface()); ok {
 | 
			
		||||
	if _, err := extendable(pv.Interface()); err == nil {
 | 
			
		||||
		if err := tm.writeExtensions(w, pv); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeRaw writes an uninterpreted raw message.
 | 
			
		||||
func writeRaw(w *textWriter, b []byte) error {
 | 
			
		||||
	if err := w.WriteByte('<'); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !w.compact {
 | 
			
		||||
		if err := w.WriteByte('\n'); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	w.indent()
 | 
			
		||||
	if err := writeUnknownStruct(w, b); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	w.unindent()
 | 
			
		||||
	if err := w.WriteByte('>'); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeAny writes an arbitrary field.
 | 
			
		||||
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
 | 
			
		||||
	v = reflect.Indirect(v)
 | 
			
		||||
| 
						 | 
				
			
			@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		w.indent()
 | 
			
		||||
		if v.CanAddr() {
 | 
			
		||||
			// Calling v.Interface on a struct causes the reflect package to
 | 
			
		||||
			// copy the entire struct. This is racy with the new Marshaler
 | 
			
		||||
			// since we atomically update the XXX_sizecache.
 | 
			
		||||
			//
 | 
			
		||||
			// Thus, we retrieve a pointer to the struct if possible to avoid
 | 
			
		||||
			// a race since v.Interface on the pointer doesn't copy the struct.
 | 
			
		||||
			//
 | 
			
		||||
			// If v is not addressable, then we are not worried about a race
 | 
			
		||||
			// since it implies that the binary Marshaler cannot possibly be
 | 
			
		||||
			// mutating this value.
 | 
			
		||||
			v = v.Addr()
 | 
			
		||||
		}
 | 
			
		||||
		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
 | 
			
		||||
			text, err := etm.MarshalText()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 | 
			
		|||
			if _, err = w.Write(text); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else if err := tm.writeStruct(w, v); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else {
 | 
			
		||||
			if v.Kind() == reflect.Ptr {
 | 
			
		||||
				v = v.Elem()
 | 
			
		||||
			}
 | 
			
		||||
			if err := tm.writeStruct(w, v); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		w.unindent()
 | 
			
		||||
		if err := w.WriteByte(ket); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -206,7 +206,6 @@ func (p *textParser) advance() {
 | 
			
		|||
 | 
			
		||||
var (
 | 
			
		||||
	errBadUTF8 = errors.New("proto: bad UTF-8")
 | 
			
		||||
	errBadHex  = errors.New("proto: bad hexadecimal")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func unquoteC(s string, quote rune) (string, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) {
 | 
			
		|||
		return "?", s, nil // trigraph workaround
 | 
			
		||||
	case '\'', '"', '\\':
 | 
			
		||||
		return string(r), s, nil
 | 
			
		||||
	case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
 | 
			
		||||
	case '0', '1', '2', '3', '4', '5', '6', '7':
 | 
			
		||||
		if len(s) < 2 {
 | 
			
		||||
			return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
 | 
			
		||||
		}
 | 
			
		||||
		base := 8
 | 
			
		||||
		ss := s[:2]
 | 
			
		||||
		ss := string(r) + s[:2]
 | 
			
		||||
		s = s[2:]
 | 
			
		||||
		if r == 'x' || r == 'X' {
 | 
			
		||||
			base = 16
 | 
			
		||||
		} else {
 | 
			
		||||
			ss = string(r) + ss
 | 
			
		||||
		}
 | 
			
		||||
		i, err := strconv.ParseUint(ss, base, 8)
 | 
			
		||||
		i, err := strconv.ParseUint(ss, 8, 8)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", "", err
 | 
			
		||||
			return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
 | 
			
		||||
		}
 | 
			
		||||
		return string([]byte{byte(i)}), s, nil
 | 
			
		||||
	case 'u', 'U':
 | 
			
		||||
		n := 4
 | 
			
		||||
		if r == 'U' {
 | 
			
		||||
	case 'x', 'X', 'u', 'U':
 | 
			
		||||
		var n int
 | 
			
		||||
		switch r {
 | 
			
		||||
		case 'x', 'X':
 | 
			
		||||
			n = 2
 | 
			
		||||
		case 'u':
 | 
			
		||||
			n = 4
 | 
			
		||||
		case 'U':
 | 
			
		||||
			n = 8
 | 
			
		||||
		}
 | 
			
		||||
		if len(s) < n {
 | 
			
		||||
			return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bs := make([]byte, n/2)
 | 
			
		||||
		for i := 0; i < n; i += 2 {
 | 
			
		||||
			a, ok1 := unhex(s[i])
 | 
			
		||||
			b, ok2 := unhex(s[i+1])
 | 
			
		||||
			if !ok1 || !ok2 {
 | 
			
		||||
				return "", "", errBadHex
 | 
			
		||||
			}
 | 
			
		||||
			bs[i/2] = a<<4 | b
 | 
			
		||||
			return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
 | 
			
		||||
		}
 | 
			
		||||
		ss := s[:n]
 | 
			
		||||
		s = s[n:]
 | 
			
		||||
		return string(bs), s, nil
 | 
			
		||||
		i, err := strconv.ParseUint(ss, 16, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
 | 
			
		||||
		}
 | 
			
		||||
		if r == 'x' || r == 'X' {
 | 
			
		||||
			return string([]byte{byte(i)}), s, nil
 | 
			
		||||
		}
 | 
			
		||||
		if i > utf8.MaxRune {
 | 
			
		||||
			return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
 | 
			
		||||
		}
 | 
			
		||||
		return string(i), s, nil
 | 
			
		||||
	}
 | 
			
		||||
	return "", "", fmt.Errorf(`unknown escape \%c`, r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Adapted from src/pkg/strconv/quote.go.
 | 
			
		||||
func unhex(b byte) (v byte, ok bool) {
 | 
			
		||||
	switch {
 | 
			
		||||
	case '0' <= b && b <= '9':
 | 
			
		||||
		return b - '0', true
 | 
			
		||||
	case 'a' <= b && b <= 'f':
 | 
			
		||||
		return b - 'a' + 10, true
 | 
			
		||||
	case 'A' <= b && b <= 'F':
 | 
			
		||||
		return b - 'A' + 10, true
 | 
			
		||||
	}
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Back off the parser by one token. Can only be done between calls to next().
 | 
			
		||||
// It makes the next advance() a no-op.
 | 
			
		||||
func (p *textParser) back() { p.backed = true }
 | 
			
		||||
| 
						 | 
				
			
			@ -644,17 +630,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.mkeyprop); err != nil {
 | 
			
		||||
					if err := p.readAny(key, props.MapKeyProp); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if err := p.consumeOptionalSeparator(); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				case "value":
 | 
			
		||||
					if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
 | 
			
		||||
					if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if err := p.readAny(val, props.mvalprop); err != nil {
 | 
			
		||||
					if err := p.readAny(val, props.MapValProp); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					if err := p.consumeOptionalSeparator(); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) {
 | 
			
		|||
		if tok.err != nil {
 | 
			
		||||
			return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
 | 
			
		||||
		}
 | 
			
		||||
		if p.done && tok.value != "]" {
 | 
			
		||||
			return "", p.errorf("unclosed type_url or extension name")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Join(parts, ""), nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 | 
			
		|||
		return p.readStruct(fv, terminator)
 | 
			
		||||
	case reflect.Uint32:
 | 
			
		||||
		if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
 | 
			
		||||
			fv.SetUint(x)
 | 
			
		||||
			fv.SetUint(uint64(x))
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Uint64:
 | 
			
		||||
| 
						 | 
				
			
			@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 | 
			
		|||
// UnmarshalText returns *RequiredNotSetError.
 | 
			
		||||
func UnmarshalText(s string, pb Message) error {
 | 
			
		||||
	if um, ok := pb.(encoding.TextUnmarshaler); ok {
 | 
			
		||||
		err := um.UnmarshalText([]byte(s))
 | 
			
		||||
		return err
 | 
			
		||||
		return um.UnmarshalText([]byte(s))
 | 
			
		||||
	}
 | 
			
		||||
	pb.Reset()
 | 
			
		||||
	v := reflect.ValueOf(pb)
 | 
			
		||||
	if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
 | 
			
		||||
		return pe
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
	return newTextParser(s).readStruct(v.Elem(), "")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,173 @@
 | 
			
		|||
# Building `sys/unix`
 | 
			
		||||
 | 
			
		||||
The sys/unix package provides access to the raw system call interface of the
 | 
			
		||||
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
 | 
			
		||||
 | 
			
		||||
Porting Go to a new architecture/OS combination or adding syscalls, types, or
 | 
			
		||||
constants to an existing architecture/OS pair requires some manual effort;
 | 
			
		||||
however, there are tools that automate much of the process.
 | 
			
		||||
 | 
			
		||||
## Build Systems
 | 
			
		||||
 | 
			
		||||
There are currently two ways we generate the necessary files. We are currently
 | 
			
		||||
migrating the build system to use containers so the builds are reproducible.
 | 
			
		||||
This is being done on an OS-by-OS basis. Please update this documentation as
 | 
			
		||||
components of the build system change.
 | 
			
		||||
 | 
			
		||||
### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
 | 
			
		||||
 | 
			
		||||
The old build system generates the Go files based on the C header files
 | 
			
		||||
present on your system. This means that files
 | 
			
		||||
for a given GOOS/GOARCH pair must be generated on a system with that OS and
 | 
			
		||||
architecture. This also means that the generated code can differ from system
 | 
			
		||||
to system, based on differences in the header files.
 | 
			
		||||
 | 
			
		||||
To avoid this, if you are using the old build system, only generate the Go
 | 
			
		||||
files on an installation with unmodified header files. It is also important to
 | 
			
		||||
keep track of which version of the OS the files were generated from (ex.
 | 
			
		||||
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
 | 
			
		||||
and have each OS upgrade correspond to a single change.
 | 
			
		||||
 | 
			
		||||
To build the files for your current OS and architecture, make sure GOOS and
 | 
			
		||||
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
 | 
			
		||||
your specific system. Running `mkall.sh -n` shows the commands that will be run.
 | 
			
		||||
 | 
			
		||||
Requirements: bash, perl, go
 | 
			
		||||
 | 
			
		||||
### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
 | 
			
		||||
 | 
			
		||||
The new build system uses a Docker container to generate the go files directly
 | 
			
		||||
from source checkouts of the kernel and various system libraries. This means
 | 
			
		||||
that on any platform that supports Docker, all the files using the new build
 | 
			
		||||
system can be generated at once, and generated files will not change based on
 | 
			
		||||
what the person running the scripts has installed on their computer.
 | 
			
		||||
 | 
			
		||||
The OS specific files for the new build system are located in the `${GOOS}`
 | 
			
		||||
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
 | 
			
		||||
the kernel or system library updates, modify the Dockerfile at
 | 
			
		||||
`${GOOS}/Dockerfile` to checkout the new release of the source.
 | 
			
		||||
 | 
			
		||||
To build all the files under the new build system, you must be on an amd64/Linux
 | 
			
		||||
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
 | 
			
		||||
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
 | 
			
		||||
system. Running `mkall.sh -n` shows the commands that will be run.
 | 
			
		||||
 | 
			
		||||
Requirements: bash, perl, go, docker
 | 
			
		||||
 | 
			
		||||
## Component files
 | 
			
		||||
 | 
			
		||||
This section describes the various files used in the code generation process.
 | 
			
		||||
It also contains instructions on how to modify these files to add a new
 | 
			
		||||
architecture/OS or to add additional syscalls, types, or constants. Note that
 | 
			
		||||
if you are using the new build system, the scripts cannot be called normally.
 | 
			
		||||
They must be called from within the docker container.
 | 
			
		||||
 | 
			
		||||
### asm files
 | 
			
		||||
 | 
			
		||||
The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
 | 
			
		||||
call dispatch. There are three entry points:
 | 
			
		||||
```
 | 
			
		||||
  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
 | 
			
		||||
  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
 | 
			
		||||
  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
 | 
			
		||||
```
 | 
			
		||||
The first and second are the standard ones; they differ only in how many
 | 
			
		||||
arguments can be passed to the kernel. The third is for low-level use by the
 | 
			
		||||
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
 | 
			
		||||
let it know that a system call is running.
 | 
			
		||||
 | 
			
		||||
When porting Go to an new architecture/OS, this file must be implemented for
 | 
			
		||||
each GOOS/GOARCH pair.
 | 
			
		||||
 | 
			
		||||
### mksysnum
 | 
			
		||||
 | 
			
		||||
Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
 | 
			
		||||
for the old system). This script takes in a list of header files containing the
 | 
			
		||||
syscall number declarations and parses them to produce the corresponding list of
 | 
			
		||||
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
 | 
			
		||||
constants.
 | 
			
		||||
 | 
			
		||||
Adding new syscall numbers is mostly done by running the build on a sufficiently
 | 
			
		||||
new installation of the target OS (or updating the source checkouts for the
 | 
			
		||||
new build system). However, depending on the OS, you make need to update the
 | 
			
		||||
parsing in mksysnum.
 | 
			
		||||
 | 
			
		||||
### mksyscall.pl
 | 
			
		||||
 | 
			
		||||
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
 | 
			
		||||
hand-written Go files which implement system calls (for unix, the specific OS,
 | 
			
		||||
or the specific OS/Architecture pair respectively) that need special handling
 | 
			
		||||
and list `//sys` comments giving prototypes for ones that can be generated.
 | 
			
		||||
 | 
			
		||||
The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
 | 
			
		||||
them into syscalls. This requires the name of the prototype in the comment to
 | 
			
		||||
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
 | 
			
		||||
prototype can be exported (capitalized) or not.
 | 
			
		||||
 | 
			
		||||
Adding a new syscall often just requires adding a new `//sys` function prototype
 | 
			
		||||
with the desired arguments and a capitalized name so it is exported. However, if
 | 
			
		||||
you want the interface to the syscall to be different, often one will make an
 | 
			
		||||
unexported `//sys` prototype, an then write a custom wrapper in
 | 
			
		||||
`syscall_${GOOS}.go`.
 | 
			
		||||
 | 
			
		||||
### types files
 | 
			
		||||
 | 
			
		||||
For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
 | 
			
		||||
`types_${GOOS}.go` on the old system). This file includes standard C headers and
 | 
			
		||||
creates Go type aliases to the corresponding C types. The file is then fed
 | 
			
		||||
through godef to get the Go compatible definitions. Finally, the generated code
 | 
			
		||||
is fed though mkpost.go to format the code correctly and remove any hidden or
 | 
			
		||||
private identifiers. This cleaned-up code is written to
 | 
			
		||||
`ztypes_${GOOS}_${GOARCH}.go`.
 | 
			
		||||
 | 
			
		||||
The hardest part about preparing this file is figuring out which headers to
 | 
			
		||||
include and which symbols need to be `#define`d to get the actual data
 | 
			
		||||
structures that pass through to the kernel system calls. Some C libraries
 | 
			
		||||
preset alternate versions for binary compatibility and translate them on the
 | 
			
		||||
way in and out of system calls, but there is almost always a `#define` that can
 | 
			
		||||
get the real ones.
 | 
			
		||||
See `types_darwin.go` and `linux/types.go` for examples.
 | 
			
		||||
 | 
			
		||||
To add a new type, add in the necessary include statement at the top of the
 | 
			
		||||
file (if it is not already there) and add in a type alias line. Note that if
 | 
			
		||||
your type is significantly different on different architectures, you may need
 | 
			
		||||
some `#if/#elif` macros in your include statements.
 | 
			
		||||
 | 
			
		||||
### mkerrors.sh
 | 
			
		||||
 | 
			
		||||
This script is used to generate the system's various constants. This doesn't
 | 
			
		||||
just include the error numbers and error strings, but also the signal numbers
 | 
			
		||||
an a wide variety of miscellaneous constants. The constants come from the list
 | 
			
		||||
of include files in the `includes_${uname}` variable. A regex then picks out
 | 
			
		||||
the desired `#define` statements, and generates the corresponding Go constants.
 | 
			
		||||
The error numbers and strings are generated from `#include <errno.h>`, and the
 | 
			
		||||
signal numbers and strings are generated from `#include <signal.h>`. All of
 | 
			
		||||
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
 | 
			
		||||
`_errors.c`, which prints out all the constants.
 | 
			
		||||
 | 
			
		||||
To add a constant, add the header that includes it to the appropriate variable.
 | 
			
		||||
Then, edit the regex (if necessary) to match the desired constant. Avoid making
 | 
			
		||||
the regex too broad to avoid matching unintended constants.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Generated files
 | 
			
		||||
 | 
			
		||||
### `zerror_${GOOS}_${GOARCH}.go`
 | 
			
		||||
 | 
			
		||||
A file containing all of the system's generated error numbers, error strings,
 | 
			
		||||
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
 | 
			
		||||
 | 
			
		||||
### `zsyscall_${GOOS}_${GOARCH}.go`
 | 
			
		||||
 | 
			
		||||
A file containing all the generated syscalls for a specific GOOS and GOARCH.
 | 
			
		||||
Generated by `mksyscall.pl` (see above).
 | 
			
		||||
 | 
			
		||||
### `zsysnum_${GOOS}_${GOARCH}.go`
 | 
			
		||||
 | 
			
		||||
A list of numeric constants for all the syscall number of the specific GOOS
 | 
			
		||||
and GOARCH. Generated by mksysnum (see above).
 | 
			
		||||
 | 
			
		||||
### `ztypes_${GOOS}_${GOARCH}.go`
 | 
			
		||||
 | 
			
		||||
A file containing Go types for passing into (or returning from) syscalls.
 | 
			
		||||
Generated by godefs and the types file (see above).
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
// 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.
 | 
			
		||||
 | 
			
		||||
// CPU affinity functions
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
 | 
			
		||||
 | 
			
		||||
// CPUSet represents a CPU affinity mask.
 | 
			
		||||
type CPUSet [cpuSetSize]cpuMask
 | 
			
		||||
 | 
			
		||||
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
 | 
			
		||||
	_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
 | 
			
		||||
	if e != 0 {
 | 
			
		||||
		return errnoErr(e)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
 | 
			
		||||
// If pid is 0 the calling thread is used.
 | 
			
		||||
func SchedGetaffinity(pid int, set *CPUSet) error {
 | 
			
		||||
	return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
 | 
			
		||||
// If pid is 0 the calling thread is used.
 | 
			
		||||
func SchedSetaffinity(pid int, set *CPUSet) error {
 | 
			
		||||
	return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Zero clears the set s, so that it contains no CPUs.
 | 
			
		||||
func (s *CPUSet) Zero() {
 | 
			
		||||
	for i := range s {
 | 
			
		||||
		s[i] = 0
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cpuBitsIndex(cpu int) int {
 | 
			
		||||
	return cpu / _NCPUBITS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cpuBitsMask(cpu int) cpuMask {
 | 
			
		||||
	return cpuMask(1 << (uint(cpu) % _NCPUBITS))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set adds cpu to the set s.
 | 
			
		||||
func (s *CPUSet) Set(cpu int) {
 | 
			
		||||
	i := cpuBitsIndex(cpu)
 | 
			
		||||
	if i < len(s) {
 | 
			
		||||
		s[i] |= cpuBitsMask(cpu)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Clear removes cpu from the set s.
 | 
			
		||||
func (s *CPUSet) Clear(cpu int) {
 | 
			
		||||
	i := cpuBitsIndex(cpu)
 | 
			
		||||
	if i < len(s) {
 | 
			
		||||
		s[i] &^= cpuBitsMask(cpu)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsSet reports whether cpu is in the set s.
 | 
			
		||||
func (s *CPUSet) IsSet(cpu int) bool {
 | 
			
		||||
	i := cpuBitsIndex(cpu)
 | 
			
		||||
	if i < len(s) {
 | 
			
		||||
		return s[i]&cpuBitsMask(cpu) != 0
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count returns the number of CPUs in the set s.
 | 
			
		||||
func (s *CPUSet) Count() int {
 | 
			
		||||
	c := 0
 | 
			
		||||
	for _, b := range s {
 | 
			
		||||
		c += onesCount64(uint64(b))
 | 
			
		||||
	}
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
 | 
			
		||||
// Once this package can require Go 1.9, we can delete this
 | 
			
		||||
// and update the caller to use bits.OnesCount64.
 | 
			
		||||
func onesCount64(x uint64) int {
 | 
			
		||||
	const m0 = 0x5555555555555555 // 01010101 ...
 | 
			
		||||
	const m1 = 0x3333333333333333 // 00110011 ...
 | 
			
		||||
	const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
 | 
			
		||||
	const m3 = 0x00ff00ff00ff00ff // etc.
 | 
			
		||||
	const m4 = 0x0000ffff0000ffff
 | 
			
		||||
 | 
			
		||||
	// Implementation: Parallel summing of adjacent bits.
 | 
			
		||||
	// See "Hacker's Delight", Chap. 5: Counting Bits.
 | 
			
		||||
	// The following pattern shows the general approach:
 | 
			
		||||
	//
 | 
			
		||||
	//   x = x>>1&(m0&m) + x&(m0&m)
 | 
			
		||||
	//   x = x>>2&(m1&m) + x&(m1&m)
 | 
			
		||||
	//   x = x>>4&(m2&m) + x&(m2&m)
 | 
			
		||||
	//   x = x>>8&(m3&m) + x&(m3&m)
 | 
			
		||||
	//   x = x>>16&(m4&m) + x&(m4&m)
 | 
			
		||||
	//   x = x>>32&(m5&m) + x&(m5&m)
 | 
			
		||||
	//   return int(x)
 | 
			
		||||
	//
 | 
			
		||||
	// Masking (& operations) can be left away when there's no
 | 
			
		||||
	// danger that a field's sum will carry over into the next
 | 
			
		||||
	// field: Since the result cannot be > 64, 8 bits is enough
 | 
			
		||||
	// and we can ignore the masks for the shifts by 8 and up.
 | 
			
		||||
	// Per "Hacker's Delight", the first line can be simplified
 | 
			
		||||
	// more, but it saves at best one instruction, so we leave
 | 
			
		||||
	// it alone for clarity.
 | 
			
		||||
	const m = 1<<64 - 1
 | 
			
		||||
	x = x>>1&(m0&m) + x&(m0&m)
 | 
			
		||||
	x = x>>2&(m1&m) + x&(m1&m)
 | 
			
		||||
	x = (x>>4 + x) & (m2 & m)
 | 
			
		||||
	x += x >> 8
 | 
			
		||||
	x += x >> 16
 | 
			
		||||
	x += x >> 32
 | 
			
		||||
	return int(x) & (1<<7 - 1)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
// +build go1.9
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
type Signal = syscall.Signal
 | 
			
		||||
type Errno = syscall.Errno
 | 
			
		||||
type SysProcAttr = syscall.SysProcAttr
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
// 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 !gccgo
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
TEXT ·syscall6(SB),NOSPLIT,$0-88
 | 
			
		||||
	JMP	syscall·syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
 | 
			
		||||
	JMP	syscall·rawSyscall6(SB)
 | 
			
		||||
| 
						 | 
				
			
			@ -13,17 +13,17 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-64
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-88
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall9(SB),NOSPLIT,$0-112
 | 
			
		||||
TEXT	·Syscall9(SB),NOSPLIT,$0-104
 | 
			
		||||
	JMP	syscall·Syscall9(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-64
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-88
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·RawSyscall6(SB)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,21 +10,51 @@
 | 
			
		|||
// System calls for 386, Linux
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
 | 
			
		||||
// instead of the glibc-specific "CALL 0x10(GS)".
 | 
			
		||||
#define INVOKE_SYSCALL	INT	$0x80
 | 
			
		||||
 | 
			
		||||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	JMP	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	JMP	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	CALL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVL	trap+0(FP), AX  // syscall entry
 | 
			
		||||
	MOVL	a1+4(FP), BX
 | 
			
		||||
	MOVL	a2+8(FP), CX
 | 
			
		||||
	MOVL	a3+12(FP), DX
 | 
			
		||||
	MOVL	$0, SI
 | 
			
		||||
	MOVL	$0, DI
 | 
			
		||||
	INVOKE_SYSCALL
 | 
			
		||||
	MOVL	AX, r1+16(FP)
 | 
			
		||||
	MOVL	DX, r2+20(FP)
 | 
			
		||||
	CALL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	JMP	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	JMP	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	MOVL	trap+0(FP), AX  // syscall entry
 | 
			
		||||
	MOVL	a1+4(FP), BX
 | 
			
		||||
	MOVL	a2+8(FP), CX
 | 
			
		||||
	MOVL	a3+12(FP), DX
 | 
			
		||||
	MOVL	$0, SI
 | 
			
		||||
	MOVL	$0, DI
 | 
			
		||||
	INVOKE_SYSCALL
 | 
			
		||||
	MOVL	AX, r1+16(FP)
 | 
			
		||||
	MOVL	DX, r2+20(FP)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·socketcall(SB),NOSPLIT,$0-36
 | 
			
		||||
	JMP	syscall·socketcall(SB)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,17 +13,45 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	CALL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVQ	a1+8(FP), DI
 | 
			
		||||
	MOVQ	a2+16(FP), SI
 | 
			
		||||
	MOVQ	a3+24(FP), DX
 | 
			
		||||
	MOVQ	$0, R10
 | 
			
		||||
	MOVQ	$0, R8
 | 
			
		||||
	MOVQ	$0, R9
 | 
			
		||||
	MOVQ	trap+0(FP), AX	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVQ	AX, r1+32(FP)
 | 
			
		||||
	MOVQ	DX, r2+40(FP)
 | 
			
		||||
	CALL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	MOVQ	a1+8(FP), DI
 | 
			
		||||
	MOVQ	a2+16(FP), SI
 | 
			
		||||
	MOVQ	a3+24(FP), DX
 | 
			
		||||
	MOVQ	$0, R10
 | 
			
		||||
	MOVQ	$0, R8
 | 
			
		||||
	MOVQ	$0, R9
 | 
			
		||||
	MOVQ	trap+0(FP), AX	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVQ	AX, r1+32(FP)
 | 
			
		||||
	MOVQ	DX, r2+40(FP)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
 | 
			
		||||
	JMP	syscall·gettimeofday(SB)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,17 +13,44 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	B	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	B	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	BL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVW	trap+0(FP), R7
 | 
			
		||||
	MOVW	a1+4(FP), R0
 | 
			
		||||
	MOVW	a2+8(FP), R1
 | 
			
		||||
	MOVW	a3+12(FP), R2
 | 
			
		||||
	MOVW	$0, R3
 | 
			
		||||
	MOVW	$0, R4
 | 
			
		||||
	MOVW	$0, R5
 | 
			
		||||
	SWI	$0
 | 
			
		||||
	MOVW	R0, r1+16(FP)
 | 
			
		||||
	MOVW	$0, R0
 | 
			
		||||
	MOVW	R0, r2+20(FP)
 | 
			
		||||
	BL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	B	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	B	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·seek(SB),NOSPLIT,$0-32
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	MOVW	trap+0(FP), R7	// syscall entry
 | 
			
		||||
	MOVW	a1+4(FP), R0
 | 
			
		||||
	MOVW	a2+8(FP), R1
 | 
			
		||||
	MOVW	a3+12(FP), R2
 | 
			
		||||
	SWI	$0
 | 
			
		||||
	MOVW	R0, r1+16(FP)
 | 
			
		||||
	MOVW	$0, R0
 | 
			
		||||
	MOVW	R0, r2+20(FP)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·seek(SB),NOSPLIT,$0-28
 | 
			
		||||
	B	syscall·seek(SB)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,14 +11,42 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	B	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	B	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	BL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVD	a1+8(FP), R0
 | 
			
		||||
	MOVD	a2+16(FP), R1
 | 
			
		||||
	MOVD	a3+24(FP), R2
 | 
			
		||||
	MOVD	$0, R3
 | 
			
		||||
	MOVD	$0, R4
 | 
			
		||||
	MOVD	$0, R5
 | 
			
		||||
	MOVD	trap+0(FP), R8	// syscall entry
 | 
			
		||||
	SVC
 | 
			
		||||
	MOVD	R0, r1+32(FP)	// r1
 | 
			
		||||
	MOVD	R1, r2+40(FP)	// r2
 | 
			
		||||
	BL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	B	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	B	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	MOVD	a1+8(FP), R0
 | 
			
		||||
	MOVD	a2+16(FP), R1
 | 
			
		||||
	MOVD	a3+24(FP), R2
 | 
			
		||||
	MOVD	$0, R3
 | 
			
		||||
	MOVD	$0, R4
 | 
			
		||||
	MOVD	$0, R5
 | 
			
		||||
	MOVD	trap+0(FP), R8	// syscall entry
 | 
			
		||||
	SVC
 | 
			
		||||
	MOVD	R0, r1+32(FP)
 | 
			
		||||
	MOVD	R1, r2+40(FP)
 | 
			
		||||
	RET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,14 +15,42 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	JAL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVV	a1+8(FP), R4
 | 
			
		||||
	MOVV	a2+16(FP), R5
 | 
			
		||||
	MOVV	a3+24(FP), R6
 | 
			
		||||
	MOVV	R0, R7
 | 
			
		||||
	MOVV	R0, R8
 | 
			
		||||
	MOVV	R0, R9
 | 
			
		||||
	MOVV	trap+0(FP), R2	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVV	R2, r1+32(FP)
 | 
			
		||||
	MOVV	R3, r2+40(FP)
 | 
			
		||||
	JAL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	JMP	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	JMP	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	MOVV	a1+8(FP), R4
 | 
			
		||||
	MOVV	a2+16(FP), R5
 | 
			
		||||
	MOVV	a3+24(FP), R6
 | 
			
		||||
	MOVV	R0, R7
 | 
			
		||||
	MOVV	R0, R8
 | 
			
		||||
	MOVV	R0, R9
 | 
			
		||||
	MOVV	trap+0(FP), R2	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVV	R2, r1+32(FP)
 | 
			
		||||
	MOVV	R3, r2+40(FP)
 | 
			
		||||
	RET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,17 +15,40 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	JMP syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	JMP syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall9(SB),NOSPLIT,$0-52
 | 
			
		||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
 | 
			
		||||
	JMP syscall·Syscall9(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall(SB),NOSPLIT,$0-28
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	JAL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVW	a1+4(FP), R4
 | 
			
		||||
	MOVW	a2+8(FP), R5
 | 
			
		||||
	MOVW	a3+12(FP), R6
 | 
			
		||||
	MOVW	R0, R7
 | 
			
		||||
	MOVW	trap+0(FP), R2	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVW	R2, r1+16(FP)	// r1
 | 
			
		||||
	MOVW	R3, r2+20(FP)	// r2
 | 
			
		||||
	JAL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	JMP syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	JMP syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
 | 
			
		||||
	MOVW	a1+4(FP), R4
 | 
			
		||||
	MOVW	a2+8(FP), R5
 | 
			
		||||
	MOVW	a3+12(FP), R6
 | 
			
		||||
	MOVW	trap+0(FP), R2	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVW	R2, r1+16(FP)
 | 
			
		||||
	MOVW	R3, r2+20(FP)
 | 
			
		||||
	RET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,14 +15,30 @@
 | 
			
		|||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	BR	syscall·Syscall(SB)
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	BL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVD	a1+8(FP), R3
 | 
			
		||||
	MOVD	a2+16(FP), R4
 | 
			
		||||
	MOVD	a3+24(FP), R5
 | 
			
		||||
	MOVD	R0, R6
 | 
			
		||||
	MOVD	R0, R7
 | 
			
		||||
	MOVD	R0, R8
 | 
			
		||||
	MOVD	trap+0(FP), R9	// syscall entry
 | 
			
		||||
	SYSCALL R9
 | 
			
		||||
	MOVD	R3, r1+32(FP)
 | 
			
		||||
	MOVD	R4, r2+40(FP)
 | 
			
		||||
	BL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	BR	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	BR	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	BR	syscall·RawSyscall6(SB)
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	MOVD	a1+8(FP), R3
 | 
			
		||||
	MOVD	a2+16(FP), R4
 | 
			
		||||
	MOVD	a3+24(FP), R5
 | 
			
		||||
	MOVD	R0, R6
 | 
			
		||||
	MOVD	R0, R7
 | 
			
		||||
	MOVD	R0, R8
 | 
			
		||||
	MOVD	trap+0(FP), R9	// syscall entry
 | 
			
		||||
	SYSCALL R9
 | 
			
		||||
	MOVD	R3, r1+32(FP)
 | 
			
		||||
	MOVD	R4, r2+40(FP)
 | 
			
		||||
	RET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,36 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
 | 
			
		|||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	BR	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	BL	runtime·entersyscall(SB)
 | 
			
		||||
	MOVD	a1+8(FP), R2
 | 
			
		||||
	MOVD	a2+16(FP), R3
 | 
			
		||||
	MOVD	a3+24(FP), R4
 | 
			
		||||
	MOVD	$0, R5
 | 
			
		||||
	MOVD	$0, R6
 | 
			
		||||
	MOVD	$0, R7
 | 
			
		||||
	MOVD	trap+0(FP), R1	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVD	R2, r1+32(FP)
 | 
			
		||||
	MOVD	R3, r2+40(FP)
 | 
			
		||||
	BL	runtime·exitsyscall(SB)
 | 
			
		||||
	RET
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
 | 
			
		||||
	BR	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
 | 
			
		||||
	BR	syscall·RawSyscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
 | 
			
		||||
	MOVD	a1+8(FP), R2
 | 
			
		||||
	MOVD	a2+16(FP), R3
 | 
			
		||||
	MOVD	a3+24(FP), R4
 | 
			
		||||
	MOVD	$0, R5
 | 
			
		||||
	MOVD	$0, R6
 | 
			
		||||
	MOVD	$0, R7
 | 
			
		||||
	MOVD	trap+0(FP), R1	// syscall entry
 | 
			
		||||
	SYSCALL
 | 
			
		||||
	MOVD	R2, r1+32(FP)
 | 
			
		||||
	MOVD	R3, r2+40(FP)
 | 
			
		||||
	RET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// Copyright 2017 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 !gccgo
 | 
			
		||||
 | 
			
		||||
#include "textflag.h"
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// System call support for ARM, OpenBSD
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Just jump to package syscall's implementation for all these functions.
 | 
			
		||||
// The runtime may know about them.
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	B	syscall·Syscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	B	syscall·Syscall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·Syscall9(SB),NOSPLIT,$0-52
 | 
			
		||||
	B	syscall·Syscall9(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall(SB),NOSPLIT,$0-28
 | 
			
		||||
	B	syscall·RawSyscall(SB)
 | 
			
		||||
 | 
			
		||||
TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
 | 
			
		||||
	B	syscall·RawSyscall6(SB)
 | 
			
		||||
| 
						 | 
				
			
			@ -10,8 +10,8 @@
 | 
			
		|||
// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
TEXT ·sysvicall6(SB),NOSPLIT,$0-64
 | 
			
		||||
TEXT ·sysvicall6(SB),NOSPLIT,$0-88
 | 
			
		||||
	JMP	syscall·sysvicall6(SB)
 | 
			
		||||
 | 
			
		||||
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-64
 | 
			
		||||
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
 | 
			
		||||
	JMP	syscall·rawSysvicall6(SB)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,195 @@
 | 
			
		|||
// Copyright 2017 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 freebsd
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// This is the version of CapRights this package understands. See C implementation for parallels.
 | 
			
		||||
	capRightsGoVersion = CAP_RIGHTS_VERSION_00
 | 
			
		||||
	capArSizeMin       = CAP_RIGHTS_VERSION_00 + 2
 | 
			
		||||
	capArSizeMax       = capRightsGoVersion + 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	bit2idx = []int{
 | 
			
		||||
		-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
 | 
			
		||||
		4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func capidxbit(right uint64) int {
 | 
			
		||||
	return int((right >> 57) & 0x1f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rightToIndex(right uint64) (int, error) {
 | 
			
		||||
	idx := capidxbit(right)
 | 
			
		||||
	if idx < 0 || idx >= len(bit2idx) {
 | 
			
		||||
		return -2, fmt.Errorf("index for right 0x%x out of range", right)
 | 
			
		||||
	}
 | 
			
		||||
	return bit2idx[idx], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func caprver(right uint64) int {
 | 
			
		||||
	return int(right >> 62)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func capver(rights *CapRights) int {
 | 
			
		||||
	return caprver(rights.Rights[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func caparsize(rights *CapRights) int {
 | 
			
		||||
	return capver(rights) + 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsSet sets the permissions in setrights in rights.
 | 
			
		||||
func CapRightsSet(rights *CapRights, setrights []uint64) error {
 | 
			
		||||
	// This is essentially a copy of cap_rights_vset()
 | 
			
		||||
	if capver(rights) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
		return fmt.Errorf("bad rights version %d", capver(rights))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n := caparsize(rights)
 | 
			
		||||
	if n < capArSizeMin || n > capArSizeMax {
 | 
			
		||||
		return errors.New("bad rights size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, right := range setrights {
 | 
			
		||||
		if caprver(right) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
			return errors.New("bad right version")
 | 
			
		||||
		}
 | 
			
		||||
		i, err := rightToIndex(right)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if i >= n {
 | 
			
		||||
			return errors.New("index overflow")
 | 
			
		||||
		}
 | 
			
		||||
		if capidxbit(rights.Rights[i]) != capidxbit(right) {
 | 
			
		||||
			return errors.New("index mismatch")
 | 
			
		||||
		}
 | 
			
		||||
		rights.Rights[i] |= right
 | 
			
		||||
		if capidxbit(rights.Rights[i]) != capidxbit(right) {
 | 
			
		||||
			return errors.New("index mismatch (after assign)")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsClear clears the permissions in clearrights from rights.
 | 
			
		||||
func CapRightsClear(rights *CapRights, clearrights []uint64) error {
 | 
			
		||||
	// This is essentially a copy of cap_rights_vclear()
 | 
			
		||||
	if capver(rights) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
		return fmt.Errorf("bad rights version %d", capver(rights))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n := caparsize(rights)
 | 
			
		||||
	if n < capArSizeMin || n > capArSizeMax {
 | 
			
		||||
		return errors.New("bad rights size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, right := range clearrights {
 | 
			
		||||
		if caprver(right) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
			return errors.New("bad right version")
 | 
			
		||||
		}
 | 
			
		||||
		i, err := rightToIndex(right)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if i >= n {
 | 
			
		||||
			return errors.New("index overflow")
 | 
			
		||||
		}
 | 
			
		||||
		if capidxbit(rights.Rights[i]) != capidxbit(right) {
 | 
			
		||||
			return errors.New("index mismatch")
 | 
			
		||||
		}
 | 
			
		||||
		rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
 | 
			
		||||
		if capidxbit(rights.Rights[i]) != capidxbit(right) {
 | 
			
		||||
			return errors.New("index mismatch (after assign)")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
 | 
			
		||||
func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
 | 
			
		||||
	// This is essentially a copy of cap_rights_is_vset()
 | 
			
		||||
	if capver(rights) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
		return false, fmt.Errorf("bad rights version %d", capver(rights))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	n := caparsize(rights)
 | 
			
		||||
	if n < capArSizeMin || n > capArSizeMax {
 | 
			
		||||
		return false, errors.New("bad rights size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, right := range setrights {
 | 
			
		||||
		if caprver(right) != CAP_RIGHTS_VERSION_00 {
 | 
			
		||||
			return false, errors.New("bad right version")
 | 
			
		||||
		}
 | 
			
		||||
		i, err := rightToIndex(right)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
		if i >= n {
 | 
			
		||||
			return false, errors.New("index overflow")
 | 
			
		||||
		}
 | 
			
		||||
		if capidxbit(rights.Rights[i]) != capidxbit(right) {
 | 
			
		||||
			return false, errors.New("index mismatch")
 | 
			
		||||
		}
 | 
			
		||||
		if (rights.Rights[i] & right) != right {
 | 
			
		||||
			return false, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func capright(idx uint64, bit uint64) uint64 {
 | 
			
		||||
	return ((1 << (57 + idx)) | bit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
 | 
			
		||||
// See man cap_rights_init(3) and rights(4).
 | 
			
		||||
func CapRightsInit(rights []uint64) (*CapRights, error) {
 | 
			
		||||
	var r CapRights
 | 
			
		||||
	r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
 | 
			
		||||
	r.Rights[1] = capright(1, 0)
 | 
			
		||||
 | 
			
		||||
	err := CapRightsSet(&r, rights)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
 | 
			
		||||
// The capability rights on fd can never be increased by CapRightsLimit.
 | 
			
		||||
// See man cap_rights_limit(2) and rights(4).
 | 
			
		||||
func CapRightsLimit(fd uintptr, rights *CapRights) error {
 | 
			
		||||
	return capRightsLimit(int(fd), rights)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
 | 
			
		||||
// See man cap_rights_get(3) and rights(4).
 | 
			
		||||
func CapRightsGet(fd uintptr) (*CapRights, error) {
 | 
			
		||||
	r, err := CapRightsInit(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	err = capRightsGet(capRightsGoVersion, int(fd), r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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 darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
// 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 aix
 | 
			
		||||
// +build ppc
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used by AIX.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a Linux device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev >> 16) & 0xffff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a Linux device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	return uint32(dev & 0xffff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a Linux device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	return uint64(((major) << 16) | (minor))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// 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 aix
 | 
			
		||||
// +build ppc64
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used AIX.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a Linux device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev & 0x3fffffff00000000) >> 32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a Linux device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev & 0x00000000ffffffff) >> 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a Linux device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	var DEVNO64 uint64
 | 
			
		||||
	DEVNO64 = 0x8000000000000000
 | 
			
		||||
	return ((uint64(major) << 32) | (uint64(minor) & 0x00000000FFFFFFFF) | DEVNO64)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used in Darwin's sys/types.h header.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a Darwin device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev >> 24) & 0xff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a Darwin device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	return uint32(dev & 0xffffff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a Darwin device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	return (uint64(major) << 24) | uint64(minor)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used in Dragonfly's sys/types.h header.
 | 
			
		||||
//
 | 
			
		||||
// The information below is extracted and adapted from sys/types.h:
 | 
			
		||||
//
 | 
			
		||||
// Minor gives a cookie instead of an index since in order to avoid changing the
 | 
			
		||||
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
 | 
			
		||||
// devices that don't use them.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a DragonFlyBSD device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev >> 8) & 0xff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a DragonFlyBSD device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	return uint32(dev & 0xffff00ff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a DragonFlyBSD device number generated from the given major and
 | 
			
		||||
// minor components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	return (uint64(major) << 8) | uint64(minor)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used in FreeBSD's sys/types.h header.
 | 
			
		||||
//
 | 
			
		||||
// The information below is extracted and adapted from sys/types.h:
 | 
			
		||||
//
 | 
			
		||||
// Minor gives a cookie instead of an index since in order to avoid changing the
 | 
			
		||||
// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
 | 
			
		||||
// devices that don't use them.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a FreeBSD device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev >> 8) & 0xff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a FreeBSD device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	return uint32(dev & 0xffff00ff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a FreeBSD device number generated from the given major and
 | 
			
		||||
// minor components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	return (uint64(major) << 8) | uint64(minor)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used by the Linux kernel and glibc.
 | 
			
		||||
//
 | 
			
		||||
// The information below is extracted and adapted from bits/sysmacros.h in the
 | 
			
		||||
// glibc sources:
 | 
			
		||||
//
 | 
			
		||||
// dev_t in glibc is 64-bit, with 32-bit major and minor numbers. glibc's
 | 
			
		||||
// default encoding is MMMM Mmmm mmmM MMmm, where M is a hex digit of the major
 | 
			
		||||
// number and m is a hex digit of the minor number. This is backward compatible
 | 
			
		||||
// with legacy systems where dev_t is 16 bits wide, encoded as MMmm. It is also
 | 
			
		||||
// backward compatible with the Linux kernel, which for some architectures uses
 | 
			
		||||
// 32-bit dev_t, encoded as mmmM MMmm.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a Linux device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	major := uint32((dev & 0x00000000000fff00) >> 8)
 | 
			
		||||
	major |= uint32((dev & 0xfffff00000000000) >> 32)
 | 
			
		||||
	return major
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a Linux device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	minor := uint32((dev & 0x00000000000000ff) >> 0)
 | 
			
		||||
	minor |= uint32((dev & 0x00000ffffff00000) >> 12)
 | 
			
		||||
	return minor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a Linux device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	dev := (uint64(major) & 0x00000fff) << 8
 | 
			
		||||
	dev |= (uint64(major) & 0xfffff000) << 32
 | 
			
		||||
	dev |= (uint64(minor) & 0x000000ff) << 0
 | 
			
		||||
	dev |= (uint64(minor) & 0xffffff00) << 12
 | 
			
		||||
	return dev
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used in NetBSD's sys/types.h header.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of a NetBSD device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev & 0x000fff00) >> 8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of a NetBSD device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	minor := uint32((dev & 0x000000ff) >> 0)
 | 
			
		||||
	minor |= uint32((dev & 0xfff00000) >> 12)
 | 
			
		||||
	return minor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns a NetBSD device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	dev := (uint64(major) << 8) & 0x000fff00
 | 
			
		||||
	dev |= (uint64(minor) << 12) & 0xfff00000
 | 
			
		||||
	dev |= (uint64(minor) << 0) & 0x000000ff
 | 
			
		||||
	return dev
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Functions to access/create device major and minor numbers matching the
 | 
			
		||||
// encoding used in OpenBSD's sys/types.h header.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
// Major returns the major component of an OpenBSD device number.
 | 
			
		||||
func Major(dev uint64) uint32 {
 | 
			
		||||
	return uint32((dev & 0x0000ff00) >> 8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minor returns the minor component of an OpenBSD device number.
 | 
			
		||||
func Minor(dev uint64) uint32 {
 | 
			
		||||
	minor := uint32((dev & 0x000000ff) >> 0)
 | 
			
		||||
	minor |= uint32((dev & 0xffff0000) >> 8)
 | 
			
		||||
	return minor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mkdev returns an OpenBSD device number generated from the given major and minor
 | 
			
		||||
// components.
 | 
			
		||||
func Mkdev(major, minor uint32) uint64 {
 | 
			
		||||
	dev := (uint64(major) << 8) & 0x0000ff00
 | 
			
		||||
	dev |= (uint64(minor) << 8) & 0xffff0000
 | 
			
		||||
	dev |= (uint64(minor) << 0) & 0x000000ff
 | 
			
		||||
	return dev
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
// Copyright 2009 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 aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
// ParseDirent parses up to max directory entries in buf,
 | 
			
		||||
// appending the names to names. It returns the number of
 | 
			
		||||
// bytes consumed from buf, the number of entries added
 | 
			
		||||
// to names, and the new names slice.
 | 
			
		||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
 | 
			
		||||
	return syscall.ParseDirent(buf, max, names)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// Copyright 2016 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 ppc64 s390x mips mips64
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
const isBigEndian = true
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// Copyright 2016 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 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
const isBigEndian = false
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
// Copyright 2010 The Go Authors.  All rights reserved.
 | 
			
		||||
// Copyright 2010 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 darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
 | 
			
		||||
// Unix environment variables.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,3 +25,7 @@ func Clearenv() {
 | 
			
		|||
func Environ() []string {
 | 
			
		||||
	return syscall.Environ()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Unsetenv(key string) error {
 | 
			
		||||
	return syscall.Unsetenv(key)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
// Copyright 2014 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.4
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
func Unsetenv(key string) error {
 | 
			
		||||
	// This was added in Go 1.4.
 | 
			
		||||
	return syscall.Unsetenv(key)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,227 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
 | 
			
		||||
// them here for backwards compatibility.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	IFF_SMART                         = 0x20
 | 
			
		||||
	IFT_1822                          = 0x2
 | 
			
		||||
	IFT_A12MPPSWITCH                  = 0x82
 | 
			
		||||
	IFT_AAL2                          = 0xbb
 | 
			
		||||
	IFT_AAL5                          = 0x31
 | 
			
		||||
	IFT_ADSL                          = 0x5e
 | 
			
		||||
	IFT_AFLANE8023                    = 0x3b
 | 
			
		||||
	IFT_AFLANE8025                    = 0x3c
 | 
			
		||||
	IFT_ARAP                          = 0x58
 | 
			
		||||
	IFT_ARCNET                        = 0x23
 | 
			
		||||
	IFT_ARCNETPLUS                    = 0x24
 | 
			
		||||
	IFT_ASYNC                         = 0x54
 | 
			
		||||
	IFT_ATM                           = 0x25
 | 
			
		||||
	IFT_ATMDXI                        = 0x69
 | 
			
		||||
	IFT_ATMFUNI                       = 0x6a
 | 
			
		||||
	IFT_ATMIMA                        = 0x6b
 | 
			
		||||
	IFT_ATMLOGICAL                    = 0x50
 | 
			
		||||
	IFT_ATMRADIO                      = 0xbd
 | 
			
		||||
	IFT_ATMSUBINTERFACE               = 0x86
 | 
			
		||||
	IFT_ATMVCIENDPT                   = 0xc2
 | 
			
		||||
	IFT_ATMVIRTUAL                    = 0x95
 | 
			
		||||
	IFT_BGPPOLICYACCOUNTING           = 0xa2
 | 
			
		||||
	IFT_BSC                           = 0x53
 | 
			
		||||
	IFT_CCTEMUL                       = 0x3d
 | 
			
		||||
	IFT_CEPT                          = 0x13
 | 
			
		||||
	IFT_CES                           = 0x85
 | 
			
		||||
	IFT_CHANNEL                       = 0x46
 | 
			
		||||
	IFT_CNR                           = 0x55
 | 
			
		||||
	IFT_COFFEE                        = 0x84
 | 
			
		||||
	IFT_COMPOSITELINK                 = 0x9b
 | 
			
		||||
	IFT_DCN                           = 0x8d
 | 
			
		||||
	IFT_DIGITALPOWERLINE              = 0x8a
 | 
			
		||||
	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
 | 
			
		||||
	IFT_DLSW                          = 0x4a
 | 
			
		||||
	IFT_DOCSCABLEDOWNSTREAM           = 0x80
 | 
			
		||||
	IFT_DOCSCABLEMACLAYER             = 0x7f
 | 
			
		||||
	IFT_DOCSCABLEUPSTREAM             = 0x81
 | 
			
		||||
	IFT_DS0                           = 0x51
 | 
			
		||||
	IFT_DS0BUNDLE                     = 0x52
 | 
			
		||||
	IFT_DS1FDL                        = 0xaa
 | 
			
		||||
	IFT_DS3                           = 0x1e
 | 
			
		||||
	IFT_DTM                           = 0x8c
 | 
			
		||||
	IFT_DVBASILN                      = 0xac
 | 
			
		||||
	IFT_DVBASIOUT                     = 0xad
 | 
			
		||||
	IFT_DVBRCCDOWNSTREAM              = 0x93
 | 
			
		||||
	IFT_DVBRCCMACLAYER                = 0x92
 | 
			
		||||
	IFT_DVBRCCUPSTREAM                = 0x94
 | 
			
		||||
	IFT_ENC                           = 0xf4
 | 
			
		||||
	IFT_EON                           = 0x19
 | 
			
		||||
	IFT_EPLRS                         = 0x57
 | 
			
		||||
	IFT_ESCON                         = 0x49
 | 
			
		||||
	IFT_ETHER                         = 0x6
 | 
			
		||||
	IFT_FAITH                         = 0xf2
 | 
			
		||||
	IFT_FAST                          = 0x7d
 | 
			
		||||
	IFT_FASTETHER                     = 0x3e
 | 
			
		||||
	IFT_FASTETHERFX                   = 0x45
 | 
			
		||||
	IFT_FDDI                          = 0xf
 | 
			
		||||
	IFT_FIBRECHANNEL                  = 0x38
 | 
			
		||||
	IFT_FRAMERELAYINTERCONNECT        = 0x3a
 | 
			
		||||
	IFT_FRAMERELAYMPI                 = 0x5c
 | 
			
		||||
	IFT_FRDLCIENDPT                   = 0xc1
 | 
			
		||||
	IFT_FRELAY                        = 0x20
 | 
			
		||||
	IFT_FRELAYDCE                     = 0x2c
 | 
			
		||||
	IFT_FRF16MFRBUNDLE                = 0xa3
 | 
			
		||||
	IFT_FRFORWARD                     = 0x9e
 | 
			
		||||
	IFT_G703AT2MB                     = 0x43
 | 
			
		||||
	IFT_G703AT64K                     = 0x42
 | 
			
		||||
	IFT_GIF                           = 0xf0
 | 
			
		||||
	IFT_GIGABITETHERNET               = 0x75
 | 
			
		||||
	IFT_GR303IDT                      = 0xb2
 | 
			
		||||
	IFT_GR303RDT                      = 0xb1
 | 
			
		||||
	IFT_H323GATEKEEPER                = 0xa4
 | 
			
		||||
	IFT_H323PROXY                     = 0xa5
 | 
			
		||||
	IFT_HDH1822                       = 0x3
 | 
			
		||||
	IFT_HDLC                          = 0x76
 | 
			
		||||
	IFT_HDSL2                         = 0xa8
 | 
			
		||||
	IFT_HIPERLAN2                     = 0xb7
 | 
			
		||||
	IFT_HIPPI                         = 0x2f
 | 
			
		||||
	IFT_HIPPIINTERFACE                = 0x39
 | 
			
		||||
	IFT_HOSTPAD                       = 0x5a
 | 
			
		||||
	IFT_HSSI                          = 0x2e
 | 
			
		||||
	IFT_HY                            = 0xe
 | 
			
		||||
	IFT_IBM370PARCHAN                 = 0x48
 | 
			
		||||
	IFT_IDSL                          = 0x9a
 | 
			
		||||
	IFT_IEEE80211                     = 0x47
 | 
			
		||||
	IFT_IEEE80212                     = 0x37
 | 
			
		||||
	IFT_IEEE8023ADLAG                 = 0xa1
 | 
			
		||||
	IFT_IFGSN                         = 0x91
 | 
			
		||||
	IFT_IMT                           = 0xbe
 | 
			
		||||
	IFT_INTERLEAVE                    = 0x7c
 | 
			
		||||
	IFT_IP                            = 0x7e
 | 
			
		||||
	IFT_IPFORWARD                     = 0x8e
 | 
			
		||||
	IFT_IPOVERATM                     = 0x72
 | 
			
		||||
	IFT_IPOVERCDLC                    = 0x6d
 | 
			
		||||
	IFT_IPOVERCLAW                    = 0x6e
 | 
			
		||||
	IFT_IPSWITCH                      = 0x4e
 | 
			
		||||
	IFT_IPXIP                         = 0xf9
 | 
			
		||||
	IFT_ISDN                          = 0x3f
 | 
			
		||||
	IFT_ISDNBASIC                     = 0x14
 | 
			
		||||
	IFT_ISDNPRIMARY                   = 0x15
 | 
			
		||||
	IFT_ISDNS                         = 0x4b
 | 
			
		||||
	IFT_ISDNU                         = 0x4c
 | 
			
		||||
	IFT_ISO88022LLC                   = 0x29
 | 
			
		||||
	IFT_ISO88023                      = 0x7
 | 
			
		||||
	IFT_ISO88024                      = 0x8
 | 
			
		||||
	IFT_ISO88025                      = 0x9
 | 
			
		||||
	IFT_ISO88025CRFPINT               = 0x62
 | 
			
		||||
	IFT_ISO88025DTR                   = 0x56
 | 
			
		||||
	IFT_ISO88025FIBER                 = 0x73
 | 
			
		||||
	IFT_ISO88026                      = 0xa
 | 
			
		||||
	IFT_ISUP                          = 0xb3
 | 
			
		||||
	IFT_L3IPXVLAN                     = 0x89
 | 
			
		||||
	IFT_LAPB                          = 0x10
 | 
			
		||||
	IFT_LAPD                          = 0x4d
 | 
			
		||||
	IFT_LAPF                          = 0x77
 | 
			
		||||
	IFT_LOCALTALK                     = 0x2a
 | 
			
		||||
	IFT_LOOP                          = 0x18
 | 
			
		||||
	IFT_MEDIAMAILOVERIP               = 0x8b
 | 
			
		||||
	IFT_MFSIGLINK                     = 0xa7
 | 
			
		||||
	IFT_MIOX25                        = 0x26
 | 
			
		||||
	IFT_MODEM                         = 0x30
 | 
			
		||||
	IFT_MPC                           = 0x71
 | 
			
		||||
	IFT_MPLS                          = 0xa6
 | 
			
		||||
	IFT_MPLSTUNNEL                    = 0x96
 | 
			
		||||
	IFT_MSDSL                         = 0x8f
 | 
			
		||||
	IFT_MVL                           = 0xbf
 | 
			
		||||
	IFT_MYRINET                       = 0x63
 | 
			
		||||
	IFT_NFAS                          = 0xaf
 | 
			
		||||
	IFT_NSIP                          = 0x1b
 | 
			
		||||
	IFT_OPTICALCHANNEL                = 0xc3
 | 
			
		||||
	IFT_OPTICALTRANSPORT              = 0xc4
 | 
			
		||||
	IFT_OTHER                         = 0x1
 | 
			
		||||
	IFT_P10                           = 0xc
 | 
			
		||||
	IFT_P80                           = 0xd
 | 
			
		||||
	IFT_PARA                          = 0x22
 | 
			
		||||
	IFT_PFLOG                         = 0xf6
 | 
			
		||||
	IFT_PFSYNC                        = 0xf7
 | 
			
		||||
	IFT_PLC                           = 0xae
 | 
			
		||||
	IFT_POS                           = 0xab
 | 
			
		||||
	IFT_PPPMULTILINKBUNDLE            = 0x6c
 | 
			
		||||
	IFT_PROPBWAP2MP                   = 0xb8
 | 
			
		||||
	IFT_PROPCNLS                      = 0x59
 | 
			
		||||
	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
 | 
			
		||||
	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
 | 
			
		||||
	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
 | 
			
		||||
	IFT_PROPMUX                       = 0x36
 | 
			
		||||
	IFT_PROPWIRELESSP2P               = 0x9d
 | 
			
		||||
	IFT_PTPSERIAL                     = 0x16
 | 
			
		||||
	IFT_PVC                           = 0xf1
 | 
			
		||||
	IFT_QLLC                          = 0x44
 | 
			
		||||
	IFT_RADIOMAC                      = 0xbc
 | 
			
		||||
	IFT_RADSL                         = 0x5f
 | 
			
		||||
	IFT_REACHDSL                      = 0xc0
 | 
			
		||||
	IFT_RFC1483                       = 0x9f
 | 
			
		||||
	IFT_RS232                         = 0x21
 | 
			
		||||
	IFT_RSRB                          = 0x4f
 | 
			
		||||
	IFT_SDLC                          = 0x11
 | 
			
		||||
	IFT_SDSL                          = 0x60
 | 
			
		||||
	IFT_SHDSL                         = 0xa9
 | 
			
		||||
	IFT_SIP                           = 0x1f
 | 
			
		||||
	IFT_SLIP                          = 0x1c
 | 
			
		||||
	IFT_SMDSDXI                       = 0x2b
 | 
			
		||||
	IFT_SMDSICIP                      = 0x34
 | 
			
		||||
	IFT_SONET                         = 0x27
 | 
			
		||||
	IFT_SONETOVERHEADCHANNEL          = 0xb9
 | 
			
		||||
	IFT_SONETPATH                     = 0x32
 | 
			
		||||
	IFT_SONETVT                       = 0x33
 | 
			
		||||
	IFT_SRP                           = 0x97
 | 
			
		||||
	IFT_SS7SIGLINK                    = 0x9c
 | 
			
		||||
	IFT_STACKTOSTACK                  = 0x6f
 | 
			
		||||
	IFT_STARLAN                       = 0xb
 | 
			
		||||
	IFT_STF                           = 0xd7
 | 
			
		||||
	IFT_T1                            = 0x12
 | 
			
		||||
	IFT_TDLC                          = 0x74
 | 
			
		||||
	IFT_TERMPAD                       = 0x5b
 | 
			
		||||
	IFT_TR008                         = 0xb0
 | 
			
		||||
	IFT_TRANSPHDLC                    = 0x7b
 | 
			
		||||
	IFT_TUNNEL                        = 0x83
 | 
			
		||||
	IFT_ULTRA                         = 0x1d
 | 
			
		||||
	IFT_USB                           = 0xa0
 | 
			
		||||
	IFT_V11                           = 0x40
 | 
			
		||||
	IFT_V35                           = 0x2d
 | 
			
		||||
	IFT_V36                           = 0x41
 | 
			
		||||
	IFT_V37                           = 0x78
 | 
			
		||||
	IFT_VDSL                          = 0x61
 | 
			
		||||
	IFT_VIRTUALIPADDRESS              = 0x70
 | 
			
		||||
	IFT_VOICEEM                       = 0x64
 | 
			
		||||
	IFT_VOICEENCAP                    = 0x67
 | 
			
		||||
	IFT_VOICEFXO                      = 0x65
 | 
			
		||||
	IFT_VOICEFXS                      = 0x66
 | 
			
		||||
	IFT_VOICEOVERATM                  = 0x98
 | 
			
		||||
	IFT_VOICEOVERFRAMERELAY           = 0x99
 | 
			
		||||
	IFT_VOICEOVERIP                   = 0x68
 | 
			
		||||
	IFT_X213                          = 0x5d
 | 
			
		||||
	IFT_X25                           = 0x5
 | 
			
		||||
	IFT_X25DDN                        = 0x4
 | 
			
		||||
	IFT_X25HUNTGROUP                  = 0x7a
 | 
			
		||||
	IFT_X25MLP                        = 0x79
 | 
			
		||||
	IFT_X25PLE                        = 0x28
 | 
			
		||||
	IFT_XETHER                        = 0x1a
 | 
			
		||||
	IPPROTO_MAXID                     = 0x34
 | 
			
		||||
	IPV6_FAITH                        = 0x1d
 | 
			
		||||
	IP_FAITH                          = 0x16
 | 
			
		||||
	MAP_NORESERVE                     = 0x40
 | 
			
		||||
	MAP_RENAME                        = 0x20
 | 
			
		||||
	NET_RT_MAXID                      = 0x6
 | 
			
		||||
	RTF_PRCLONING                     = 0x10000
 | 
			
		||||
	RTM_OLDADD                        = 0x9
 | 
			
		||||
	RTM_OLDDEL                        = 0xa
 | 
			
		||||
	SIOCADDRT                         = 0x8030720a
 | 
			
		||||
	SIOCALIFADDR                      = 0x8118691b
 | 
			
		||||
	SIOCDELRT                         = 0x8030720b
 | 
			
		||||
	SIOCDLIFADDR                      = 0x8118691d
 | 
			
		||||
	SIOCGLIFADDR                      = 0xc118691c
 | 
			
		||||
	SIOCGLIFPHYADDR                   = 0xc118694b
 | 
			
		||||
	SIOCSLIFPHYADDR                   = 0x8118694a
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,227 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
 | 
			
		||||
// them here for backwards compatibility.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	IFF_SMART                         = 0x20
 | 
			
		||||
	IFT_1822                          = 0x2
 | 
			
		||||
	IFT_A12MPPSWITCH                  = 0x82
 | 
			
		||||
	IFT_AAL2                          = 0xbb
 | 
			
		||||
	IFT_AAL5                          = 0x31
 | 
			
		||||
	IFT_ADSL                          = 0x5e
 | 
			
		||||
	IFT_AFLANE8023                    = 0x3b
 | 
			
		||||
	IFT_AFLANE8025                    = 0x3c
 | 
			
		||||
	IFT_ARAP                          = 0x58
 | 
			
		||||
	IFT_ARCNET                        = 0x23
 | 
			
		||||
	IFT_ARCNETPLUS                    = 0x24
 | 
			
		||||
	IFT_ASYNC                         = 0x54
 | 
			
		||||
	IFT_ATM                           = 0x25
 | 
			
		||||
	IFT_ATMDXI                        = 0x69
 | 
			
		||||
	IFT_ATMFUNI                       = 0x6a
 | 
			
		||||
	IFT_ATMIMA                        = 0x6b
 | 
			
		||||
	IFT_ATMLOGICAL                    = 0x50
 | 
			
		||||
	IFT_ATMRADIO                      = 0xbd
 | 
			
		||||
	IFT_ATMSUBINTERFACE               = 0x86
 | 
			
		||||
	IFT_ATMVCIENDPT                   = 0xc2
 | 
			
		||||
	IFT_ATMVIRTUAL                    = 0x95
 | 
			
		||||
	IFT_BGPPOLICYACCOUNTING           = 0xa2
 | 
			
		||||
	IFT_BSC                           = 0x53
 | 
			
		||||
	IFT_CCTEMUL                       = 0x3d
 | 
			
		||||
	IFT_CEPT                          = 0x13
 | 
			
		||||
	IFT_CES                           = 0x85
 | 
			
		||||
	IFT_CHANNEL                       = 0x46
 | 
			
		||||
	IFT_CNR                           = 0x55
 | 
			
		||||
	IFT_COFFEE                        = 0x84
 | 
			
		||||
	IFT_COMPOSITELINK                 = 0x9b
 | 
			
		||||
	IFT_DCN                           = 0x8d
 | 
			
		||||
	IFT_DIGITALPOWERLINE              = 0x8a
 | 
			
		||||
	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
 | 
			
		||||
	IFT_DLSW                          = 0x4a
 | 
			
		||||
	IFT_DOCSCABLEDOWNSTREAM           = 0x80
 | 
			
		||||
	IFT_DOCSCABLEMACLAYER             = 0x7f
 | 
			
		||||
	IFT_DOCSCABLEUPSTREAM             = 0x81
 | 
			
		||||
	IFT_DS0                           = 0x51
 | 
			
		||||
	IFT_DS0BUNDLE                     = 0x52
 | 
			
		||||
	IFT_DS1FDL                        = 0xaa
 | 
			
		||||
	IFT_DS3                           = 0x1e
 | 
			
		||||
	IFT_DTM                           = 0x8c
 | 
			
		||||
	IFT_DVBASILN                      = 0xac
 | 
			
		||||
	IFT_DVBASIOUT                     = 0xad
 | 
			
		||||
	IFT_DVBRCCDOWNSTREAM              = 0x93
 | 
			
		||||
	IFT_DVBRCCMACLAYER                = 0x92
 | 
			
		||||
	IFT_DVBRCCUPSTREAM                = 0x94
 | 
			
		||||
	IFT_ENC                           = 0xf4
 | 
			
		||||
	IFT_EON                           = 0x19
 | 
			
		||||
	IFT_EPLRS                         = 0x57
 | 
			
		||||
	IFT_ESCON                         = 0x49
 | 
			
		||||
	IFT_ETHER                         = 0x6
 | 
			
		||||
	IFT_FAITH                         = 0xf2
 | 
			
		||||
	IFT_FAST                          = 0x7d
 | 
			
		||||
	IFT_FASTETHER                     = 0x3e
 | 
			
		||||
	IFT_FASTETHERFX                   = 0x45
 | 
			
		||||
	IFT_FDDI                          = 0xf
 | 
			
		||||
	IFT_FIBRECHANNEL                  = 0x38
 | 
			
		||||
	IFT_FRAMERELAYINTERCONNECT        = 0x3a
 | 
			
		||||
	IFT_FRAMERELAYMPI                 = 0x5c
 | 
			
		||||
	IFT_FRDLCIENDPT                   = 0xc1
 | 
			
		||||
	IFT_FRELAY                        = 0x20
 | 
			
		||||
	IFT_FRELAYDCE                     = 0x2c
 | 
			
		||||
	IFT_FRF16MFRBUNDLE                = 0xa3
 | 
			
		||||
	IFT_FRFORWARD                     = 0x9e
 | 
			
		||||
	IFT_G703AT2MB                     = 0x43
 | 
			
		||||
	IFT_G703AT64K                     = 0x42
 | 
			
		||||
	IFT_GIF                           = 0xf0
 | 
			
		||||
	IFT_GIGABITETHERNET               = 0x75
 | 
			
		||||
	IFT_GR303IDT                      = 0xb2
 | 
			
		||||
	IFT_GR303RDT                      = 0xb1
 | 
			
		||||
	IFT_H323GATEKEEPER                = 0xa4
 | 
			
		||||
	IFT_H323PROXY                     = 0xa5
 | 
			
		||||
	IFT_HDH1822                       = 0x3
 | 
			
		||||
	IFT_HDLC                          = 0x76
 | 
			
		||||
	IFT_HDSL2                         = 0xa8
 | 
			
		||||
	IFT_HIPERLAN2                     = 0xb7
 | 
			
		||||
	IFT_HIPPI                         = 0x2f
 | 
			
		||||
	IFT_HIPPIINTERFACE                = 0x39
 | 
			
		||||
	IFT_HOSTPAD                       = 0x5a
 | 
			
		||||
	IFT_HSSI                          = 0x2e
 | 
			
		||||
	IFT_HY                            = 0xe
 | 
			
		||||
	IFT_IBM370PARCHAN                 = 0x48
 | 
			
		||||
	IFT_IDSL                          = 0x9a
 | 
			
		||||
	IFT_IEEE80211                     = 0x47
 | 
			
		||||
	IFT_IEEE80212                     = 0x37
 | 
			
		||||
	IFT_IEEE8023ADLAG                 = 0xa1
 | 
			
		||||
	IFT_IFGSN                         = 0x91
 | 
			
		||||
	IFT_IMT                           = 0xbe
 | 
			
		||||
	IFT_INTERLEAVE                    = 0x7c
 | 
			
		||||
	IFT_IP                            = 0x7e
 | 
			
		||||
	IFT_IPFORWARD                     = 0x8e
 | 
			
		||||
	IFT_IPOVERATM                     = 0x72
 | 
			
		||||
	IFT_IPOVERCDLC                    = 0x6d
 | 
			
		||||
	IFT_IPOVERCLAW                    = 0x6e
 | 
			
		||||
	IFT_IPSWITCH                      = 0x4e
 | 
			
		||||
	IFT_IPXIP                         = 0xf9
 | 
			
		||||
	IFT_ISDN                          = 0x3f
 | 
			
		||||
	IFT_ISDNBASIC                     = 0x14
 | 
			
		||||
	IFT_ISDNPRIMARY                   = 0x15
 | 
			
		||||
	IFT_ISDNS                         = 0x4b
 | 
			
		||||
	IFT_ISDNU                         = 0x4c
 | 
			
		||||
	IFT_ISO88022LLC                   = 0x29
 | 
			
		||||
	IFT_ISO88023                      = 0x7
 | 
			
		||||
	IFT_ISO88024                      = 0x8
 | 
			
		||||
	IFT_ISO88025                      = 0x9
 | 
			
		||||
	IFT_ISO88025CRFPINT               = 0x62
 | 
			
		||||
	IFT_ISO88025DTR                   = 0x56
 | 
			
		||||
	IFT_ISO88025FIBER                 = 0x73
 | 
			
		||||
	IFT_ISO88026                      = 0xa
 | 
			
		||||
	IFT_ISUP                          = 0xb3
 | 
			
		||||
	IFT_L3IPXVLAN                     = 0x89
 | 
			
		||||
	IFT_LAPB                          = 0x10
 | 
			
		||||
	IFT_LAPD                          = 0x4d
 | 
			
		||||
	IFT_LAPF                          = 0x77
 | 
			
		||||
	IFT_LOCALTALK                     = 0x2a
 | 
			
		||||
	IFT_LOOP                          = 0x18
 | 
			
		||||
	IFT_MEDIAMAILOVERIP               = 0x8b
 | 
			
		||||
	IFT_MFSIGLINK                     = 0xa7
 | 
			
		||||
	IFT_MIOX25                        = 0x26
 | 
			
		||||
	IFT_MODEM                         = 0x30
 | 
			
		||||
	IFT_MPC                           = 0x71
 | 
			
		||||
	IFT_MPLS                          = 0xa6
 | 
			
		||||
	IFT_MPLSTUNNEL                    = 0x96
 | 
			
		||||
	IFT_MSDSL                         = 0x8f
 | 
			
		||||
	IFT_MVL                           = 0xbf
 | 
			
		||||
	IFT_MYRINET                       = 0x63
 | 
			
		||||
	IFT_NFAS                          = 0xaf
 | 
			
		||||
	IFT_NSIP                          = 0x1b
 | 
			
		||||
	IFT_OPTICALCHANNEL                = 0xc3
 | 
			
		||||
	IFT_OPTICALTRANSPORT              = 0xc4
 | 
			
		||||
	IFT_OTHER                         = 0x1
 | 
			
		||||
	IFT_P10                           = 0xc
 | 
			
		||||
	IFT_P80                           = 0xd
 | 
			
		||||
	IFT_PARA                          = 0x22
 | 
			
		||||
	IFT_PFLOG                         = 0xf6
 | 
			
		||||
	IFT_PFSYNC                        = 0xf7
 | 
			
		||||
	IFT_PLC                           = 0xae
 | 
			
		||||
	IFT_POS                           = 0xab
 | 
			
		||||
	IFT_PPPMULTILINKBUNDLE            = 0x6c
 | 
			
		||||
	IFT_PROPBWAP2MP                   = 0xb8
 | 
			
		||||
	IFT_PROPCNLS                      = 0x59
 | 
			
		||||
	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
 | 
			
		||||
	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
 | 
			
		||||
	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
 | 
			
		||||
	IFT_PROPMUX                       = 0x36
 | 
			
		||||
	IFT_PROPWIRELESSP2P               = 0x9d
 | 
			
		||||
	IFT_PTPSERIAL                     = 0x16
 | 
			
		||||
	IFT_PVC                           = 0xf1
 | 
			
		||||
	IFT_QLLC                          = 0x44
 | 
			
		||||
	IFT_RADIOMAC                      = 0xbc
 | 
			
		||||
	IFT_RADSL                         = 0x5f
 | 
			
		||||
	IFT_REACHDSL                      = 0xc0
 | 
			
		||||
	IFT_RFC1483                       = 0x9f
 | 
			
		||||
	IFT_RS232                         = 0x21
 | 
			
		||||
	IFT_RSRB                          = 0x4f
 | 
			
		||||
	IFT_SDLC                          = 0x11
 | 
			
		||||
	IFT_SDSL                          = 0x60
 | 
			
		||||
	IFT_SHDSL                         = 0xa9
 | 
			
		||||
	IFT_SIP                           = 0x1f
 | 
			
		||||
	IFT_SLIP                          = 0x1c
 | 
			
		||||
	IFT_SMDSDXI                       = 0x2b
 | 
			
		||||
	IFT_SMDSICIP                      = 0x34
 | 
			
		||||
	IFT_SONET                         = 0x27
 | 
			
		||||
	IFT_SONETOVERHEADCHANNEL          = 0xb9
 | 
			
		||||
	IFT_SONETPATH                     = 0x32
 | 
			
		||||
	IFT_SONETVT                       = 0x33
 | 
			
		||||
	IFT_SRP                           = 0x97
 | 
			
		||||
	IFT_SS7SIGLINK                    = 0x9c
 | 
			
		||||
	IFT_STACKTOSTACK                  = 0x6f
 | 
			
		||||
	IFT_STARLAN                       = 0xb
 | 
			
		||||
	IFT_STF                           = 0xd7
 | 
			
		||||
	IFT_T1                            = 0x12
 | 
			
		||||
	IFT_TDLC                          = 0x74
 | 
			
		||||
	IFT_TERMPAD                       = 0x5b
 | 
			
		||||
	IFT_TR008                         = 0xb0
 | 
			
		||||
	IFT_TRANSPHDLC                    = 0x7b
 | 
			
		||||
	IFT_TUNNEL                        = 0x83
 | 
			
		||||
	IFT_ULTRA                         = 0x1d
 | 
			
		||||
	IFT_USB                           = 0xa0
 | 
			
		||||
	IFT_V11                           = 0x40
 | 
			
		||||
	IFT_V35                           = 0x2d
 | 
			
		||||
	IFT_V36                           = 0x41
 | 
			
		||||
	IFT_V37                           = 0x78
 | 
			
		||||
	IFT_VDSL                          = 0x61
 | 
			
		||||
	IFT_VIRTUALIPADDRESS              = 0x70
 | 
			
		||||
	IFT_VOICEEM                       = 0x64
 | 
			
		||||
	IFT_VOICEENCAP                    = 0x67
 | 
			
		||||
	IFT_VOICEFXO                      = 0x65
 | 
			
		||||
	IFT_VOICEFXS                      = 0x66
 | 
			
		||||
	IFT_VOICEOVERATM                  = 0x98
 | 
			
		||||
	IFT_VOICEOVERFRAMERELAY           = 0x99
 | 
			
		||||
	IFT_VOICEOVERIP                   = 0x68
 | 
			
		||||
	IFT_X213                          = 0x5d
 | 
			
		||||
	IFT_X25                           = 0x5
 | 
			
		||||
	IFT_X25DDN                        = 0x4
 | 
			
		||||
	IFT_X25HUNTGROUP                  = 0x7a
 | 
			
		||||
	IFT_X25MLP                        = 0x79
 | 
			
		||||
	IFT_X25PLE                        = 0x28
 | 
			
		||||
	IFT_XETHER                        = 0x1a
 | 
			
		||||
	IPPROTO_MAXID                     = 0x34
 | 
			
		||||
	IPV6_FAITH                        = 0x1d
 | 
			
		||||
	IP_FAITH                          = 0x16
 | 
			
		||||
	MAP_NORESERVE                     = 0x40
 | 
			
		||||
	MAP_RENAME                        = 0x20
 | 
			
		||||
	NET_RT_MAXID                      = 0x6
 | 
			
		||||
	RTF_PRCLONING                     = 0x10000
 | 
			
		||||
	RTM_OLDADD                        = 0x9
 | 
			
		||||
	RTM_OLDDEL                        = 0xa
 | 
			
		||||
	SIOCADDRT                         = 0x8040720a
 | 
			
		||||
	SIOCALIFADDR                      = 0x8118691b
 | 
			
		||||
	SIOCDELRT                         = 0x8040720b
 | 
			
		||||
	SIOCDLIFADDR                      = 0x8118691d
 | 
			
		||||
	SIOCGLIFADDR                      = 0xc118691c
 | 
			
		||||
	SIOCGLIFPHYADDR                   = 0xc118694b
 | 
			
		||||
	SIOCSLIFPHYADDR                   = 0x8118694a
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,226 @@
 | 
			
		|||
// Copyright 2017 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.
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	IFT_1822                          = 0x2
 | 
			
		||||
	IFT_A12MPPSWITCH                  = 0x82
 | 
			
		||||
	IFT_AAL2                          = 0xbb
 | 
			
		||||
	IFT_AAL5                          = 0x31
 | 
			
		||||
	IFT_ADSL                          = 0x5e
 | 
			
		||||
	IFT_AFLANE8023                    = 0x3b
 | 
			
		||||
	IFT_AFLANE8025                    = 0x3c
 | 
			
		||||
	IFT_ARAP                          = 0x58
 | 
			
		||||
	IFT_ARCNET                        = 0x23
 | 
			
		||||
	IFT_ARCNETPLUS                    = 0x24
 | 
			
		||||
	IFT_ASYNC                         = 0x54
 | 
			
		||||
	IFT_ATM                           = 0x25
 | 
			
		||||
	IFT_ATMDXI                        = 0x69
 | 
			
		||||
	IFT_ATMFUNI                       = 0x6a
 | 
			
		||||
	IFT_ATMIMA                        = 0x6b
 | 
			
		||||
	IFT_ATMLOGICAL                    = 0x50
 | 
			
		||||
	IFT_ATMRADIO                      = 0xbd
 | 
			
		||||
	IFT_ATMSUBINTERFACE               = 0x86
 | 
			
		||||
	IFT_ATMVCIENDPT                   = 0xc2
 | 
			
		||||
	IFT_ATMVIRTUAL                    = 0x95
 | 
			
		||||
	IFT_BGPPOLICYACCOUNTING           = 0xa2
 | 
			
		||||
	IFT_BSC                           = 0x53
 | 
			
		||||
	IFT_CCTEMUL                       = 0x3d
 | 
			
		||||
	IFT_CEPT                          = 0x13
 | 
			
		||||
	IFT_CES                           = 0x85
 | 
			
		||||
	IFT_CHANNEL                       = 0x46
 | 
			
		||||
	IFT_CNR                           = 0x55
 | 
			
		||||
	IFT_COFFEE                        = 0x84
 | 
			
		||||
	IFT_COMPOSITELINK                 = 0x9b
 | 
			
		||||
	IFT_DCN                           = 0x8d
 | 
			
		||||
	IFT_DIGITALPOWERLINE              = 0x8a
 | 
			
		||||
	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
 | 
			
		||||
	IFT_DLSW                          = 0x4a
 | 
			
		||||
	IFT_DOCSCABLEDOWNSTREAM           = 0x80
 | 
			
		||||
	IFT_DOCSCABLEMACLAYER             = 0x7f
 | 
			
		||||
	IFT_DOCSCABLEUPSTREAM             = 0x81
 | 
			
		||||
	IFT_DS0                           = 0x51
 | 
			
		||||
	IFT_DS0BUNDLE                     = 0x52
 | 
			
		||||
	IFT_DS1FDL                        = 0xaa
 | 
			
		||||
	IFT_DS3                           = 0x1e
 | 
			
		||||
	IFT_DTM                           = 0x8c
 | 
			
		||||
	IFT_DVBASILN                      = 0xac
 | 
			
		||||
	IFT_DVBASIOUT                     = 0xad
 | 
			
		||||
	IFT_DVBRCCDOWNSTREAM              = 0x93
 | 
			
		||||
	IFT_DVBRCCMACLAYER                = 0x92
 | 
			
		||||
	IFT_DVBRCCUPSTREAM                = 0x94
 | 
			
		||||
	IFT_ENC                           = 0xf4
 | 
			
		||||
	IFT_EON                           = 0x19
 | 
			
		||||
	IFT_EPLRS                         = 0x57
 | 
			
		||||
	IFT_ESCON                         = 0x49
 | 
			
		||||
	IFT_ETHER                         = 0x6
 | 
			
		||||
	IFT_FAST                          = 0x7d
 | 
			
		||||
	IFT_FASTETHER                     = 0x3e
 | 
			
		||||
	IFT_FASTETHERFX                   = 0x45
 | 
			
		||||
	IFT_FDDI                          = 0xf
 | 
			
		||||
	IFT_FIBRECHANNEL                  = 0x38
 | 
			
		||||
	IFT_FRAMERELAYINTERCONNECT        = 0x3a
 | 
			
		||||
	IFT_FRAMERELAYMPI                 = 0x5c
 | 
			
		||||
	IFT_FRDLCIENDPT                   = 0xc1
 | 
			
		||||
	IFT_FRELAY                        = 0x20
 | 
			
		||||
	IFT_FRELAYDCE                     = 0x2c
 | 
			
		||||
	IFT_FRF16MFRBUNDLE                = 0xa3
 | 
			
		||||
	IFT_FRFORWARD                     = 0x9e
 | 
			
		||||
	IFT_G703AT2MB                     = 0x43
 | 
			
		||||
	IFT_G703AT64K                     = 0x42
 | 
			
		||||
	IFT_GIF                           = 0xf0
 | 
			
		||||
	IFT_GIGABITETHERNET               = 0x75
 | 
			
		||||
	IFT_GR303IDT                      = 0xb2
 | 
			
		||||
	IFT_GR303RDT                      = 0xb1
 | 
			
		||||
	IFT_H323GATEKEEPER                = 0xa4
 | 
			
		||||
	IFT_H323PROXY                     = 0xa5
 | 
			
		||||
	IFT_HDH1822                       = 0x3
 | 
			
		||||
	IFT_HDLC                          = 0x76
 | 
			
		||||
	IFT_HDSL2                         = 0xa8
 | 
			
		||||
	IFT_HIPERLAN2                     = 0xb7
 | 
			
		||||
	IFT_HIPPI                         = 0x2f
 | 
			
		||||
	IFT_HIPPIINTERFACE                = 0x39
 | 
			
		||||
	IFT_HOSTPAD                       = 0x5a
 | 
			
		||||
	IFT_HSSI                          = 0x2e
 | 
			
		||||
	IFT_HY                            = 0xe
 | 
			
		||||
	IFT_IBM370PARCHAN                 = 0x48
 | 
			
		||||
	IFT_IDSL                          = 0x9a
 | 
			
		||||
	IFT_IEEE80211                     = 0x47
 | 
			
		||||
	IFT_IEEE80212                     = 0x37
 | 
			
		||||
	IFT_IEEE8023ADLAG                 = 0xa1
 | 
			
		||||
	IFT_IFGSN                         = 0x91
 | 
			
		||||
	IFT_IMT                           = 0xbe
 | 
			
		||||
	IFT_INTERLEAVE                    = 0x7c
 | 
			
		||||
	IFT_IP                            = 0x7e
 | 
			
		||||
	IFT_IPFORWARD                     = 0x8e
 | 
			
		||||
	IFT_IPOVERATM                     = 0x72
 | 
			
		||||
	IFT_IPOVERCDLC                    = 0x6d
 | 
			
		||||
	IFT_IPOVERCLAW                    = 0x6e
 | 
			
		||||
	IFT_IPSWITCH                      = 0x4e
 | 
			
		||||
	IFT_ISDN                          = 0x3f
 | 
			
		||||
	IFT_ISDNBASIC                     = 0x14
 | 
			
		||||
	IFT_ISDNPRIMARY                   = 0x15
 | 
			
		||||
	IFT_ISDNS                         = 0x4b
 | 
			
		||||
	IFT_ISDNU                         = 0x4c
 | 
			
		||||
	IFT_ISO88022LLC                   = 0x29
 | 
			
		||||
	IFT_ISO88023                      = 0x7
 | 
			
		||||
	IFT_ISO88024                      = 0x8
 | 
			
		||||
	IFT_ISO88025                      = 0x9
 | 
			
		||||
	IFT_ISO88025CRFPINT               = 0x62
 | 
			
		||||
	IFT_ISO88025DTR                   = 0x56
 | 
			
		||||
	IFT_ISO88025FIBER                 = 0x73
 | 
			
		||||
	IFT_ISO88026                      = 0xa
 | 
			
		||||
	IFT_ISUP                          = 0xb3
 | 
			
		||||
	IFT_L3IPXVLAN                     = 0x89
 | 
			
		||||
	IFT_LAPB                          = 0x10
 | 
			
		||||
	IFT_LAPD                          = 0x4d
 | 
			
		||||
	IFT_LAPF                          = 0x77
 | 
			
		||||
	IFT_LOCALTALK                     = 0x2a
 | 
			
		||||
	IFT_LOOP                          = 0x18
 | 
			
		||||
	IFT_MEDIAMAILOVERIP               = 0x8b
 | 
			
		||||
	IFT_MFSIGLINK                     = 0xa7
 | 
			
		||||
	IFT_MIOX25                        = 0x26
 | 
			
		||||
	IFT_MODEM                         = 0x30
 | 
			
		||||
	IFT_MPC                           = 0x71
 | 
			
		||||
	IFT_MPLS                          = 0xa6
 | 
			
		||||
	IFT_MPLSTUNNEL                    = 0x96
 | 
			
		||||
	IFT_MSDSL                         = 0x8f
 | 
			
		||||
	IFT_MVL                           = 0xbf
 | 
			
		||||
	IFT_MYRINET                       = 0x63
 | 
			
		||||
	IFT_NFAS                          = 0xaf
 | 
			
		||||
	IFT_NSIP                          = 0x1b
 | 
			
		||||
	IFT_OPTICALCHANNEL                = 0xc3
 | 
			
		||||
	IFT_OPTICALTRANSPORT              = 0xc4
 | 
			
		||||
	IFT_OTHER                         = 0x1
 | 
			
		||||
	IFT_P10                           = 0xc
 | 
			
		||||
	IFT_P80                           = 0xd
 | 
			
		||||
	IFT_PARA                          = 0x22
 | 
			
		||||
	IFT_PFLOG                         = 0xf6
 | 
			
		||||
	IFT_PFSYNC                        = 0xf7
 | 
			
		||||
	IFT_PLC                           = 0xae
 | 
			
		||||
	IFT_POS                           = 0xab
 | 
			
		||||
	IFT_PPPMULTILINKBUNDLE            = 0x6c
 | 
			
		||||
	IFT_PROPBWAP2MP                   = 0xb8
 | 
			
		||||
	IFT_PROPCNLS                      = 0x59
 | 
			
		||||
	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
 | 
			
		||||
	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
 | 
			
		||||
	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
 | 
			
		||||
	IFT_PROPMUX                       = 0x36
 | 
			
		||||
	IFT_PROPWIRELESSP2P               = 0x9d
 | 
			
		||||
	IFT_PTPSERIAL                     = 0x16
 | 
			
		||||
	IFT_PVC                           = 0xf1
 | 
			
		||||
	IFT_QLLC                          = 0x44
 | 
			
		||||
	IFT_RADIOMAC                      = 0xbc
 | 
			
		||||
	IFT_RADSL                         = 0x5f
 | 
			
		||||
	IFT_REACHDSL                      = 0xc0
 | 
			
		||||
	IFT_RFC1483                       = 0x9f
 | 
			
		||||
	IFT_RS232                         = 0x21
 | 
			
		||||
	IFT_RSRB                          = 0x4f
 | 
			
		||||
	IFT_SDLC                          = 0x11
 | 
			
		||||
	IFT_SDSL                          = 0x60
 | 
			
		||||
	IFT_SHDSL                         = 0xa9
 | 
			
		||||
	IFT_SIP                           = 0x1f
 | 
			
		||||
	IFT_SLIP                          = 0x1c
 | 
			
		||||
	IFT_SMDSDXI                       = 0x2b
 | 
			
		||||
	IFT_SMDSICIP                      = 0x34
 | 
			
		||||
	IFT_SONET                         = 0x27
 | 
			
		||||
	IFT_SONETOVERHEADCHANNEL          = 0xb9
 | 
			
		||||
	IFT_SONETPATH                     = 0x32
 | 
			
		||||
	IFT_SONETVT                       = 0x33
 | 
			
		||||
	IFT_SRP                           = 0x97
 | 
			
		||||
	IFT_SS7SIGLINK                    = 0x9c
 | 
			
		||||
	IFT_STACKTOSTACK                  = 0x6f
 | 
			
		||||
	IFT_STARLAN                       = 0xb
 | 
			
		||||
	IFT_STF                           = 0xd7
 | 
			
		||||
	IFT_T1                            = 0x12
 | 
			
		||||
	IFT_TDLC                          = 0x74
 | 
			
		||||
	IFT_TERMPAD                       = 0x5b
 | 
			
		||||
	IFT_TR008                         = 0xb0
 | 
			
		||||
	IFT_TRANSPHDLC                    = 0x7b
 | 
			
		||||
	IFT_TUNNEL                        = 0x83
 | 
			
		||||
	IFT_ULTRA                         = 0x1d
 | 
			
		||||
	IFT_USB                           = 0xa0
 | 
			
		||||
	IFT_V11                           = 0x40
 | 
			
		||||
	IFT_V35                           = 0x2d
 | 
			
		||||
	IFT_V36                           = 0x41
 | 
			
		||||
	IFT_V37                           = 0x78
 | 
			
		||||
	IFT_VDSL                          = 0x61
 | 
			
		||||
	IFT_VIRTUALIPADDRESS              = 0x70
 | 
			
		||||
	IFT_VOICEEM                       = 0x64
 | 
			
		||||
	IFT_VOICEENCAP                    = 0x67
 | 
			
		||||
	IFT_VOICEFXO                      = 0x65
 | 
			
		||||
	IFT_VOICEFXS                      = 0x66
 | 
			
		||||
	IFT_VOICEOVERATM                  = 0x98
 | 
			
		||||
	IFT_VOICEOVERFRAMERELAY           = 0x99
 | 
			
		||||
	IFT_VOICEOVERIP                   = 0x68
 | 
			
		||||
	IFT_X213                          = 0x5d
 | 
			
		||||
	IFT_X25                           = 0x5
 | 
			
		||||
	IFT_X25DDN                        = 0x4
 | 
			
		||||
	IFT_X25HUNTGROUP                  = 0x7a
 | 
			
		||||
	IFT_X25MLP                        = 0x79
 | 
			
		||||
	IFT_X25PLE                        = 0x28
 | 
			
		||||
	IFT_XETHER                        = 0x1a
 | 
			
		||||
 | 
			
		||||
	// missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go
 | 
			
		||||
	IFF_SMART       = 0x20
 | 
			
		||||
	IFT_FAITH       = 0xf2
 | 
			
		||||
	IFT_IPXIP       = 0xf9
 | 
			
		||||
	IPPROTO_MAXID   = 0x34
 | 
			
		||||
	IPV6_FAITH      = 0x1d
 | 
			
		||||
	IP_FAITH        = 0x16
 | 
			
		||||
	MAP_NORESERVE   = 0x40
 | 
			
		||||
	MAP_RENAME      = 0x20
 | 
			
		||||
	NET_RT_MAXID    = 0x6
 | 
			
		||||
	RTF_PRCLONING   = 0x10000
 | 
			
		||||
	RTM_OLDADD      = 0x9
 | 
			
		||||
	RTM_OLDDEL      = 0xa
 | 
			
		||||
	SIOCADDRT       = 0x8030720a
 | 
			
		||||
	SIOCALIFADDR    = 0x8118691b
 | 
			
		||||
	SIOCDELRT       = 0x8030720b
 | 
			
		||||
	SIOCDLIFADDR    = 0x8118691d
 | 
			
		||||
	SIOCGLIFADDR    = 0xc118691c
 | 
			
		||||
	SIOCGLIFPHYADDR = 0xc118694b
 | 
			
		||||
	SIOCSLIFPHYADDR = 0x8118694a
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
// +build linux darwin freebsd openbsd netbsd dragonfly
 | 
			
		||||
 | 
			
		||||
// Copyright 2014 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.
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +12,16 @@ import "unsafe"
 | 
			
		|||
// systems by flock_linux_32bit.go to be SYS_FCNTL64.
 | 
			
		||||
var fcntl64Syscall uintptr = SYS_FCNTL
 | 
			
		||||
 | 
			
		||||
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
 | 
			
		||||
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
 | 
			
		||||
	valptr, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(arg))
 | 
			
		||||
	var err error
 | 
			
		||||
	if errno != 0 {
 | 
			
		||||
		err = errno
 | 
			
		||||
	}
 | 
			
		||||
	return int(valptr), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
 | 
			
		||||
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
 | 
			
		||||
	_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +1,30 @@
 | 
			
		|||
// Copyright 2015 The Go Authors.  All rights reserved.
 | 
			
		||||
// Copyright 2015 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 gccgo
 | 
			
		||||
// +build !aix
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
// We can't use the gc-syntax .s files for gccgo.  On the plus side
 | 
			
		||||
// We can't use the gc-syntax .s files for gccgo. On the plus side
 | 
			
		||||
// much of the functionality can be written directly in Go.
 | 
			
		||||
 | 
			
		||||
//extern gccgoRealSyscallNoError
 | 
			
		||||
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
 | 
			
		||||
 | 
			
		||||
//extern gccgoRealSyscall
 | 
			
		||||
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
 | 
			
		||||
 | 
			
		||||
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
 | 
			
		||||
	syscall.Entersyscall()
 | 
			
		||||
	r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
 | 
			
		||||
	syscall.Exitsyscall()
 | 
			
		||||
	return r, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 | 
			
		||||
	syscall.Entersyscall()
 | 
			
		||||
	r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +46,11 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
 | 
			
		|||
	return r, 0, syscall.Errno(errno)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
 | 
			
		||||
	r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
 | 
			
		||||
	return r, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
 | 
			
		||||
	r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
 | 
			
		||||
	return r, 0, syscall.Errno(errno)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,9 @@
 | 
			
		|||
// Copyright 2015 The Go Authors.  All rights reserved.
 | 
			
		||||
// Copyright 2015 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 gccgo
 | 
			
		||||
// +build !aix
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -31,11 +32,8 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
 | 
			
		|||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Define the use function in C so that it is not inlined.
 | 
			
		||||
 | 
			
		||||
extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
use(void *p __attribute__ ((unused)))
 | 
			
		||||
uintptr_t
 | 
			
		||||
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
 | 
			
		||||
{
 | 
			
		||||
	return syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// Copyright 2015 The Go Authors.  All rights reserved.
 | 
			
		||||
// Copyright 2015 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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,20 +0,0 @@
 | 
			
		|||
// Copyright 2016 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 gccgo,linux,sparc64
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
//extern sysconf
 | 
			
		||||
func realSysconf(name int) int64
 | 
			
		||||
 | 
			
		||||
func sysconf(name int) (n int64, err syscall.Errno) {
 | 
			
		||||
	r := realSysconf(name)
 | 
			
		||||
	if r < 0 {
 | 
			
		||||
		return 0, syscall.GetErrno()
 | 
			
		||||
	}
 | 
			
		||||
	return r, 0
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// 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 aix darwin dragonfly freebsd linux netbsd openbsd solaris
 | 
			
		||||
 | 
			
		||||
package unix
 | 
			
		||||
 | 
			
		||||
import "runtime"
 | 
			
		||||
 | 
			
		||||
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
 | 
			
		||||
//
 | 
			
		||||
// To change fd's window size, the req argument should be TIOCSWINSZ.
 | 
			
		||||
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
 | 
			
		||||
	// TODO: if we get the chance, remove the req parameter and
 | 
			
		||||
	// hardcode TIOCSWINSZ.
 | 
			
		||||
	err := ioctlSetWinsize(fd, req, value)
 | 
			
		||||
	runtime.KeepAlive(value)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IoctlSetTermios performs an ioctl on fd with a *Termios.
 | 
			
		||||
//
 | 
			
		||||
// The req value will usually be TCSETA or TIOCSETA.
 | 
			
		||||
func IoctlSetTermios(fd int, req uint, value *Termios) error {
 | 
			
		||||
	// TODO: if we get the chance, remove the req parameter.
 | 
			
		||||
	err := ioctlSetTermios(fd, req, value)
 | 
			
		||||
	runtime.KeepAlive(value)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,75 +3,9 @@
 | 
			
		|||
# Use of this source code is governed by a BSD-style
 | 
			
		||||
# license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
# The unix package provides access to the raw system call
 | 
			
		||||
# interface of the underlying operating system.  Porting Go to
 | 
			
		||||
# a new architecture/operating system combination requires
 | 
			
		||||
# some manual effort, though there are tools that automate
 | 
			
		||||
# much of the process.  The auto-generated files have names
 | 
			
		||||
# beginning with z.
 | 
			
		||||
#
 | 
			
		||||
# This script runs or (given -n) prints suggested commands to generate z files
 | 
			
		||||
# for the current system.  Running those commands is not automatic.
 | 
			
		||||
# This script is documentation more than anything else.
 | 
			
		||||
#
 | 
			
		||||
# * asm_${GOOS}_${GOARCH}.s
 | 
			
		||||
#
 | 
			
		||||
# This hand-written assembly file implements system call dispatch.
 | 
			
		||||
# There are three entry points:
 | 
			
		||||
#
 | 
			
		||||
# 	func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
 | 
			
		||||
# 	func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
 | 
			
		||||
# 	func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
 | 
			
		||||
#
 | 
			
		||||
# The first and second are the standard ones; they differ only in
 | 
			
		||||
# how many arguments can be passed to the kernel.
 | 
			
		||||
# The third is for low-level use by the ForkExec wrapper;
 | 
			
		||||
# unlike the first two, it does not call into the scheduler to
 | 
			
		||||
# let it know that a system call is running.
 | 
			
		||||
#
 | 
			
		||||
# * syscall_${GOOS}.go
 | 
			
		||||
#
 | 
			
		||||
# This hand-written Go file implements system calls that need
 | 
			
		||||
# special handling and lists "//sys" comments giving prototypes
 | 
			
		||||
# for ones that can be auto-generated.  Mksyscall reads those
 | 
			
		||||
# comments to generate the stubs.
 | 
			
		||||
#
 | 
			
		||||
# * syscall_${GOOS}_${GOARCH}.go
 | 
			
		||||
#
 | 
			
		||||
# Same as syscall_${GOOS}.go except that it contains code specific
 | 
			
		||||
# to ${GOOS} on one particular architecture.
 | 
			
		||||
#
 | 
			
		||||
# * types_${GOOS}.c
 | 
			
		||||
#
 | 
			
		||||
# This hand-written C file includes standard C headers and then
 | 
			
		||||
# creates typedef or enum names beginning with a dollar sign
 | 
			
		||||
# (use of $ in variable names is a gcc extension).  The hardest
 | 
			
		||||
# part about preparing this file is figuring out which headers to
 | 
			
		||||
# include and which symbols need to be #defined to get the
 | 
			
		||||
# actual data structures that pass through to the kernel system calls.
 | 
			
		||||
# Some C libraries present alternate versions for binary compatibility
 | 
			
		||||
# and translate them on the way in and out of system calls, but
 | 
			
		||||
# there is almost always a #define that can get the real ones.
 | 
			
		||||
# See types_darwin.c and types_linux.c for examples.
 | 
			
		||||
#
 | 
			
		||||
# * zerror_${GOOS}_${GOARCH}.go
 | 
			
		||||
#
 | 
			
		||||
# This machine-generated file defines the system's error numbers,
 | 
			
		||||
# error strings, and signal numbers.  The generator is "mkerrors.sh".
 | 
			
		||||
# Usually no arguments are needed, but mkerrors.sh will pass its
 | 
			
		||||
# arguments on to godefs.
 | 
			
		||||
#
 | 
			
		||||
# * zsyscall_${GOOS}_${GOARCH}.go
 | 
			
		||||
#
 | 
			
		||||
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
 | 
			
		||||
#
 | 
			
		||||
# * zsysnum_${GOOS}_${GOARCH}.go
 | 
			
		||||
#
 | 
			
		||||
# Generated by mksysnum_${GOOS}.
 | 
			
		||||
#
 | 
			
		||||
# * ztypes_${GOOS}_${GOARCH}.go
 | 
			
		||||
#
 | 
			
		||||
# Generated by godefs; see types_${GOOS}.c above.
 | 
			
		||||
# This script runs or (given -n) prints suggested commands to generate files for
 | 
			
		||||
# the Architecture/OS specified by the GOARCH and GOOS environment variables.
 | 
			
		||||
# See README.md for more information about how the build system works.
 | 
			
		||||
 | 
			
		||||
GOOSARCH="${GOOS}_${GOARCH}"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +18,7 @@ zsysctl="zsysctl_$GOOSARCH.go"
 | 
			
		|||
mksysnum=
 | 
			
		||||
mktypes=
 | 
			
		||||
run="sh"
 | 
			
		||||
cmd=""
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
-syscalls)
 | 
			
		||||
| 
						 | 
				
			
			@ -98,6 +33,7 @@ case "$1" in
 | 
			
		|||
	;;
 | 
			
		||||
-n)
 | 
			
		||||
	run="cat"
 | 
			
		||||
	cmd="echo"
 | 
			
		||||
	shift
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,12 +45,30 @@ case "$#" in
 | 
			
		|||
	exit 2
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
 | 
			
		||||
	# Use then new build system
 | 
			
		||||
	# Files generated through docker (use $cmd so you can Ctl-C the build or run)
 | 
			
		||||
	$cmd docker build --tag generate:$GOOS $GOOS
 | 
			
		||||
	$cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
 | 
			
		||||
	exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
GOOSARCH_in=syscall_$GOOSARCH.go
 | 
			
		||||
case "$GOOSARCH" in
 | 
			
		||||
_* | *_ | _)
 | 
			
		||||
	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
 | 
			
		||||
	exit 1
 | 
			
		||||
	;;
 | 
			
		||||
aix_ppc)
 | 
			
		||||
	mkerrors="$mkerrors -maix32"
 | 
			
		||||
	mksyscall="./mksyscall_aix_ppc.pl -aix"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
aix_ppc64)
 | 
			
		||||
	mkerrors="$mkerrors -maix64"
 | 
			
		||||
	mksyscall="./mksyscall_aix_ppc64.pl -aix"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
darwin_386)
 | 
			
		||||
	mkerrors="$mkerrors -m32"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32"
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +82,7 @@ darwin_amd64)
 | 
			
		|||
	;;
 | 
			
		||||
darwin_arm)
 | 
			
		||||
	mkerrors="$mkerrors"
 | 
			
		||||
	mksysnum="./mksysnum_darwin.pl /usr/include/sys/syscall.h"
 | 
			
		||||
	mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
darwin_arm64)
 | 
			
		||||
| 
						 | 
				
			
			@ -136,12 +90,6 @@ darwin_arm64)
 | 
			
		|||
	mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
dragonfly_386)
 | 
			
		||||
	mkerrors="$mkerrors -m32"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32 -dragonfly"
 | 
			
		||||
	mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
dragonfly_amd64)
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksyscall="./mksyscall.pl -dragonfly"
 | 
			
		||||
| 
						 | 
				
			
			@ -164,65 +112,7 @@ freebsd_arm)
 | 
			
		|||
	mksyscall="./mksyscall.pl -l32 -arm"
 | 
			
		||||
	mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
 | 
			
		||||
	# Let the type of C char be signed for making the bare syscall
 | 
			
		||||
	# API consistent across over platforms.
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
 | 
			
		||||
	;;
 | 
			
		||||
linux_386)
 | 
			
		||||
	mkerrors="$mkerrors -m32"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32"
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl /usr/include/asm/unistd_32.h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
linux_amd64)
 | 
			
		||||
	unistd_h=$(ls -1 /usr/include/asm/unistd_64.h /usr/include/x86_64-linux-gnu/asm/unistd_64.h 2>/dev/null | head -1)
 | 
			
		||||
	if [ "$unistd_h" = "" ]; then
 | 
			
		||||
		echo >&2 cannot find unistd_64.h
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl $unistd_h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
linux_arm)
 | 
			
		||||
	mkerrors="$mkerrors"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32 -arm"
 | 
			
		||||
	mksysnum="curl -s 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/arch/arm/include/uapi/asm/unistd.h' | ./mksysnum_linux.pl -"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
linux_arm64)
 | 
			
		||||
	unistd_h=$(ls -1 /usr/include/asm/unistd.h /usr/include/asm-generic/unistd.h 2>/dev/null | head -1)
 | 
			
		||||
	if [ "$unistd_h" = "" ]; then
 | 
			
		||||
		echo >&2 cannot find unistd_64.h
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl $unistd_h"
 | 
			
		||||
	# Let the type of C char be signed for making the bare syscall
 | 
			
		||||
	# API consistent across over platforms.
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
 | 
			
		||||
	;;
 | 
			
		||||
linux_ppc64)
 | 
			
		||||
	GOOSARCH_in=syscall_linux_ppc64x.go
 | 
			
		||||
	unistd_h=/usr/include/asm/unistd.h
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl $unistd_h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
linux_ppc64le)
 | 
			
		||||
	GOOSARCH_in=syscall_linux_ppc64x.go
 | 
			
		||||
	unistd_h=/usr/include/powerpc64le-linux-gnu/asm/unistd.h
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl $unistd_h"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
linux_s390x)
 | 
			
		||||
	GOOSARCH_in=syscall_linux_s390x.go
 | 
			
		||||
	unistd_h=/usr/include/asm/unistd.h
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksysnum="./mksysnum_linux.pl $unistd_h"
 | 
			
		||||
	# Let the type of C char be signed to make the bare sys
 | 
			
		||||
	# API more consistent between platforms.
 | 
			
		||||
	# This is a deliberate departure from the way the syscall
 | 
			
		||||
	# package generates its version of the types file.
 | 
			
		||||
	# API consistent across platforms.
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
 | 
			
		||||
	;;
 | 
			
		||||
linux_sparc64)
 | 
			
		||||
| 
						 | 
				
			
			@ -244,11 +134,18 @@ netbsd_amd64)
 | 
			
		|||
	mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
netbsd_arm)
 | 
			
		||||
	mkerrors="$mkerrors"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32 -netbsd -arm"
 | 
			
		||||
	mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
 | 
			
		||||
	# Let the type of C char be signed for making the bare syscall
 | 
			
		||||
	# API consistent across platforms.
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
 | 
			
		||||
	;;
 | 
			
		||||
openbsd_386)
 | 
			
		||||
	mkerrors="$mkerrors -m32"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32 -openbsd"
 | 
			
		||||
	mksysctl="./mksysctl_openbsd.pl"
 | 
			
		||||
	zsysctl="zsysctl_openbsd.go"
 | 
			
		||||
	mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
| 
						 | 
				
			
			@ -256,10 +153,18 @@ openbsd_amd64)
 | 
			
		|||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
	mksyscall="./mksyscall.pl -openbsd"
 | 
			
		||||
	mksysctl="./mksysctl_openbsd.pl"
 | 
			
		||||
	zsysctl="zsysctl_openbsd.go"
 | 
			
		||||
	mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 | 
			
		||||
	;;
 | 
			
		||||
openbsd_arm)
 | 
			
		||||
	mkerrors="$mkerrors"
 | 
			
		||||
	mksyscall="./mksyscall.pl -l32 -openbsd -arm"
 | 
			
		||||
	mksysctl="./mksysctl_openbsd.pl"
 | 
			
		||||
	mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
 | 
			
		||||
	# Let the type of C char be signed for making the bare syscall
 | 
			
		||||
	# API consistent across platforms.
 | 
			
		||||
	mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
 | 
			
		||||
	;;
 | 
			
		||||
solaris_amd64)
 | 
			
		||||
	mksyscall="./mksyscall_solaris.pl"
 | 
			
		||||
	mkerrors="$mkerrors -m64"
 | 
			
		||||
| 
						 | 
				
			
			@ -282,13 +187,18 @@ esac
 | 
			
		|||
			syscall_goos="syscall_bsd.go $syscall_goos"
 | 
			
		||||
			;;
 | 
			
		||||
		esac
 | 
			
		||||
		if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
 | 
			
		||||
		;;
 | 
			
		||||
		if [ -n "$mksyscall" ]; then
 | 
			
		||||
			if [ "$GOOSARCH" == "aix_ppc64" ]; then
 | 
			
		||||
				# aix/ppc64 script generates files instead of writing to stdin.
 | 
			
		||||
				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
 | 
			
		||||
			else
 | 
			
		||||
				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
	esac
 | 
			
		||||
	if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
 | 
			
		||||
	if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
 | 
			
		||||
	if [ -n "$mktypes" ]; then
 | 
			
		||||
		echo "echo // +build $GOARCH,$GOOS > ztypes_$GOOSARCH.go";
 | 
			
		||||
		echo "$mktypes types_$GOOS.go | go run mkpost.go >>ztypes_$GOOSARCH.go";
 | 
			
		||||
		echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go";
 | 
			
		||||
	fi
 | 
			
		||||
) | $run
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,19 +16,49 @@ if test -z "$GOARCH" -o -z "$GOOS"; then
 | 
			
		|||
	exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
CC=${CC:-cc}
 | 
			
		||||
# Check that we are using the new build system if we should
 | 
			
		||||
if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
 | 
			
		||||
	if [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
 | 
			
		||||
		echo 1>&2 "In the new build system, mkerrors should not be called directly."
 | 
			
		||||
		echo 1>&2 "See README.md"
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ "$GOOS" -eq "solaris" ]]; then
 | 
			
		||||
if [[ "$GOOS" = "aix" ]]; then
 | 
			
		||||
	CC=${CC:-gcc}
 | 
			
		||||
else
 | 
			
		||||
	CC=${CC:-cc}
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ "$GOOS" = "solaris" ]]; then
 | 
			
		||||
	# Assumes GNU versions of utilities in PATH.
 | 
			
		||||
	export PATH=/usr/gnu/bin:$PATH
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
uname=$(uname)
 | 
			
		||||
 | 
			
		||||
includes_AIX='
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <net/netopt.h>
 | 
			
		||||
#include <netinet/ip_mroute.h>
 | 
			
		||||
#include <sys/protosw.h>
 | 
			
		||||
#include <sys/stropts.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/poll.h>
 | 
			
		||||
#include <sys/termio.h>
 | 
			
		||||
#include <termios.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#define AF_LOCAL AF_UNIX
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
includes_Darwin='
 | 
			
		||||
#define _DARWIN_C_SOURCE
 | 
			
		||||
#define KERNEL
 | 
			
		||||
#define _DARWIN_USE_64_BIT_INODE
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <sys/attr.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/event.h>
 | 
			
		||||
#include <sys/ptrace.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +66,10 @@ includes_Darwin='
 | 
			
		|||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <sys/xattr.h>
 | 
			
		||||
#include <net/bpf.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <net/if_types.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +84,10 @@ includes_DragonFly='
 | 
			
		|||
#include <sys/event.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <net/bpf.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -66,13 +101,16 @@ includes_DragonFly='
 | 
			
		|||
'
 | 
			
		||||
 | 
			
		||||
includes_FreeBSD='
 | 
			
		||||
#include <sys/capsicum.h>
 | 
			
		||||
#include <sys/param.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/event.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <net/bpf.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -102,8 +140,39 @@ includes_Linux='
 | 
			
		|||
#endif
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
// <sys/ioctl.h> is broken on powerpc64, as it fails to include definitions of
 | 
			
		||||
// these structures. We just include them copied from <bits/termios.h>.
 | 
			
		||||
#if defined(__powerpc__)
 | 
			
		||||
struct sgttyb {
 | 
			
		||||
        char    sg_ispeed;
 | 
			
		||||
        char    sg_ospeed;
 | 
			
		||||
        char    sg_erase;
 | 
			
		||||
        char    sg_kill;
 | 
			
		||||
        short   sg_flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tchars {
 | 
			
		||||
        char    t_intrc;
 | 
			
		||||
        char    t_quitc;
 | 
			
		||||
        char    t_startc;
 | 
			
		||||
        char    t_stopc;
 | 
			
		||||
        char    t_eofc;
 | 
			
		||||
        char    t_brkc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ltchars {
 | 
			
		||||
        char    t_suspc;
 | 
			
		||||
        char    t_dsuspc;
 | 
			
		||||
        char    t_rprntc;
 | 
			
		||||
        char    t_flushc;
 | 
			
		||||
        char    t_werasc;
 | 
			
		||||
        char    t_lnextc;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <bits/sockaddr.h>
 | 
			
		||||
#include <sys/epoll.h>
 | 
			
		||||
#include <sys/eventfd.h>
 | 
			
		||||
#include <sys/inotify.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +182,7 @@ includes_Linux='
 | 
			
		|||
#include <sys/types.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/xattr.h>
 | 
			
		||||
#include <linux/if.h>
 | 
			
		||||
#include <linux/if_alg.h>
 | 
			
		||||
#include <linux/if_arp.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -122,15 +192,35 @@ includes_Linux='
 | 
			
		|||
#include <linux/if_addr.h>
 | 
			
		||||
#include <linux/falloc.h>
 | 
			
		||||
#include <linux/filter.h>
 | 
			
		||||
#include <linux/fs.h>
 | 
			
		||||
#include <linux/kexec.h>
 | 
			
		||||
#include <linux/keyctl.h>
 | 
			
		||||
#include <linux/magic.h>
 | 
			
		||||
#include <linux/memfd.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/netfilter/nfnetlink.h>
 | 
			
		||||
#include <linux/netlink.h>
 | 
			
		||||
#include <linux/net_namespace.h>
 | 
			
		||||
#include <linux/perf_event.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/reboot.h>
 | 
			
		||||
#include <linux/rtnetlink.h>
 | 
			
		||||
#include <linux/ptrace.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/seccomp.h>
 | 
			
		||||
#include <linux/sockios.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/icmpv6.h>
 | 
			
		||||
#include <linux/serial.h>
 | 
			
		||||
#include <linux/can.h>
 | 
			
		||||
#include <linux/vm_sockets.h>
 | 
			
		||||
#include <linux/taskstats.h>
 | 
			
		||||
#include <linux/genetlink.h>
 | 
			
		||||
#include <linux/watchdog.h>
 | 
			
		||||
#include <linux/hdreg.h>
 | 
			
		||||
#include <linux/rtc.h>
 | 
			
		||||
#include <linux/if_xdp.h>
 | 
			
		||||
#include <mtd/ubi-user.h>
 | 
			
		||||
#include <net/route.h>
 | 
			
		||||
#include <asm/termbits.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,18 +236,39 @@ includes_Linux='
 | 
			
		|||
#define PTRACE_SETREGS	0xd
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef SOL_NETLINK
 | 
			
		||||
#define SOL_NETLINK	270
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SOL_BLUETOOTH
 | 
			
		||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
 | 
			
		||||
// but it is already in bluetooth_linux.go
 | 
			
		||||
#undef SOL_BLUETOOTH
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Certain constants are missing from the fs/crypto UAPI
 | 
			
		||||
#define FS_KEY_DESC_PREFIX              "fscrypt:"
 | 
			
		||||
#define FS_KEY_DESC_PREFIX_SIZE         8
 | 
			
		||||
#define FS_MAX_KEY_SIZE                 64
 | 
			
		||||
 | 
			
		||||
// XDP socket constants do not appear to be picked up otherwise.
 | 
			
		||||
// Copied from samples/bpf/xdpsock_user.c.
 | 
			
		||||
#ifndef SOL_XDP
 | 
			
		||||
#define SOL_XDP 283
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef AF_XDP
 | 
			
		||||
#define AF_XDP 44
 | 
			
		||||
#endif
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
includes_NetBSD='
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/param.h>
 | 
			
		||||
#include <sys/event.h>
 | 
			
		||||
#include <sys/extattr.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -183,11 +294,14 @@ includes_OpenBSD='
 | 
			
		|||
#include <sys/param.h>
 | 
			
		||||
#include <sys/event.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <sys/termios.h>
 | 
			
		||||
#include <sys/ttycom.h>
 | 
			
		||||
#include <sys/unistd.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <net/bpf.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -219,9 +333,11 @@ includes_SunOS='
 | 
			
		|||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mkdev.h>
 | 
			
		||||
#include <net/bpf.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <net/if_arp.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -280,12 +396,14 @@ ccflags="$@"
 | 
			
		|||
		$2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
 | 
			
		||||
		$2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
 | 
			
		||||
 | 
			
		||||
		$2 !~ /^ECCAPBITS/ &&
 | 
			
		||||
		$2 !~ /^ETH_/ &&
 | 
			
		||||
		$2 !~ /^EPROC_/ &&
 | 
			
		||||
		$2 !~ /^EQUIV_/ &&
 | 
			
		||||
		$2 !~ /^EXPR_/ &&
 | 
			
		||||
		$2 ~ /^E[A-Z0-9_]+$/ ||
 | 
			
		||||
		$2 ~ /^B[0-9_]+$/ ||
 | 
			
		||||
		$2 ~ /^(OLD|NEW)DEV$/ ||
 | 
			
		||||
		$2 == "BOTHER" ||
 | 
			
		||||
		$2 ~ /^CI?BAUD(EX)?$/ ||
 | 
			
		||||
		$2 == "IBSHIFT" ||
 | 
			
		||||
| 
						 | 
				
			
			@ -295,6 +413,7 @@ ccflags="$@"
 | 
			
		|||
		$2 ~ /^IGN/ ||
 | 
			
		||||
		$2 ~ /^IX(ON|ANY|OFF)$/ ||
 | 
			
		||||
		$2 ~ /^IN(LCR|PCK)$/ ||
 | 
			
		||||
		$2 !~ "X86_CR3_PCID_NOFLUSH" &&
 | 
			
		||||
		$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
 | 
			
		||||
		$2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
 | 
			
		||||
		$2 == "BRKINT" ||
 | 
			
		||||
| 
						 | 
				
			
			@ -313,21 +432,27 @@ ccflags="$@"
 | 
			
		|||
		$2 ~ /^TC[IO](ON|OFF)$/ ||
 | 
			
		||||
		$2 ~ /^IN_/ ||
 | 
			
		||||
		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
 | 
			
		||||
		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 | 
			
		||||
		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 | 
			
		||||
		$2 ~ /^TP_STATUS_/ ||
 | 
			
		||||
		$2 ~ /^FALLOC_/ ||
 | 
			
		||||
		$2 == "ICMPV6_FILTER" ||
 | 
			
		||||
		$2 == "SOMAXCONN" ||
 | 
			
		||||
		$2 == "NAME_MAX" ||
 | 
			
		||||
		$2 == "IFNAMSIZ" ||
 | 
			
		||||
		$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
 | 
			
		||||
		$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
 | 
			
		||||
		$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
 | 
			
		||||
		$2 ~ /^HW_MACHINE$/ ||
 | 
			
		||||
		$2 ~ /^SYSCTL_VERS/ ||
 | 
			
		||||
		$2 ~ /^(MS|MNT)_/ ||
 | 
			
		||||
		$2 !~ "MNT_BITS" &&
 | 
			
		||||
		$2 ~ /^(MS|MNT|UMOUNT)_/ ||
 | 
			
		||||
		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
 | 
			
		||||
		$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
 | 
			
		||||
		$2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ ||
 | 
			
		||||
		$2 ~ /^KEXEC_/ ||
 | 
			
		||||
		$2 ~ /^LINUX_REBOOT_CMD_/ ||
 | 
			
		||||
		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
 | 
			
		||||
		$2 ~ /^MODULE_INIT_/ ||
 | 
			
		||||
		$2 !~ "NLA_TYPE_MASK" &&
 | 
			
		||||
		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
 | 
			
		||||
		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
 | 
			
		||||
		$2 ~ /^SIOC/ ||
 | 
			
		||||
		$2 ~ /^TIOC/ ||
 | 
			
		||||
		$2 ~ /^TCGET/ ||
 | 
			
		||||
| 
						 | 
				
			
			@ -337,17 +462,45 @@ ccflags="$@"
 | 
			
		|||
		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
 | 
			
		||||
		$2 ~ /^BIOC/ ||
 | 
			
		||||
		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
 | 
			
		||||
		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
 | 
			
		||||
		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
 | 
			
		||||
		$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
 | 
			
		||||
		$2 ~ /^CLONE_[A-Z_]+/ ||
 | 
			
		||||
		$2 !~ /^(BPF_TIMEVAL)$/ &&
 | 
			
		||||
		$2 ~ /^(BPF|DLT)_/ ||
 | 
			
		||||
		$2 ~ /^CLOCK_/ ||
 | 
			
		||||
		$2 ~ /^CAN_/ ||
 | 
			
		||||
		$2 ~ /^CAP_/ ||
 | 
			
		||||
		$2 ~ /^ALG_/ ||
 | 
			
		||||
		$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
 | 
			
		||||
		$2 ~ /^GRND_/ ||
 | 
			
		||||
		$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
 | 
			
		||||
		$2 ~ /^KEYCTL_/ ||
 | 
			
		||||
		$2 ~ /^PERF_EVENT_IOC_/ ||
 | 
			
		||||
		$2 ~ /^SECCOMP_MODE_/ ||
 | 
			
		||||
		$2 ~ /^SPLICE_/ ||
 | 
			
		||||
		$2 ~ /^SYNC_FILE_RANGE_/ ||
 | 
			
		||||
		$2 !~ /^AUDIT_RECORD_MAGIC/ &&
 | 
			
		||||
		$2 !~ /IOC_MAGIC/ &&
 | 
			
		||||
		$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
 | 
			
		||||
		$2 ~ /^(VM|VMADDR)_/ ||
 | 
			
		||||
		$2 ~ /^IOCTL_VM_SOCKETS_/ ||
 | 
			
		||||
		$2 ~ /^(TASKSTATS|TS)_/ ||
 | 
			
		||||
		$2 ~ /^CGROUPSTATS_/ ||
 | 
			
		||||
		$2 ~ /^GENL_/ ||
 | 
			
		||||
		$2 ~ /^STATX_/ ||
 | 
			
		||||
		$2 ~ /^RENAME/ ||
 | 
			
		||||
		$2 ~ /^UBI_IOC[A-Z]/ ||
 | 
			
		||||
		$2 ~ /^UTIME_/ ||
 | 
			
		||||
		$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
 | 
			
		||||
		$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
 | 
			
		||||
		$2 ~ /^FSOPT_/ ||
 | 
			
		||||
		$2 ~ /^WDIOC_/ ||
 | 
			
		||||
		$2 ~ /^NFN/ ||
 | 
			
		||||
		$2 ~ /^XDP_/ ||
 | 
			
		||||
		$2 ~ /^(HDIO|WIN|SMART)_/ ||
 | 
			
		||||
		$2 !~ "WMESGLEN" &&
 | 
			
		||||
		$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
 | 
			
		||||
		$2 ~ /^W[A-Z0-9]+$/ ||
 | 
			
		||||
		$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
 | 
			
		||||
		$2 ~ /^__WCOREFLAG$/ {next}
 | 
			
		||||
		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +521,7 @@ errors=$(
 | 
			
		|||
signals=$(
 | 
			
		||||
	echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
 | 
			
		||||
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
 | 
			
		||||
	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
 | 
			
		||||
	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
 | 
			
		||||
	sort
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -378,11 +531,11 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
 | 
			
		|||
	sort >_error.grep
 | 
			
		||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
 | 
			
		||||
	awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
 | 
			
		||||
	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
 | 
			
		||||
	egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
 | 
			
		||||
	sort >_signal.grep
 | 
			
		||||
 | 
			
		||||
echo '// mkerrors.sh' "$@"
 | 
			
		||||
echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
 | 
			
		||||
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
 | 
			
		||||
echo
 | 
			
		||||
echo "// +build ${GOARCH},${GOOS}"
 | 
			
		||||
echo
 | 
			
		||||
| 
						 | 
				
			
			@ -414,21 +567,26 @@ echo ')'
 | 
			
		|||
 | 
			
		||||
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
 | 
			
		||||
 | 
			
		||||
int errors[] = {
 | 
			
		||||
struct tuple {
 | 
			
		||||
	int num;
 | 
			
		||||
	const char *name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tuple errors[] = {
 | 
			
		||||
"
 | 
			
		||||
	for i in $errors
 | 
			
		||||
	do
 | 
			
		||||
		echo -E '	'$i,
 | 
			
		||||
		echo -E '	{'$i', "'$i'" },'
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	echo -E "
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int signals[] = {
 | 
			
		||||
struct tuple signals[] = {
 | 
			
		||||
"
 | 
			
		||||
	for i in $signals
 | 
			
		||||
	do
 | 
			
		||||
		echo -E '	'$i,
 | 
			
		||||
		echo -E '	{'$i', "'$i'" },'
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# Use -E because on some systems bash builtin interprets \n itself.
 | 
			
		||||
| 
						 | 
				
			
			@ -436,38 +594,46 @@ int signals[] = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
intcmp(const void *a, const void *b)
 | 
			
		||||
tuplecmp(const void *a, const void *b)
 | 
			
		||||
{
 | 
			
		||||
	return *(int*)a - *(int*)b;
 | 
			
		||||
	return ((struct tuple *)a)->num - ((struct tuple *)b)->num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(void)
 | 
			
		||||
{
 | 
			
		||||
	int i, j, e;
 | 
			
		||||
	int i, e;
 | 
			
		||||
	char buf[1024], *p;
 | 
			
		||||
 | 
			
		||||
	printf("\n\n// Error table\n");
 | 
			
		||||
	printf("var errors = [...]string {\n");
 | 
			
		||||
	qsort(errors, nelem(errors), sizeof errors[0], intcmp);
 | 
			
		||||
	printf("var errorList = [...]struct {\n");
 | 
			
		||||
	printf("\tnum  syscall.Errno\n");
 | 
			
		||||
	printf("\tname string\n");
 | 
			
		||||
	printf("\tdesc string\n");
 | 
			
		||||
	printf("} {\n");
 | 
			
		||||
	qsort(errors, nelem(errors), sizeof errors[0], tuplecmp);
 | 
			
		||||
	for(i=0; i<nelem(errors); i++) {
 | 
			
		||||
		e = errors[i];
 | 
			
		||||
		if(i > 0 && errors[i-1] == e)
 | 
			
		||||
		e = errors[i].num;
 | 
			
		||||
		if(i > 0 && errors[i-1].num == e)
 | 
			
		||||
			continue;
 | 
			
		||||
		strcpy(buf, strerror(e));
 | 
			
		||||
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
 | 
			
		||||
		if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
 | 
			
		||||
			buf[0] += a - A;
 | 
			
		||||
		printf("\t%d: \"%s\",\n", e, buf);
 | 
			
		||||
		printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf);
 | 
			
		||||
	}
 | 
			
		||||
	printf("}\n\n");
 | 
			
		||||
 | 
			
		||||
	printf("\n\n// Signal table\n");
 | 
			
		||||
	printf("var signals = [...]string {\n");
 | 
			
		||||
	qsort(signals, nelem(signals), sizeof signals[0], intcmp);
 | 
			
		||||
	printf("var signalList = [...]struct {\n");
 | 
			
		||||
	printf("\tnum  syscall.Signal\n");
 | 
			
		||||
	printf("\tname string\n");
 | 
			
		||||
	printf("\tdesc string\n");
 | 
			
		||||
	printf("} {\n");
 | 
			
		||||
	qsort(signals, nelem(signals), sizeof signals[0], tuplecmp);
 | 
			
		||||
	for(i=0; i<nelem(signals); i++) {
 | 
			
		||||
		e = signals[i];
 | 
			
		||||
		if(i > 0 && signals[i-1] == e)
 | 
			
		||||
		e = signals[i].num;
 | 
			
		||||
		if(i > 0 && signals[i-1].num == e)
 | 
			
		||||
			continue;
 | 
			
		||||
		strcpy(buf, strsignal(e));
 | 
			
		||||
		// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
 | 
			
		||||
| 
						 | 
				
			
			@ -477,7 +643,7 @@ main(void)
 | 
			
		|||
		p = strrchr(buf, ":"[0]);
 | 
			
		||||
		if(p)
 | 
			
		||||
			*p = '\0';
 | 
			
		||||
		printf("\t%d: \"%s\",\n", e, buf);
 | 
			
		||||
		printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf);
 | 
			
		||||
	}
 | 
			
		||||
	printf("}\n\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,62 +0,0 @@
 | 
			
		|||
// Copyright 2016 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 ignore
 | 
			
		||||
 | 
			
		||||
// mkpost processes the output of cgo -godefs to
 | 
			
		||||
// modify the generated types. It is used to clean up
 | 
			
		||||
// the sys API in an architecture specific manner.
 | 
			
		||||
//
 | 
			
		||||
// mkpost is run after cgo -godefs by mkall.sh.
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"go/format"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"regexp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	b, err := ioutil.ReadAll(os.Stdin)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b)
 | 
			
		||||
 | 
			
		||||
	goarch := os.Getenv("GOARCH")
 | 
			
		||||
	goos := os.Getenv("GOOS")
 | 
			
		||||
	if goarch == "s390x" && goos == "linux" {
 | 
			
		||||
		// Export the types of PtraceRegs fields.
 | 
			
		||||
		re := regexp.MustCompile("ptrace(Psw|Fpregs|Per)")
 | 
			
		||||
		s = re.ReplaceAllString(s, "Ptrace$1")
 | 
			
		||||
 | 
			
		||||
		// Replace padding fields inserted by cgo with blank identifiers.
 | 
			
		||||
		re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*")
 | 
			
		||||
		s = re.ReplaceAllString(s, "_")
 | 
			
		||||
 | 
			
		||||
		// Replace other unwanted fields with blank identifiers.
 | 
			
		||||
		re = regexp.MustCompile("X_[A-Za-z0-9_]*")
 | 
			
		||||
		s = re.ReplaceAllString(s, "_")
 | 
			
		||||
 | 
			
		||||
		// Replace the control_regs union with a blank identifier for now.
 | 
			
		||||
		re = regexp.MustCompile("(Control_regs)\\s+\\[0\\]uint64")
 | 
			
		||||
		s = re.ReplaceAllString(s, "_ [0]uint64")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// gofmt
 | 
			
		||||
	b, err = format.Source([]byte(s))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Append this command to the header to show where the new file
 | 
			
		||||
	// came from.
 | 
			
		||||
	re := regexp.MustCompile("(cgo -godefs [a-zA-Z0-9_]+\\.go.*)")
 | 
			
		||||
	b = re.ReplaceAll(b, []byte("$1 | go run mkpost.go"))
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("%s", b)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +69,16 @@ if($ARGV[0] =~ /^-/) {
 | 
			
		|||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check that we are using the new build system if we should
 | 
			
		||||
if($ENV{'GOOS'} eq "linux" && $ENV{'GOARCH'} ne "sparc64") {
 | 
			
		||||
	if($ENV{'GOLANG_SYS_BUILD'} ne "docker") {
 | 
			
		||||
		print STDERR "In the new build system, mksyscall should not be called directly.\n";
 | 
			
		||||
		print STDERR "See README.md\n";
 | 
			
		||||
		exit 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub parseparamlist($) {
 | 
			
		||||
	my ($list) = @_;
 | 
			
		||||
	$list =~ s/^\s*//;
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +210,15 @@ while(<>) {
 | 
			
		|||
	# Determine which form to use; pad args with zeros.
 | 
			
		||||
	my $asm = "Syscall";
 | 
			
		||||
	if ($nonblock) {
 | 
			
		||||
		$asm = "RawSyscall";
 | 
			
		||||
		if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
 | 
			
		||||
			$asm = "RawSyscallNoError";
 | 
			
		||||
		} else {
 | 
			
		||||
			$asm = "RawSyscall";
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
 | 
			
		||||
			$asm = "SyscallNoError";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if(@args <= 3) {
 | 
			
		||||
		while(@args < 3) {
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +292,12 @@ while(<>) {
 | 
			
		|||
	if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
 | 
			
		||||
		$text .= "\t$call\n";
 | 
			
		||||
	} else {
 | 
			
		||||
		$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
 | 
			
		||||
		if ($errvar eq "" && $ENV{'GOOS'} eq "linux") {
 | 
			
		||||
			# raw syscall without error on Linux, see golang.org/issue/22924
 | 
			
		||||
			$text .= "\t$ret[0], $ret[1] := $call\n";
 | 
			
		||||
		} else {
 | 
			
		||||
			$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	$text .= $body;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +323,7 @@ if($errors) {
 | 
			
		|||
 | 
			
		||||
print <<EOF;
 | 
			
		||||
// $cmdline
 | 
			
		||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 | 
			
		||||
// Code generated by the command above; see README.md. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
// +build $tags
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,384 @@
 | 
			
		|||
#!/usr/bin/env perl
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
# This program reads a file containing function prototypes
 | 
			
		||||
# (like syscall_aix.go) and generates system call bodies.
 | 
			
		||||
# The prototypes are marked by lines beginning with "//sys"
 | 
			
		||||
# and read like func declarations if //sys is replaced by func, but:
 | 
			
		||||
#	* The parameter lists must give a name for each argument.
 | 
			
		||||
#	  This includes return parameters.
 | 
			
		||||
#	* The parameter lists must give a type for each argument:
 | 
			
		||||
#	  the (x, y, z int) shorthand is not allowed.
 | 
			
		||||
#	* If the return parameter is an error number, it must be named err.
 | 
			
		||||
#	* If go func name needs to be different than its libc name,
 | 
			
		||||
#	* or the function is not in libc, name could be specified
 | 
			
		||||
#	* at the end, after "=" sign, like
 | 
			
		||||
#	  //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
my $cmdline = "mksyscall_aix_ppc.pl " . join(' ', @ARGV);
 | 
			
		||||
my $errors = 0;
 | 
			
		||||
my $_32bit = "";
 | 
			
		||||
my $tags = "";  # build tags
 | 
			
		||||
my $aix = 0;
 | 
			
		||||
my $solaris = 0;
 | 
			
		||||
 | 
			
		||||
binmode STDOUT;
 | 
			
		||||
 | 
			
		||||
if($ARGV[0] eq "-b32") {
 | 
			
		||||
	$_32bit = "big-endian";
 | 
			
		||||
	shift;
 | 
			
		||||
} elsif($ARGV[0] eq "-l32") {
 | 
			
		||||
	$_32bit = "little-endian";
 | 
			
		||||
	shift;
 | 
			
		||||
}
 | 
			
		||||
if($ARGV[0] eq "-aix") {
 | 
			
		||||
	$aix = 1;
 | 
			
		||||
	shift;
 | 
			
		||||
}
 | 
			
		||||
if($ARGV[0] eq "-tags") {
 | 
			
		||||
	shift;
 | 
			
		||||
	$tags = $ARGV[0];
 | 
			
		||||
	shift;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if($ARGV[0] =~ /^-/) {
 | 
			
		||||
	print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
 | 
			
		||||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub parseparamlist($) {
 | 
			
		||||
	my ($list) = @_;
 | 
			
		||||
	$list =~ s/^\s*//;
 | 
			
		||||
	$list =~ s/\s*$//;
 | 
			
		||||
	if($list eq "") {
 | 
			
		||||
		return ();
 | 
			
		||||
	}
 | 
			
		||||
	return split(/\s*,\s*/, $list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub parseparam($) {
 | 
			
		||||
	my ($p) = @_;
 | 
			
		||||
	if($p !~ /^(\S*) (\S*)$/) {
 | 
			
		||||
		print STDERR "$ARGV:$.: malformed parameter: $p\n";
 | 
			
		||||
		$errors = 1;
 | 
			
		||||
		return ("xx", "int");
 | 
			
		||||
	}
 | 
			
		||||
	return ($1, $2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
my $package = "";
 | 
			
		||||
my $text = "";
 | 
			
		||||
my $c_extern = "/*\n#include <stdint.h>\n#include <stddef.h>\n";
 | 
			
		||||
my @vars = ();
 | 
			
		||||
while(<>) {
 | 
			
		||||
	chomp;
 | 
			
		||||
	s/\s+/ /g;
 | 
			
		||||
	s/^\s+//;
 | 
			
		||||
	s/\s+$//;
 | 
			
		||||
	$package = $1 if !$package && /^package (\S+)$/;
 | 
			
		||||
	my $nonblock = /^\/\/sysnb /;
 | 
			
		||||
	next if !/^\/\/sys / && !$nonblock;
 | 
			
		||||
 | 
			
		||||
	# Line must be of the form
 | 
			
		||||
	# func Open(path string, mode int, perm int) (fd int, err error)
 | 
			
		||||
	# Split into name, in params, out params.
 | 
			
		||||
	if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
 | 
			
		||||
		print STDERR "$ARGV:$.: malformed //sys declaration\n";
 | 
			
		||||
		$errors = 1;
 | 
			
		||||
		next;
 | 
			
		||||
	}
 | 
			
		||||
	my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
 | 
			
		||||
 | 
			
		||||
	# Split argument lists on comma.
 | 
			
		||||
	my @in = parseparamlist($in);
 | 
			
		||||
	my @out = parseparamlist($out);
 | 
			
		||||
 | 
			
		||||
	$in = join(', ', @in);
 | 
			
		||||
	$out = join(', ', @out);
 | 
			
		||||
 | 
			
		||||
	# Try in vain to keep people from editing this file.
 | 
			
		||||
	# The theory is that they jump into the middle of the file
 | 
			
		||||
	# without reading the header.
 | 
			
		||||
	$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
 | 
			
		||||
 | 
			
		||||
	# Check if value return, err return available
 | 
			
		||||
	my $errvar = "";
 | 
			
		||||
	my $retvar = "";
 | 
			
		||||
	my $rettype = "";
 | 
			
		||||
	foreach my $p (@out) {
 | 
			
		||||
		my ($name, $type) = parseparam($p);
 | 
			
		||||
		if($type eq "error") {
 | 
			
		||||
			$errvar = $name;
 | 
			
		||||
		} else {
 | 
			
		||||
			$retvar = $name;
 | 
			
		||||
			$rettype = $type;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# System call name.
 | 
			
		||||
	#if($func ne "fcntl") {
 | 
			
		||||
 | 
			
		||||
	if($sysname eq "") {
 | 
			
		||||
		$sysname = "$func";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	$sysname =~ s/([a-z])([A-Z])/${1}_$2/g;
 | 
			
		||||
	$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
 | 
			
		||||
 | 
			
		||||
	my $C_rettype = "";
 | 
			
		||||
	if($rettype eq "unsafe.Pointer") {
 | 
			
		||||
		$C_rettype = "uintptr_t";
 | 
			
		||||
	} elsif($rettype eq "uintptr") {
 | 
			
		||||
		$C_rettype = "uintptr_t";
 | 
			
		||||
	} elsif($rettype =~ /^_/) {
 | 
			
		||||
		$C_rettype = "uintptr_t";
 | 
			
		||||
	} elsif($rettype eq "int") {
 | 
			
		||||
		$C_rettype = "int";
 | 
			
		||||
	} elsif($rettype eq "int32") {
 | 
			
		||||
		$C_rettype = "int";
 | 
			
		||||
	} elsif($rettype eq "int64") {
 | 
			
		||||
		$C_rettype = "long long";
 | 
			
		||||
	} elsif($rettype eq "uint32") {
 | 
			
		||||
		$C_rettype = "unsigned int";
 | 
			
		||||
	} elsif($rettype eq "uint64") {
 | 
			
		||||
		$C_rettype = "unsigned long long";
 | 
			
		||||
	} else {
 | 
			
		||||
		$C_rettype = "int";
 | 
			
		||||
	}
 | 
			
		||||
	if($sysname eq "exit") {
 | 
			
		||||
		$C_rettype = "void";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# Change types to c
 | 
			
		||||
	my @c_in = ();
 | 
			
		||||
	foreach my $p (@in) {
 | 
			
		||||
		my ($name, $type) = parseparam($p);
 | 
			
		||||
		if($type =~ /^\*/) {
 | 
			
		||||
			push @c_in, "uintptr_t";
 | 
			
		||||
			} elsif($type eq "string") {
 | 
			
		||||
			push @c_in, "uintptr_t";
 | 
			
		||||
		} elsif($type =~ /^\[\](.*)/) {
 | 
			
		||||
			push @c_in, "uintptr_t", "size_t";
 | 
			
		||||
		} elsif($type eq "unsafe.Pointer") {
 | 
			
		||||
			push @c_in, "uintptr_t";
 | 
			
		||||
		} elsif($type eq "uintptr") {
 | 
			
		||||
			push @c_in, "uintptr_t";
 | 
			
		||||
		} elsif($type =~ /^_/) {
 | 
			
		||||
			push @c_in, "uintptr_t";
 | 
			
		||||
		} elsif($type eq "int") {
 | 
			
		||||
			push @c_in, "int";
 | 
			
		||||
		} elsif($type eq "int32") {
 | 
			
		||||
			push @c_in, "int";
 | 
			
		||||
		} elsif($type eq "int64") {
 | 
			
		||||
			push @c_in, "long long";
 | 
			
		||||
		} elsif($type eq "uint32") {
 | 
			
		||||
			push @c_in, "unsigned int";
 | 
			
		||||
		} elsif($type eq "uint64") {
 | 
			
		||||
			push @c_in, "unsigned long long";
 | 
			
		||||
		} else {
 | 
			
		||||
			push @c_in, "int";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ($func ne "fcntl" && $func ne "FcntlInt" && $func ne "readlen" && $func ne "writelen") {
 | 
			
		||||
		# Imports of system calls from libc
 | 
			
		||||
		$c_extern .= "$C_rettype $sysname";
 | 
			
		||||
		my $c_in = join(', ', @c_in);
 | 
			
		||||
		$c_extern .= "($c_in);\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# So file name.
 | 
			
		||||
	if($aix) {
 | 
			
		||||
		if($modname eq "") {
 | 
			
		||||
			$modname = "libc.a/shr_64.o";
 | 
			
		||||
		} else {
 | 
			
		||||
			print STDERR "$func: only syscall using libc are available\n";
 | 
			
		||||
			$errors = 1;
 | 
			
		||||
			next;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	my $strconvfunc = "C.CString";
 | 
			
		||||
	my $strconvtype = "*byte";
 | 
			
		||||
 | 
			
		||||
	# Go function header.
 | 
			
		||||
	if($out ne "") {
 | 
			
		||||
		$out = " ($out)";
 | 
			
		||||
	}
 | 
			
		||||
	if($text ne "") {
 | 
			
		||||
		$text .= "\n"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ;
 | 
			
		||||
 | 
			
		||||
	# Prepare arguments to call.
 | 
			
		||||
	my @args = ();
 | 
			
		||||
	my $n = 0;
 | 
			
		||||
	my $arg_n = 0;
 | 
			
		||||
	foreach my $p (@in) {
 | 
			
		||||
		my ($name, $type) = parseparam($p);
 | 
			
		||||
		if($type =~ /^\*/) {
 | 
			
		||||
			push @args, "C.uintptr_t(uintptr(unsafe.Pointer($name)))";
 | 
			
		||||
		} elsif($type eq "string" && $errvar ne "") {
 | 
			
		||||
			$text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n";
 | 
			
		||||
			push @args, "C.uintptr_t(_p$n)";
 | 
			
		||||
			$n++;
 | 
			
		||||
		} elsif($type eq "string") {
 | 
			
		||||
			print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
 | 
			
		||||
			$text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n";
 | 
			
		||||
			push @args, "C.uintptr_t(_p$n)";
 | 
			
		||||
			$n++;
 | 
			
		||||
		} elsif($type =~ /^\[\](.*)/) {
 | 
			
		||||
			# Convert slice into pointer, length.
 | 
			
		||||
			# Have to be careful not to take address of &a[0] if len == 0:
 | 
			
		||||
			# pass nil in that case.
 | 
			
		||||
			$text .= "\tvar _p$n *$1\n";
 | 
			
		||||
			$text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
 | 
			
		||||
			push @args, "C.uintptr_t(uintptr(unsafe.Pointer(_p$n)))";
 | 
			
		||||
			$n++;
 | 
			
		||||
			$text .= "\tvar _p$n int\n";
 | 
			
		||||
			$text .= "\t_p$n = len($name)\n";
 | 
			
		||||
			push @args, "C.size_t(_p$n)";
 | 
			
		||||
			$n++;
 | 
			
		||||
		} elsif($type eq "int64" && $_32bit ne "") {
 | 
			
		||||
			if($_32bit eq "big-endian") {
 | 
			
		||||
				push @args, "uintptr($name >> 32)", "uintptr($name)";
 | 
			
		||||
			} else {
 | 
			
		||||
				push @args, "uintptr($name)", "uintptr($name >> 32)";
 | 
			
		||||
			}
 | 
			
		||||
			$n++;
 | 
			
		||||
		} elsif($type eq "bool") {
 | 
			
		||||
			$text .= "\tvar _p$n uint32\n";
 | 
			
		||||
			$text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
 | 
			
		||||
			push @args, "_p$n";
 | 
			
		||||
			$n++;
 | 
			
		||||
		} elsif($type =~ /^_/) {
 | 
			
		||||
			push @args, "C.uintptr_t(uintptr($name))";
 | 
			
		||||
		} elsif($type eq "unsafe.Pointer") {
 | 
			
		||||
			push @args, "C.uintptr_t(uintptr($name))";
 | 
			
		||||
		} elsif($type eq "int") {
 | 
			
		||||
			if (($arg_n == 2) && (($func eq "readlen") || ($func eq "writelen"))) {
 | 
			
		||||
				push @args, "C.size_t($name)";
 | 
			
		||||
			} elsif ($arg_n == 0 && $func eq "fcntl") {
 | 
			
		||||
				push @args, "C.uintptr_t($name)";
 | 
			
		||||
			} elsif (($arg_n == 2) && (($func eq "fcntl") || ($func eq "FcntlInt"))) {
 | 
			
		||||
				push @args, "C.uintptr_t($name)";
 | 
			
		||||
			} else {
 | 
			
		||||
				push @args, "C.int($name)";
 | 
			
		||||
			}
 | 
			
		||||
		} elsif($type eq "int32") {
 | 
			
		||||
			push @args, "C.int($name)";
 | 
			
		||||
		} elsif($type eq "int64") {
 | 
			
		||||
			push @args, "C.longlong($name)";
 | 
			
		||||
		} elsif($type eq "uint32") {
 | 
			
		||||
			push @args, "C.uint($name)";
 | 
			
		||||
		} elsif($type eq "uint64") {
 | 
			
		||||
			push @args, "C.ulonglong($name)";
 | 
			
		||||
		} elsif($type eq "uintptr") {
 | 
			
		||||
			push @args, "C.uintptr_t($name)";
 | 
			
		||||
		} else {
 | 
			
		||||
			push @args, "C.int($name)";
 | 
			
		||||
		}
 | 
			
		||||
		$arg_n++;
 | 
			
		||||
	}
 | 
			
		||||
	my $nargs = @args;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	# Determine which form to use; pad args with zeros.
 | 
			
		||||
	if ($nonblock) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	my $args = join(', ', @args);
 | 
			
		||||
	my $call = "";
 | 
			
		||||
	if ($sysname eq "exit") {
 | 
			
		||||
		if ($errvar ne "") {
 | 
			
		||||
			$call .= "er :=";
 | 
			
		||||
		} else {
 | 
			
		||||
			$call .= "";
 | 
			
		||||
		}
 | 
			
		||||
	}  elsif ($errvar ne "") {
 | 
			
		||||
		$call .= "r0,er :=";
 | 
			
		||||
	}  elsif ($retvar ne "") {
 | 
			
		||||
		$call .= "r0,_ :=";
 | 
			
		||||
	}  else {
 | 
			
		||||
		$call .= ""
 | 
			
		||||
	}
 | 
			
		||||
	$call .= "C.$sysname($args)";
 | 
			
		||||
 | 
			
		||||
	# Assign return values.
 | 
			
		||||
	my $body = "";
 | 
			
		||||
	my $failexpr = "";
 | 
			
		||||
 | 
			
		||||
	for(my $i=0; $i<@out; $i++) {
 | 
			
		||||
		my $p = $out[$i];
 | 
			
		||||
		my ($name, $type) = parseparam($p);
 | 
			
		||||
		my $reg = "";
 | 
			
		||||
		if($name eq "err") {
 | 
			
		||||
			$reg = "e1";
 | 
			
		||||
		} else {
 | 
			
		||||
			$reg = "r0";
 | 
			
		||||
		}
 | 
			
		||||
		if($reg ne "e1" ) {
 | 
			
		||||
						$body .= "\t$name = $type($reg)\n";
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# verify return
 | 
			
		||||
	if ($sysname ne "exit" && $errvar ne "") {
 | 
			
		||||
		if ($C_rettype =~ /^uintptr/) {
 | 
			
		||||
			$body .= "\tif \(uintptr\(r0\) ==\^uintptr\(0\) && er != nil\) {\n";
 | 
			
		||||
			$body .= "\t\t$errvar = er\n";
 | 
			
		||||
			$body .= "\t}\n";
 | 
			
		||||
		} else {
 | 
			
		||||
			$body .= "\tif \(r0 ==-1 && er != nil\) {\n";
 | 
			
		||||
			$body .= "\t\t$errvar = er\n";
 | 
			
		||||
			$body .= "\t}\n";
 | 
			
		||||
		}
 | 
			
		||||
	} elsif ($errvar ne "") {
 | 
			
		||||
		$body .= "\tif \(er != nil\) {\n";
 | 
			
		||||
		$body .= "\t\t$errvar = er\n";
 | 
			
		||||
		$body .= "\t}\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	$text .= "\t$call\n";
 | 
			
		||||
	$text .= $body;
 | 
			
		||||
 | 
			
		||||
	$text .= "\treturn\n";
 | 
			
		||||
	$text .= "}\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if($errors) {
 | 
			
		||||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print <<EOF;
 | 
			
		||||
// $cmdline
 | 
			
		||||
// Code generated by the command above; see README.md. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
// +build $tags
 | 
			
		||||
 | 
			
		||||
package $package
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
$c_extern
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
 | 
			
		||||
 | 
			
		||||
chomp($_=<<EOF);
 | 
			
		||||
 | 
			
		||||
$text
 | 
			
		||||
EOF
 | 
			
		||||
print $_;
 | 
			
		||||
exit 0;
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue