Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / davecgh / go-spew / spew / bypass.go
1 // Copyright (c) 2015-2016 Dave Collins <dave@davec.name>
2 //
3 // Permission to use, copy, modify, and distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 // NOTE: Due to the following build constraints, this file will only be compiled
16 // when the code is not running on Google App Engine, compiled by GopherJS, and
17 // "-tags safe" is not added to the go build command line.  The "disableunsafe"
18 // tag is deprecated and thus should not be used.
19 // Go versions prior to 1.4 are disabled because they use a different layout
20 // for interfaces which make the implementation of unsafeReflectValue more complex.
21 // +build !js,!appengine,!safe,!disableunsafe,go1.4
22
23 package spew
24
25 import (
26         "reflect"
27         "unsafe"
28 )
29
30 const (
31         // UnsafeDisabled is a build-time constant which specifies whether or
32         // not access to the unsafe package is available.
33         UnsafeDisabled = false
34
35         // ptrSize is the size of a pointer on the current arch.
36         ptrSize = unsafe.Sizeof((*byte)(nil))
37 )
38
39 type flag uintptr
40
41 var (
42         // flagRO indicates whether the value field of a reflect.Value
43         // is read-only.
44         flagRO flag
45
46         // flagAddr indicates whether the address of the reflect.Value's
47         // value may be taken.
48         flagAddr flag
49 )
50
51 // flagKindMask holds the bits that make up the kind
52 // part of the flags field. In all the supported versions,
53 // it is in the lower 5 bits.
54 const flagKindMask = flag(0x1f)
55
56 // Different versions of Go have used different
57 // bit layouts for the flags type. This table
58 // records the known combinations.
59 var okFlags = []struct {
60         ro, addr flag
61 }{{
62         // From Go 1.4 to 1.5
63         ro:   1 << 5,
64         addr: 1 << 7,
65 }, {
66         // Up to Go tip.
67         ro:   1<<5 | 1<<6,
68         addr: 1 << 8,
69 }}
70
71 var flagValOffset = func() uintptr {
72         field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
73         if !ok {
74                 panic("reflect.Value has no flag field")
75         }
76         return field.Offset
77 }()
78
79 // flagField returns a pointer to the flag field of a reflect.Value.
80 func flagField(v *reflect.Value) *flag {
81         return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
82 }
83
84 // unsafeReflectValue converts the passed reflect.Value into a one that bypasses
85 // the typical safety restrictions preventing access to unaddressable and
86 // unexported data.  It works by digging the raw pointer to the underlying
87 // value out of the protected value and generating a new unprotected (unsafe)
88 // reflect.Value to it.
89 //
90 // This allows us to check for implementations of the Stringer and error
91 // interfaces to be used for pretty printing ordinarily unaddressable and
92 // inaccessible values such as unexported struct fields.
93 func unsafeReflectValue(v reflect.Value) reflect.Value {
94         if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
95                 return v
96         }
97         flagFieldPtr := flagField(&v)
98         *flagFieldPtr &^= flagRO
99         *flagFieldPtr |= flagAddr
100         return v
101 }
102
103 // Sanity checks against future reflect package changes
104 // to the type or semantics of the Value.flag field.
105 func init() {
106         field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
107         if !ok {
108                 panic("reflect.Value has no flag field")
109         }
110         if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
111                 panic("reflect.Value flag field has changed kind")
112         }
113         type t0 int
114         var t struct {
115                 A t0
116                 // t0 will have flagEmbedRO set.
117                 t0
118                 // a will have flagStickyRO set
119                 a t0
120         }
121         vA := reflect.ValueOf(t).FieldByName("A")
122         va := reflect.ValueOf(t).FieldByName("a")
123         vt0 := reflect.ValueOf(t).FieldByName("t0")
124
125         // Infer flagRO from the difference between the flags
126         // for the (otherwise identical) fields in t.
127         flagPublic := *flagField(&vA)
128         flagWithRO := *flagField(&va) | *flagField(&vt0)
129         flagRO = flagPublic ^ flagWithRO
130
131         // Infer flagAddr from the difference between a value
132         // taken from a pointer and not.
133         vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
134         flagNoPtr := *flagField(&vA)
135         flagPtr := *flagField(&vPtrA)
136         flagAddr = flagNoPtr ^ flagPtr
137
138         // Check that the inferred flags tally with one of the known versions.
139         for _, f := range okFlags {
140                 if flagRO == f.ro && flagAddr == f.addr {
141                         return
142                 }
143         }
144         panic("reflect.Value read-only flag has changed semantics")
145 }