forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/davecgh/go-spew/spew/bypass.go

246 lines
4.8 KiB
Go
Raw Normal View History

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