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 | 152 |
1 files changed, 152 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..8a4a658 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go | |||
@@ -0,0 +1,152 @@ | |||
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 | // +build !js,!appengine,!safe,!disableunsafe | ||
20 | |||
21 | package spew | ||
22 | |||
23 | import ( | ||
24 | "reflect" | ||
25 | "unsafe" | ||
26 | ) | ||
27 | |||
28 | const ( | ||
29 | // UnsafeDisabled is a build-time constant which specifies whether or | ||
30 | // not access to the unsafe package is available. | ||
31 | UnsafeDisabled = false | ||
32 | |||
33 | // ptrSize is the size of a pointer on the current arch. | ||
34 | ptrSize = unsafe.Sizeof((*byte)(nil)) | ||
35 | ) | ||
36 | |||
37 | var ( | ||
38 | // offsetPtr, offsetScalar, and offsetFlag are the offsets for the | ||
39 | // internal reflect.Value fields. These values are valid before golang | ||
40 | // commit ecccf07e7f9d which changed the format. The are also valid | ||
41 | // after commit 82f48826c6c7 which changed the format again to mirror | ||
42 | // the original format. Code in the init function updates these offsets | ||
43 | // as necessary. | ||
44 | offsetPtr = uintptr(ptrSize) | ||
45 | offsetScalar = uintptr(0) | ||
46 | offsetFlag = uintptr(ptrSize * 2) | ||
47 | |||
48 | // flagKindWidth and flagKindShift indicate various bits that the | ||
49 | // reflect package uses internally to track kind information. | ||
50 | // | ||
51 | // flagRO indicates whether or not the value field of a reflect.Value is | ||
52 | // read-only. | ||
53 | // | ||
54 | // flagIndir indicates whether the value field of a reflect.Value is | ||
55 | // the actual data or a pointer to the data. | ||
56 | // | ||
57 | // These values are valid before golang commit 90a7c3c86944 which | ||
58 | // changed their positions. Code in the init function updates these | ||
59 | // flags as necessary. | ||
60 | flagKindWidth = uintptr(5) | ||
61 | flagKindShift = uintptr(flagKindWidth - 1) | ||
62 | flagRO = uintptr(1 << 0) | ||
63 | flagIndir = uintptr(1 << 1) | ||
64 | ) | ||
65 | |||
66 | func init() { | ||
67 | // Older versions of reflect.Value stored small integers directly in the | ||
68 | // ptr field (which is named val in the older versions). Versions | ||
69 | // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named | ||
70 | // scalar for this purpose which unfortunately came before the flag | ||
71 | // field, so the offset of the flag field is different for those | ||
72 | // versions. | ||
73 | // | ||
74 | // This code constructs a new reflect.Value from a known small integer | ||
75 | // and checks if the size of the reflect.Value struct indicates it has | ||
76 | // the scalar field. When it does, the offsets are updated accordingly. | ||
77 | vv := reflect.ValueOf(0xf00) | ||
78 | if unsafe.Sizeof(vv) == (ptrSize * 4) { | ||
79 | offsetScalar = ptrSize * 2 | ||
80 | offsetFlag = ptrSize * 3 | ||
81 | } | ||
82 | |||
83 | // Commit 90a7c3c86944 changed the flag positions such that the low | ||
84 | // order bits are the kind. This code extracts the kind from the flags | ||
85 | // field and ensures it's the correct type. When it's not, the flag | ||
86 | // order has been changed to the newer format, so the flags are updated | ||
87 | // accordingly. | ||
88 | upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) | ||
89 | upfv := *(*uintptr)(upf) | ||
90 | flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift) | ||
91 | if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) { | ||
92 | flagKindShift = 0 | ||
93 | flagRO = 1 << 5 | ||
94 | flagIndir = 1 << 6 | ||
95 | |||
96 | // Commit adf9b30e5594 modified the flags to separate the | ||
97 | // flagRO flag into two bits which specifies whether or not the | ||
98 | // field is embedded. This causes flagIndir to move over a bit | ||
99 | // and means that flagRO is the combination of either of the | ||
100 | // original flagRO bit and the new bit. | ||
101 | // | ||
102 | // This code detects the change by extracting what used to be | ||
103 | // the indirect bit to ensure it's set. When it's not, the flag | ||
104 | // order has been changed to the newer format, so the flags are | ||
105 | // updated accordingly. | ||
106 | if upfv&flagIndir == 0 { | ||
107 | flagRO = 3 << 5 | ||
108 | flagIndir = 1 << 7 | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | // unsafeReflectValue converts the passed reflect.Value into a one that bypasses | ||
114 | // the typical safety restrictions preventing access to unaddressable and | ||
115 | // unexported data. It works by digging the raw pointer to the underlying | ||
116 | // value out of the protected value and generating a new unprotected (unsafe) | ||
117 | // reflect.Value to it. | ||
118 | // | ||
119 | // This allows us to check for implementations of the Stringer and error | ||
120 | // interfaces to be used for pretty printing ordinarily unaddressable and | ||
121 | // inaccessible values such as unexported struct fields. | ||
122 | func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { | ||
123 | indirects := 1 | ||
124 | vt := v.Type() | ||
125 | upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) | ||
126 | rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) | ||
127 | if rvf&flagIndir != 0 { | ||
128 | vt = reflect.PtrTo(v.Type()) | ||
129 | indirects++ | ||
130 | } else if offsetScalar != 0 { | ||
131 | // The value is in the scalar field when it's not one of the | ||
132 | // reference types. | ||
133 | switch vt.Kind() { | ||
134 | case reflect.Uintptr: | ||
135 | case reflect.Chan: | ||
136 | case reflect.Func: | ||
137 | case reflect.Map: | ||
138 | case reflect.Ptr: | ||
139 | case reflect.UnsafePointer: | ||
140 | default: | ||
141 | upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + | ||
142 | offsetScalar) | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pv := reflect.NewAt(vt, upv) | ||
147 | rv = pv | ||
148 | for i := 0; i < indirects; i++ { | ||
149 | rv = rv.Elem() | ||
150 | } | ||
151 | return rv | ||
152 | } | ||