diff options
Diffstat (limited to 'vendor/github.com/davecgh/go-spew/spew/bypass.go')
| -rw-r--r-- | vendor/github.com/davecgh/go-spew/spew/bypass.go | 145 | 
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go new file mode 100644 index 0000000..7929947 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -0,0 +1,145 @@ +// Copyright (c) 2015-2016 Dave Collins <[email protected]> +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line.  The "disableunsafe" +// tag is deprecated and thus should not be used. +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 + +package spew + +import ( +	"reflect" +	"unsafe" +) + +const ( +	// UnsafeDisabled is a build-time constant which specifies whether or +	// not access to the unsafe package is available. +	UnsafeDisabled = false + +	// ptrSize is the size of a pointer on the current arch. +	ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +type flag uintptr + +var ( +	// flagRO indicates whether the value field of a reflect.Value +	// is read-only. +	flagRO flag + +	// flagAddr indicates whether the address of the reflect.Value's +	// value may be taken. +	flagAddr flag +) + +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) + +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { +	ro, addr flag +}{{ +	// From Go 1.4 to 1.5 +	ro:   1 << 5, +	addr: 1 << 7, +}, { +	// Up to Go tip. +	ro:   1<<5 | 1<<6, +	addr: 1 << 8, +}} + +var flagValOffset = func() uintptr { +	field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") +	if !ok { +		panic("reflect.Value has no flag field") +	} +	return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { +	return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data.  It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) reflect.Value { +	if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { +		return v +	} +	flagFieldPtr := flagField(&v) +	*flagFieldPtr &^= flagRO +	*flagFieldPtr |= flagAddr +	return v +} + +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { +	field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") +	if !ok { +		panic("reflect.Value has no flag field") +	} +	if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { +		panic("reflect.Value flag field has changed kind") +	} +	type t0 int +	var t struct { +		A t0 +		// t0 will have flagEmbedRO set. +		t0 +		// a will have flagStickyRO set +		a t0 +	} +	vA := reflect.ValueOf(t).FieldByName("A") +	va := reflect.ValueOf(t).FieldByName("a") +	vt0 := reflect.ValueOf(t).FieldByName("t0") + +	// Infer flagRO from the difference between the flags +	// for the (otherwise identical) fields in t. +	flagPublic := *flagField(&vA) +	flagWithRO := *flagField(&va) | *flagField(&vt0) +	flagRO = flagPublic ^ flagWithRO + +	// Infer flagAddr from the difference between a value +	// taken from a pointer and not. +	vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") +	flagNoPtr := *flagField(&vA) +	flagPtr := *flagField(&vPtrA) +	flagAddr = flagNoPtr ^ flagPtr + +	// Check that the inferred flags tally with one of the known versions. +	for _, f := range okFlags { +		if flagRO == f.ro && flagAddr == f.addr { +			return +		} +	} +	panic("reflect.Value read-only flag has changed semantics") +}  | 
