This repository has been archived by the owner on Jul 30, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ptrs.go
139 lines (121 loc) · 3.65 KB
/
ptrs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) 2018, Randall C. O'Reilly. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package kit
// github.com/rcoreilly/goki/ki/kit
import (
"reflect"
)
// These are a set of consistently-named functions for navigating pointer
// types and values within the reflect system
/////////////////////////////////////////////////
// reflect.Type versions
// NonPtrType returns the non-pointer underlying type
func NonPtrType(typ reflect.Type) reflect.Type {
if typ == nil {
return typ
}
for typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
return typ
}
// PtrType returns the pointer type for given type, if given type is not already a Ptr
func PtrType(typ reflect.Type) reflect.Type {
if typ == nil {
return typ
}
if typ.Kind() != reflect.Ptr {
typ = reflect.PtrTo(typ)
}
return typ
}
// OnePtrType returns a type that is exactly one pointer away from a non-pointer type
func OnePtrType(typ reflect.Type) reflect.Type {
if typ == nil {
return typ
}
if typ.Kind() != reflect.Ptr {
typ = reflect.PtrTo(typ)
} else {
for typ.Elem().Kind() == reflect.Ptr {
typ = typ.Elem()
}
}
return typ
}
/////////////////////////////////////////////////
// reflect.Value versions
// NonPtrValue returns the non-pointer underlying value
func NonPtrValue(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
return v
}
// PtrValue returns the pointer version (Addr()) of the underlying value if
// the value is not already a Ptr
func PtrValue(v reflect.Value) reflect.Value {
if v.Kind() != reflect.Ptr {
v = v.Addr()
}
return v
}
// OnePtrValue returns a value that is exactly one pointer away from a non-pointer type
func OnePtrValue(v reflect.Value) reflect.Value {
if v.Kind() != reflect.Ptr {
v = v.Addr()
} else {
for v.Elem().Kind() == reflect.Ptr {
v = v.Elem()
}
}
return v
}
// MakePtrValue makes a new pointer to the given value, adding an extra level
// of indirection, and then removing that indirection, resulting in something
// that is now addressable / assignable -- this is necessary for enums..
func MakePtrValue(v reflect.Value) reflect.Value {
np := reflect.New(PtrType(v.Type()))
pi := np.Interface()
pi = v.Interface() // assign pointer using interface assignment instead of set..
p := reflect.ValueOf(pi) // has a double pointer, remove that last one
return p.Elem()
}
// UnhideIfaceValue returns a reflect.Value for any of the Make* functions
// that is actually assignable -- even though these functions return a pointer
// to the new object, it is somehow hidden behind an interface{} and this
// magic foo, posted by someone somewhere that I cannot now find again,
// un-hides it..
func UnhideIfaceValue(v reflect.Value) reflect.Value {
vn := reflect.ValueOf(v.Interface())
typ := vn.Type()
ptr := reflect.New(typ)
ptr.Elem().Set(vn)
return ptr
}
/////////////////////////////////////////////////
// interface{} versions
// NonPtrInterface returns the non-pointer value of an interface
func NonPtrInterface(el interface{}) interface{} {
v := reflect.ValueOf(el)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
return v.Interface()
}
// PtrInterface returns the pointer value of an interface, if it is possible to get one through Addr()
func PtrInterface(el interface{}) interface{} {
v := reflect.ValueOf(el)
if v.Kind() == reflect.Ptr {
return el
}
if v.CanAddr() {
return v.Addr().Interface()
}
return el
}
// OnePtrInterface returns the pointer value of an interface, if it is possible to get one through Addr()
func OnePtrInterface(el interface{}) interface{} {
return OnePtrValue(reflect.ValueOf(el)).Interface()
}