Skip to content

Commit 66066c8

Browse files
authored
Merge pull request #41 from stewart-yu/stewart-utils-pointers
cp pointers util from kubernetes/kubernetes
2 parents 73fcbfe + 53291e9 commit 66066c8

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ an existing package to this repository.
4545

4646
- [Clock](/clock) provides an interface for time-based operations. It allows
4747
mocking time for testing.
48+
49+
- [Pointers](/pointers) provides some functions for pointer-based operations.
4850

4951
[Build Status]: https://travis-ci.org/kubernetes/utils.svg?branch=master
5052
[Go standard libs]: https://golang.org/pkg/#stdlib

pointer/pointer.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pointer
18+
19+
import (
20+
"fmt"
21+
"reflect"
22+
)
23+
24+
// AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when,
25+
// for example, an API struct is handled by plugins which need to distinguish
26+
// "no plugin accepted this spec" from "this spec is empty".
27+
//
28+
// This function is only valid for structs and pointers to structs. Any other
29+
// type will cause a panic. Passing a typed nil pointer will return true.
30+
func AllPtrFieldsNil(obj interface{}) bool {
31+
v := reflect.ValueOf(obj)
32+
if !v.IsValid() {
33+
panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj))
34+
}
35+
if v.Kind() == reflect.Ptr {
36+
if v.IsNil() {
37+
return true
38+
}
39+
v = v.Elem()
40+
}
41+
for i := 0; i < v.NumField(); i++ {
42+
if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() {
43+
return false
44+
}
45+
}
46+
return true
47+
}
48+
49+
// Int32Ptr returns a pointer to an int32
50+
func Int32Ptr(i int32) *int32 {
51+
return &i
52+
}
53+
54+
// Int64Ptr returns a pointer to an int64
55+
func Int64Ptr(i int64) *int64 {
56+
return &i
57+
}
58+
59+
// Int32PtrDerefOr dereference the int32 ptr and returns it i not nil,
60+
// else returns def.
61+
func Int32PtrDerefOr(ptr *int32, def int32) int32 {
62+
if ptr != nil {
63+
return *ptr
64+
}
65+
return def
66+
}
67+
68+
// BoolPtr returns a pointer to a bool
69+
func BoolPtr(b bool) *bool {
70+
return &b
71+
}
72+
73+
// StringPtr returns a pointer to the passed string.
74+
func StringPtr(s string) *string {
75+
return &s
76+
}

pointer/pointer_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pointer
18+
19+
import (
20+
"testing"
21+
)
22+
23+
func TestAllPtrFieldsNil(t *testing.T) {
24+
testCases := []struct {
25+
obj interface{}
26+
expected bool
27+
}{
28+
{struct{}{}, true},
29+
{struct{ Foo int }{12345}, true},
30+
{&struct{ Foo int }{12345}, true},
31+
{struct{ Foo *int }{nil}, true},
32+
{&struct{ Foo *int }{nil}, true},
33+
{struct {
34+
Foo int
35+
Bar *int
36+
}{12345, nil}, true},
37+
{&struct {
38+
Foo int
39+
Bar *int
40+
}{12345, nil}, true},
41+
{struct {
42+
Foo *int
43+
Bar *int
44+
}{nil, nil}, true},
45+
{&struct {
46+
Foo *int
47+
Bar *int
48+
}{nil, nil}, true},
49+
{struct{ Foo *int }{new(int)}, false},
50+
{&struct{ Foo *int }{new(int)}, false},
51+
{struct {
52+
Foo *int
53+
Bar *int
54+
}{nil, new(int)}, false},
55+
{&struct {
56+
Foo *int
57+
Bar *int
58+
}{nil, new(int)}, false},
59+
{(*struct{})(nil), true},
60+
}
61+
for i, tc := range testCases {
62+
if AllPtrFieldsNil(tc.obj) != tc.expected {
63+
t.Errorf("case[%d]: expected %t, got %t", i, tc.expected, !tc.expected)
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)