mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-25 02:45:12 +00:00
Update Structured Merge Diff to V3
This commit is contained in:
committed by
Jennifer Buckley
parent
c9b4cf3d25
commit
b33fbc84d9
42
vendor/sigs.k8s.io/structured-merge-diff/v3/value/BUILD
generated
vendored
Normal file
42
vendor/sigs.k8s.io/structured-merge-diff/v3/value/BUILD
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"fields.go",
|
||||
"jsontagutil.go",
|
||||
"list.go",
|
||||
"listreflect.go",
|
||||
"listunstructured.go",
|
||||
"map.go",
|
||||
"mapreflect.go",
|
||||
"mapunstructured.go",
|
||||
"scalar.go",
|
||||
"structreflect.go",
|
||||
"value.go",
|
||||
"valuereflect.go",
|
||||
"valueunstructured.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/structured-merge-diff/v3/value",
|
||||
importpath = "sigs.k8s.io/structured-merge-diff/v3/value",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/json-iterator/go:go_default_library",
|
||||
"//vendor/gopkg.in/yaml.v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
21
vendor/sigs.k8s.io/structured-merge-diff/v3/value/doc.go
generated
vendored
Normal file
21
vendor/sigs.k8s.io/structured-merge-diff/v3/value/doc.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package value defines types for an in-memory representation of yaml or json
|
||||
// objects, organized for convenient comparison with a schema (as defined by
|
||||
// the sibling schema package). Functions for reading and writing the objects
|
||||
// are also provided.
|
||||
package value
|
||||
97
vendor/sigs.k8s.io/structured-merge-diff/v3/value/fields.go
generated
vendored
Normal file
97
vendor/sigs.k8s.io/structured-merge-diff/v3/value/fields.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Field is an individual key-value pair.
|
||||
type Field struct {
|
||||
Name string
|
||||
Value Value
|
||||
}
|
||||
|
||||
// FieldList is a list of key-value pairs. Each field is expectUpdated to
|
||||
// have a different name.
|
||||
type FieldList []Field
|
||||
|
||||
// Sort sorts the field list by Name.
|
||||
func (f FieldList) Sort() {
|
||||
if len(f) < 2 {
|
||||
return
|
||||
}
|
||||
if len(f) == 2 {
|
||||
if f[1].Name < f[0].Name {
|
||||
f[0], f[1] = f[1], f[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
sort.SliceStable(f, func(i, j int) bool {
|
||||
return f[i].Name < f[j].Name
|
||||
})
|
||||
}
|
||||
|
||||
// Less compares two lists lexically.
|
||||
func (f FieldList) Less(rhs FieldList) bool {
|
||||
return f.Compare(rhs) == -1
|
||||
}
|
||||
|
||||
// Compare compares two lists lexically. The result will be 0 if f==rhs, -1
|
||||
// if f < rhs, and +1 if f > rhs.
|
||||
func (f FieldList) Compare(rhs FieldList) int {
|
||||
i := 0
|
||||
for {
|
||||
if i >= len(f) && i >= len(rhs) {
|
||||
// Maps are the same length and all items are equal.
|
||||
return 0
|
||||
}
|
||||
if i >= len(f) {
|
||||
// F is shorter.
|
||||
return -1
|
||||
}
|
||||
if i >= len(rhs) {
|
||||
// RHS is shorter.
|
||||
return 1
|
||||
}
|
||||
if c := strings.Compare(f[i].Name, rhs[i].Name); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := Compare(f[i].Value, rhs[i].Value); c != 0 {
|
||||
return c
|
||||
}
|
||||
// The items are equal; continue.
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// Equals returns true if the two fieldslist are equals, false otherwise.
|
||||
func (f FieldList) Equals(rhs FieldList) bool {
|
||||
if len(f) != len(rhs) {
|
||||
return false
|
||||
}
|
||||
for i := range f {
|
||||
if f[i].Name != rhs[i].Name {
|
||||
return false
|
||||
}
|
||||
if !Equals(f[i].Value, rhs[i].Value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
91
vendor/sigs.k8s.io/structured-merge-diff/v3/value/jsontagutil.go
generated
vendored
Normal file
91
vendor/sigs.k8s.io/structured-merge-diff/v3/value/jsontagutil.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO: This implements the same functionality as https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L236
|
||||
// but is based on the highly efficient approach from https://golang.org/src/encoding/json/encode.go
|
||||
|
||||
func lookupJsonTags(f reflect.StructField) (name string, omit bool, inline bool, omitempty bool) {
|
||||
tag := f.Tag.Get("json")
|
||||
if tag == "-" {
|
||||
return "", true, false, false
|
||||
}
|
||||
name, opts := parseTag(tag)
|
||||
if name == "" {
|
||||
name = f.Name
|
||||
}
|
||||
return name, false, opts.Contains("inline"), opts.Contains("omitempty")
|
||||
}
|
||||
|
||||
func isZero(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Chan, reflect.Func:
|
||||
panic(fmt.Sprintf("unsupported type: %v", v.Type()))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
||||
80
vendor/sigs.k8s.io/structured-merge-diff/v3/value/list.go
generated
vendored
Normal file
80
vendor/sigs.k8s.io/structured-merge-diff/v3/value/list.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
// List represents a list object.
|
||||
type List interface {
|
||||
// Length returns how many items can be found in the map.
|
||||
Length() int
|
||||
// At returns the item at the given position in the map. It will
|
||||
// panic if the index is out of range.
|
||||
At(int) Value
|
||||
}
|
||||
|
||||
// ListEquals compares two lists lexically.
|
||||
func ListEquals(lhs, rhs List) bool {
|
||||
if lhs.Length() != rhs.Length() {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < lhs.Length(); i++ {
|
||||
lv := lhs.At(i)
|
||||
rv := rhs.At(i)
|
||||
if !Equals(lv, rv) {
|
||||
lv.Recycle()
|
||||
rv.Recycle()
|
||||
return false
|
||||
}
|
||||
lv.Recycle()
|
||||
rv.Recycle()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ListLess compares two lists lexically.
|
||||
func ListLess(lhs, rhs List) bool {
|
||||
return ListCompare(lhs, rhs) == -1
|
||||
}
|
||||
|
||||
// ListCompare compares two lists lexically. The result will be 0 if l==rhs, -1
|
||||
// if l < rhs, and +1 if l > rhs.
|
||||
func ListCompare(lhs, rhs List) int {
|
||||
i := 0
|
||||
for {
|
||||
if i >= lhs.Length() && i >= rhs.Length() {
|
||||
// Lists are the same length and all items are equal.
|
||||
return 0
|
||||
}
|
||||
if i >= lhs.Length() {
|
||||
// LHS is shorter.
|
||||
return -1
|
||||
}
|
||||
if i >= rhs.Length() {
|
||||
// RHS is shorter.
|
||||
return 1
|
||||
}
|
||||
lv := lhs.At(i)
|
||||
rv := rhs.At(i)
|
||||
if c := Compare(lv, rv); c != 0 {
|
||||
return c
|
||||
}
|
||||
lv.Recycle()
|
||||
rv.Recycle()
|
||||
// The items are equal; continue.
|
||||
i++
|
||||
}
|
||||
}
|
||||
42
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listreflect.go
generated
vendored
Normal file
42
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listreflect.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import "reflect"
|
||||
|
||||
type listReflect struct {
|
||||
Value reflect.Value
|
||||
}
|
||||
|
||||
func (r listReflect) Length() int {
|
||||
val := r.Value
|
||||
return val.Len()
|
||||
}
|
||||
|
||||
func (r listReflect) At(i int) Value {
|
||||
val := r.Value
|
||||
return mustWrapValueReflect(val.Index(i))
|
||||
}
|
||||
|
||||
func (r listReflect) Unstructured() interface{} {
|
||||
l := r.Length()
|
||||
result := make([]interface{}, l)
|
||||
for i := 0; i < l; i++ {
|
||||
result[i] = r.At(i).Unstructured()
|
||||
}
|
||||
return result
|
||||
}
|
||||
27
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listunstructured.go
generated
vendored
Normal file
27
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listunstructured.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
type listUnstructured []interface{}
|
||||
|
||||
func (l listUnstructured) Length() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l listUnstructured) At(i int) Value {
|
||||
return NewValueInterface(l[i])
|
||||
}
|
||||
113
vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
generated
vendored
Normal file
113
vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Map represents a Map or go structure.
|
||||
type Map interface {
|
||||
// Set changes or set the value of the given key.
|
||||
Set(key string, val Value)
|
||||
// Get returns the value for the given key, if present, or (nil, false) otherwise.
|
||||
Get(key string) (Value, bool)
|
||||
// Has returns true if the key is present, or false otherwise.
|
||||
Has(key string) bool
|
||||
// Delete removes the key from the map.
|
||||
Delete(key string)
|
||||
// Equals compares the two maps, and return true if they are the same, false otherwise.
|
||||
// Implementations can use MapEquals as a general implementation for this methods.
|
||||
Equals(other Map) bool
|
||||
// Iterate runs the given function for each key/value in the
|
||||
// map. Returning false in the closure prematurely stops the
|
||||
// iteration.
|
||||
Iterate(func(key string, value Value) bool) bool
|
||||
// Length returns the number of items in the map.
|
||||
Length() int
|
||||
}
|
||||
|
||||
// MapLess compares two maps lexically.
|
||||
func MapLess(lhs, rhs Map) bool {
|
||||
return MapCompare(lhs, rhs) == -1
|
||||
}
|
||||
|
||||
// MapCompare compares two maps lexically.
|
||||
func MapCompare(lhs, rhs Map) int {
|
||||
lorder := make([]string, 0, lhs.Length())
|
||||
lhs.Iterate(func(key string, _ Value) bool {
|
||||
lorder = append(lorder, key)
|
||||
return true
|
||||
})
|
||||
sort.Strings(lorder)
|
||||
rorder := make([]string, 0, rhs.Length())
|
||||
rhs.Iterate(func(key string, _ Value) bool {
|
||||
rorder = append(rorder, key)
|
||||
return true
|
||||
})
|
||||
sort.Strings(rorder)
|
||||
|
||||
i := 0
|
||||
for {
|
||||
if i >= len(lorder) && i >= len(rorder) {
|
||||
// Maps are the same length and all items are equal.
|
||||
return 0
|
||||
}
|
||||
if i >= len(lorder) {
|
||||
// LHS is shorter.
|
||||
return -1
|
||||
}
|
||||
if i >= len(rorder) {
|
||||
// RHS is shorter.
|
||||
return 1
|
||||
}
|
||||
if c := strings.Compare(lorder[i], rorder[i]); c != 0 {
|
||||
return c
|
||||
}
|
||||
litem, _ := lhs.Get(lorder[i])
|
||||
ritem, _ := rhs.Get(rorder[i])
|
||||
if c := Compare(litem, ritem); c != 0 {
|
||||
return c
|
||||
}
|
||||
litem.Recycle()
|
||||
ritem.Recycle()
|
||||
// The items are equal; continue.
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
// MapEquals returns true if lhs == rhs, false otherwise. This function
|
||||
// acts on generic types and should not be used by callers, but can help
|
||||
// implement Map.Equals.
|
||||
func MapEquals(lhs, rhs Map) bool {
|
||||
if lhs.Length() != rhs.Length() {
|
||||
return false
|
||||
}
|
||||
return lhs.Iterate(func(k string, v Value) bool {
|
||||
vo, ok := rhs.Get(k)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if !Equals(v, vo) {
|
||||
vo.Recycle()
|
||||
return false
|
||||
}
|
||||
vo.Recycle()
|
||||
return true
|
||||
})
|
||||
}
|
||||
107
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapreflect.go
generated
vendored
Normal file
107
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapreflect.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import "reflect"
|
||||
|
||||
type mapReflect struct {
|
||||
valueReflect
|
||||
}
|
||||
|
||||
func (r mapReflect) Length() int {
|
||||
val := r.Value
|
||||
return val.Len()
|
||||
}
|
||||
|
||||
func (r mapReflect) Get(key string) (Value, bool) {
|
||||
mapKey := r.toMapKey(key)
|
||||
val := r.Value.MapIndex(mapKey)
|
||||
if !val.IsValid() {
|
||||
return nil, false
|
||||
}
|
||||
return mustWrapValueReflectMapItem(&r.Value, &mapKey, val), val != reflect.Value{}
|
||||
}
|
||||
|
||||
func (r mapReflect) Has(key string) bool {
|
||||
var val reflect.Value
|
||||
val = r.Value.MapIndex(r.toMapKey(key))
|
||||
if !val.IsValid() {
|
||||
return false
|
||||
}
|
||||
return val != reflect.Value{}
|
||||
}
|
||||
|
||||
func (r mapReflect) Set(key string, val Value) {
|
||||
r.Value.SetMapIndex(r.toMapKey(key), reflect.ValueOf(val.Unstructured()))
|
||||
}
|
||||
|
||||
func (r mapReflect) Delete(key string) {
|
||||
val := r.Value
|
||||
val.SetMapIndex(r.toMapKey(key), reflect.Value{})
|
||||
}
|
||||
|
||||
// TODO: Do we need to support types that implement json.Marshaler and are used as string keys?
|
||||
func (r mapReflect) toMapKey(key string) reflect.Value {
|
||||
val := r.Value
|
||||
return reflect.ValueOf(key).Convert(val.Type().Key())
|
||||
}
|
||||
|
||||
func (r mapReflect) Iterate(fn func(string, Value) bool) bool {
|
||||
return eachMapEntry(r.Value, func(s string, value reflect.Value) bool {
|
||||
mapVal := mustWrapValueReflect(value)
|
||||
defer mapVal.Recycle()
|
||||
return fn(s, mapVal)
|
||||
})
|
||||
}
|
||||
|
||||
func eachMapEntry(val reflect.Value, fn func(string, reflect.Value) bool) bool {
|
||||
iter := val.MapRange()
|
||||
for iter.Next() {
|
||||
next := iter.Value()
|
||||
if !next.IsValid() {
|
||||
continue
|
||||
}
|
||||
if !fn(iter.Key().String(), next) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r mapReflect) Unstructured() interface{} {
|
||||
result := make(map[string]interface{}, r.Length())
|
||||
r.Iterate(func(s string, value Value) bool {
|
||||
result[s] = value.Unstructured()
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func (r mapReflect) Equals(m Map) bool {
|
||||
if r.Length() != m.Length() {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: Optimize to avoid Iterate looping here by using r.Value.MapRange or similar if it improves performance.
|
||||
return m.Iterate(func(key string, value Value) bool {
|
||||
lhsVal, ok := r.Get(key)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return Equals(lhsVal, value)
|
||||
})
|
||||
}
|
||||
145
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapunstructured.go
generated
vendored
Normal file
145
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapunstructured.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
type mapUnstructuredInterface map[interface{}]interface{}
|
||||
|
||||
func (m mapUnstructuredInterface) Set(key string, val Value) {
|
||||
m[key] = val.Unstructured()
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Get(key string) (Value, bool) {
|
||||
if v, ok := m[key]; !ok {
|
||||
return nil, false
|
||||
} else {
|
||||
return NewValueInterface(v), true
|
||||
}
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Has(key string) bool {
|
||||
_, ok := m[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Delete(key string) {
|
||||
delete(m, key)
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Iterate(fn func(key string, value Value) bool) bool {
|
||||
for k, v := range m {
|
||||
if ks, ok := k.(string); !ok {
|
||||
continue
|
||||
} else {
|
||||
vv := NewValueInterface(v)
|
||||
if !fn(ks, vv) {
|
||||
vv.Recycle()
|
||||
return false
|
||||
}
|
||||
vv.Recycle()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Length() int {
|
||||
return len(m)
|
||||
}
|
||||
|
||||
func (m mapUnstructuredInterface) Equals(other Map) bool {
|
||||
if m.Length() != other.Length() {
|
||||
return false
|
||||
}
|
||||
for k, v := range m {
|
||||
ks, ok := k.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
vo, ok := other.Get(ks)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
vv := NewValueInterface(v)
|
||||
if !Equals(vv, vo) {
|
||||
vv.Recycle()
|
||||
vo.Recycle()
|
||||
return false
|
||||
}
|
||||
vo.Recycle()
|
||||
vv.Recycle()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type mapUnstructuredString map[string]interface{}
|
||||
|
||||
func (m mapUnstructuredString) Set(key string, val Value) {
|
||||
m[key] = val.Unstructured()
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Get(key string) (Value, bool) {
|
||||
if v, ok := m[key]; !ok {
|
||||
return nil, false
|
||||
} else {
|
||||
return NewValueInterface(v), true
|
||||
}
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Has(key string) bool {
|
||||
_, ok := m[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Delete(key string) {
|
||||
delete(m, key)
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Iterate(fn func(key string, value Value) bool) bool {
|
||||
for k, v := range m {
|
||||
vv := NewValueInterface(v)
|
||||
if !fn(k, vv) {
|
||||
vv.Recycle()
|
||||
return false
|
||||
}
|
||||
vv.Recycle()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Length() int {
|
||||
return len(m)
|
||||
}
|
||||
|
||||
func (m mapUnstructuredString) Equals(other Map) bool {
|
||||
if m.Length() != other.Length() {
|
||||
return false
|
||||
}
|
||||
for k, v := range m {
|
||||
vo, ok := other.Get(k)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
vv := NewValueInterface(v)
|
||||
if !Equals(vv, vo) {
|
||||
vo.Recycle()
|
||||
vv.Recycle()
|
||||
return false
|
||||
}
|
||||
vo.Recycle()
|
||||
vv.Recycle()
|
||||
}
|
||||
return true
|
||||
}
|
||||
50
vendor/sigs.k8s.io/structured-merge-diff/v3/value/scalar.go
generated
vendored
Normal file
50
vendor/sigs.k8s.io/structured-merge-diff/v3/value/scalar.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
// Compare compares floats. The result will be 0 if lhs==rhs, -1 if f <
|
||||
// rhs, and +1 if f > rhs.
|
||||
func FloatCompare(lhs, rhs float64) int {
|
||||
if lhs > rhs {
|
||||
return 1
|
||||
} else if lhs < rhs {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntCompare compares integers. The result will be 0 if i==rhs, -1 if i <
|
||||
// rhs, and +1 if i > rhs.
|
||||
func IntCompare(lhs, rhs int64) int {
|
||||
if lhs > rhs {
|
||||
return 1
|
||||
} else if lhs < rhs {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Compare compares booleans. The result will be 0 if b==rhs, -1 if b <
|
||||
// rhs, and +1 if b > rhs.
|
||||
func BoolCompare(lhs, rhs bool) int {
|
||||
if lhs == rhs {
|
||||
return 0
|
||||
} else if lhs == false {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
269
vendor/sigs.k8s.io/structured-merge-diff/v3/value/structreflect.go
generated
vendored
Normal file
269
vendor/sigs.k8s.io/structured-merge-diff/v3/value/structreflect.go
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// reflectStructCache keeps track of json tag related data for structs and fields to speed up reflection.
|
||||
// TODO: This overlaps in functionality with the fieldCache in
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L57 but
|
||||
// is more efficient at lookup by json field name. The logic should be consolidated. Only one copy of the cache needs
|
||||
// to be kept for each running process.
|
||||
var (
|
||||
reflectStructCache = newStructCache()
|
||||
)
|
||||
|
||||
type structCache struct {
|
||||
// use an atomic and copy-on-write since there are a fixed (typically very small) number of structs compiled into any
|
||||
// go program using this cache
|
||||
value atomic.Value
|
||||
// mu is held by writers when performing load/modify/store operations on the cache, readers do not need to hold a
|
||||
// read-lock since the atomic value is always read-only
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type structCacheMap map[reflect.Type]structCacheEntry
|
||||
|
||||
// structCacheEntry contains information about each struct field, keyed by json field name, that is expensive to
|
||||
// compute using reflection.
|
||||
type structCacheEntry map[string]*fieldCacheEntry
|
||||
|
||||
// Get returns true and fieldCacheEntry for the given type if the type is in the cache. Otherwise Get returns false.
|
||||
func (c *structCache) Get(t reflect.Type) (map[string]*fieldCacheEntry, bool) {
|
||||
entry, ok := c.value.Load().(structCacheMap)[t]
|
||||
return entry, ok
|
||||
}
|
||||
|
||||
// Set sets the fieldCacheEntry for the given type via a copy-on-write update to the struct cache.
|
||||
func (c *structCache) Set(t reflect.Type, m map[string]*fieldCacheEntry) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
currentCacheMap := c.value.Load().(structCacheMap)
|
||||
|
||||
if _, ok := currentCacheMap[t]; ok {
|
||||
// Bail if the entry has been set while waiting for lock acquisition.
|
||||
// This is safe since setting entries is idempotent.
|
||||
return
|
||||
}
|
||||
|
||||
newCacheMap := make(structCacheMap, len(currentCacheMap)+1)
|
||||
for k, v := range currentCacheMap {
|
||||
newCacheMap[k] = v
|
||||
}
|
||||
newCacheMap[t] = m
|
||||
c.value.Store(newCacheMap)
|
||||
}
|
||||
|
||||
func newStructCache() *structCache {
|
||||
cache := &structCache{}
|
||||
cache.value.Store(make(structCacheMap))
|
||||
return cache
|
||||
}
|
||||
|
||||
type fieldCacheEntry struct {
|
||||
// isOmitEmpty is true if the field has the json 'omitempty' tag.
|
||||
isOmitEmpty bool
|
||||
// fieldPath is the field indices (see FieldByIndex) to lookup the value of
|
||||
// a field in a reflect.Value struct. A path of field indices is used
|
||||
// to support traversing to a field field in struct fields that have the 'inline'
|
||||
// json tag.
|
||||
fieldPath [][]int
|
||||
}
|
||||
|
||||
func (f *fieldCacheEntry) getFieldFromStruct(structVal reflect.Value) reflect.Value {
|
||||
// field might be field within 'inline' structs
|
||||
for _, elem := range f.fieldPath {
|
||||
structVal = structVal.FieldByIndex(elem)
|
||||
}
|
||||
return structVal
|
||||
}
|
||||
|
||||
func getStructCacheEntry(t reflect.Type) structCacheEntry {
|
||||
if hints, ok := reflectStructCache.Get(t); ok {
|
||||
return hints
|
||||
}
|
||||
|
||||
hints := map[string]*fieldCacheEntry{}
|
||||
buildStructCacheEntry(t, hints, nil)
|
||||
|
||||
reflectStructCache.Set(t, hints)
|
||||
return hints
|
||||
}
|
||||
|
||||
func buildStructCacheEntry(t reflect.Type, infos map[string]*fieldCacheEntry, fieldPath [][]int) {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
jsonName, omit, isInline, isOmitempty := lookupJsonTags(field)
|
||||
if omit {
|
||||
continue
|
||||
}
|
||||
if isInline {
|
||||
buildStructCacheEntry(field.Type, infos, append(fieldPath, field.Index))
|
||||
continue
|
||||
}
|
||||
info := &fieldCacheEntry{isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index)}
|
||||
infos[jsonName] = info
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
type structReflect struct {
|
||||
valueReflect
|
||||
}
|
||||
|
||||
func (r structReflect) Length() int {
|
||||
i := 0
|
||||
eachStructField(r.Value, func(s string, value reflect.Value) bool {
|
||||
i++
|
||||
return true
|
||||
})
|
||||
return i
|
||||
}
|
||||
|
||||
func (r structReflect) Get(key string) (Value, bool) {
|
||||
if val, ok, _ := r.findJsonNameField(key); ok {
|
||||
return mustWrapValueReflect(val), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (r structReflect) Has(key string) bool {
|
||||
_, ok, _ := r.findJsonNameField(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r structReflect) Set(key string, val Value) {
|
||||
fieldEntry, ok := getStructCacheEntry(r.Value.Type())[key]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("key %s may not be set on struct %T: field does not exist", key, r.Value.Interface()))
|
||||
}
|
||||
oldVal := fieldEntry.getFieldFromStruct(r.Value)
|
||||
newVal := reflect.ValueOf(val.Unstructured())
|
||||
r.update(fieldEntry, key, oldVal, newVal)
|
||||
}
|
||||
|
||||
func (r structReflect) Delete(key string) {
|
||||
fieldEntry, ok := getStructCacheEntry(r.Value.Type())[key]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("key %s may not be deleted on struct %T: field does not exist", key, r.Value.Interface()))
|
||||
}
|
||||
oldVal := fieldEntry.getFieldFromStruct(r.Value)
|
||||
if oldVal.Kind() != reflect.Ptr && !fieldEntry.isOmitEmpty {
|
||||
panic(fmt.Sprintf("key %s may not be deleted on struct: %T: value is neither a pointer nor an omitempty field", key, r.Value.Interface()))
|
||||
}
|
||||
r.update(fieldEntry, key, oldVal, reflect.Zero(oldVal.Type()))
|
||||
}
|
||||
|
||||
func (r structReflect) update(fieldEntry *fieldCacheEntry, key string, oldVal, newVal reflect.Value) {
|
||||
if oldVal.CanSet() {
|
||||
oldVal.Set(newVal)
|
||||
return
|
||||
}
|
||||
|
||||
// map items are not addressable, so if a struct is contained in a map, the only way to modify it is
|
||||
// to write a replacement fieldEntry into the map.
|
||||
if r.ParentMap != nil {
|
||||
if r.ParentMapKey == nil {
|
||||
panic("ParentMapKey must not be nil if ParentMap is not nil")
|
||||
}
|
||||
replacement := reflect.New(r.Value.Type()).Elem()
|
||||
fieldEntry.getFieldFromStruct(replacement).Set(newVal)
|
||||
r.ParentMap.SetMapIndex(*r.ParentMapKey, replacement)
|
||||
return
|
||||
}
|
||||
|
||||
// This should never happen since NewValueReflect ensures that the root object reflected on is a pointer and map
|
||||
// item replacement is handled above.
|
||||
panic(fmt.Sprintf("key %s may not be modified on struct: %T: struct is not settable", key, r.Value.Interface()))
|
||||
}
|
||||
|
||||
func (r structReflect) Iterate(fn func(string, Value) bool) bool {
|
||||
return eachStructField(r.Value, func(s string, value reflect.Value) bool {
|
||||
v := mustWrapValueReflect(value)
|
||||
defer v.Recycle()
|
||||
return fn(s, v)
|
||||
})
|
||||
}
|
||||
|
||||
func eachStructField(structVal reflect.Value, fn func(string, reflect.Value) bool) bool {
|
||||
for jsonName, fieldCacheEntry := range getStructCacheEntry(structVal.Type()) {
|
||||
fieldVal := fieldCacheEntry.getFieldFromStruct(structVal)
|
||||
if fieldCacheEntry.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal)) {
|
||||
// omit it
|
||||
continue
|
||||
}
|
||||
ok := fn(jsonName, fieldVal)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r structReflect) Unstructured() interface{} {
|
||||
// Use number of struct fields as a cheap way to rough estimate map size
|
||||
result := make(map[string]interface{}, r.Value.NumField())
|
||||
r.Iterate(func(s string, value Value) bool {
|
||||
result[s] = value.Unstructured()
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func (r structReflect) Equals(m Map) bool {
|
||||
if rhsStruct, ok := m.(structReflect); ok {
|
||||
return reflect.DeepEqual(r.Value.Interface(), rhsStruct.Value.Interface())
|
||||
}
|
||||
if r.Length() != m.Length() {
|
||||
return false
|
||||
}
|
||||
structCacheEntry := getStructCacheEntry(r.Value.Type())
|
||||
|
||||
return m.Iterate(func(s string, value Value) bool {
|
||||
fieldCacheEntry, ok := structCacheEntry[s]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
lhsVal := fieldCacheEntry.getFieldFromStruct(r.Value)
|
||||
return Equals(mustWrapValueReflect(lhsVal), value)
|
||||
})
|
||||
}
|
||||
|
||||
func (r structReflect) findJsonNameFieldAndNotEmpty(jsonName string) (reflect.Value, bool) {
|
||||
structCacheEntry, ok := getStructCacheEntry(r.Value.Type())[jsonName]
|
||||
if !ok {
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
fieldVal := structCacheEntry.getFieldFromStruct(r.Value)
|
||||
omit := structCacheEntry.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal))
|
||||
return fieldVal, !omit
|
||||
}
|
||||
|
||||
func (r structReflect) findJsonNameField(jsonName string) (val reflect.Value, ok bool, omitEmpty bool) {
|
||||
structCacheEntry, ok := getStructCacheEntry(r.Value.Type())[jsonName]
|
||||
if !ok {
|
||||
return reflect.Value{}, false, false
|
||||
}
|
||||
fieldVal := structCacheEntry.getFieldFromStruct(r.Value)
|
||||
return fieldVal, true, structCacheEntry.isOmitEmpty
|
||||
}
|
||||
315
vendor/sigs.k8s.io/structured-merge-diff/v3/value/value.go
generated
vendored
Normal file
315
vendor/sigs.k8s.io/structured-merge-diff/v3/value/value.go
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()
|
||||
writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool()
|
||||
)
|
||||
|
||||
// A Value corresponds to an 'atom' in the schema. It should return true
|
||||
// for at least one of the IsXXX methods below, or the value is
|
||||
// considered "invalid"
|
||||
type Value interface {
|
||||
// IsMap returns true if the Value is a Map, false otherwise.
|
||||
IsMap() bool
|
||||
// IsList returns true if the Value is a List, false otherwise.
|
||||
IsList() bool
|
||||
// IsBool returns true if the Value is a bool, false otherwise.
|
||||
IsBool() bool
|
||||
// IsInt returns true if the Value is a int64, false otherwise.
|
||||
IsInt() bool
|
||||
// IsFloat returns true if the Value is a float64, false
|
||||
// otherwise.
|
||||
IsFloat() bool
|
||||
// IsString returns true if the Value is a string, false
|
||||
// otherwise.
|
||||
IsString() bool
|
||||
// IsMap returns true if the Value is null, false otherwise.
|
||||
IsNull() bool
|
||||
|
||||
// AsMap converts the Value into a Map (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsMap() Map
|
||||
// AsList converts the Value into a List (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsList() List
|
||||
// AsBool converts the Value into a bool (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsBool() bool
|
||||
// AsInt converts the Value into an int64 (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsInt() int64
|
||||
// AsFloat converts the Value into a float64 (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsFloat() float64
|
||||
// AsString converts the Value into a string (or panic if the type
|
||||
// doesn't allow it).
|
||||
AsString() string
|
||||
|
||||
// Recycle returns a value of this type that is no longer needed. The
|
||||
// value shouldn't be used after this call.
|
||||
Recycle()
|
||||
|
||||
// Unstructured converts the Value into an Unstructured interface{}.
|
||||
Unstructured() interface{}
|
||||
}
|
||||
|
||||
// FromJSON is a helper function for reading a JSON document.
|
||||
func FromJSON(input []byte) (Value, error) {
|
||||
return FromJSONFast(input)
|
||||
}
|
||||
|
||||
// FromJSONFast is a helper function for reading a JSON document.
|
||||
func FromJSONFast(input []byte) (Value, error) {
|
||||
iter := readPool.BorrowIterator(input)
|
||||
defer readPool.ReturnIterator(iter)
|
||||
return ReadJSONIter(iter)
|
||||
}
|
||||
|
||||
// ToJSON is a helper function for producing a JSon document.
|
||||
func ToJSON(v Value) ([]byte, error) {
|
||||
buf := bytes.Buffer{}
|
||||
stream := writePool.BorrowStream(&buf)
|
||||
defer writePool.ReturnStream(stream)
|
||||
WriteJSONStream(v, stream)
|
||||
b := stream.Buffer()
|
||||
err := stream.Flush()
|
||||
// Help jsoniter manage its buffers--without this, the next
|
||||
// use of the stream is likely to require an allocation. Look
|
||||
// at the jsoniter stream code to understand why. They were probably
|
||||
// optimizing for folks using the buffer directly.
|
||||
stream.SetBuffer(b[:0])
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// ReadJSONIter reads a Value from a JSON iterator.
|
||||
func ReadJSONIter(iter *jsoniter.Iterator) (Value, error) {
|
||||
v := iter.Read()
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
return nil, iter.Error
|
||||
}
|
||||
return NewValueInterface(v), nil
|
||||
}
|
||||
|
||||
// WriteJSONStream writes a value into a JSON stream.
|
||||
func WriteJSONStream(v Value, stream *jsoniter.Stream) {
|
||||
stream.WriteVal(v.Unstructured())
|
||||
}
|
||||
|
||||
// ToYAML marshals a value as YAML.
|
||||
func ToYAML(v Value) ([]byte, error) {
|
||||
return yaml.Marshal(v.Unstructured())
|
||||
}
|
||||
|
||||
// Equals returns true iff the two values are equal.
|
||||
func Equals(lhs, rhs Value) bool {
|
||||
if lhs.IsFloat() || rhs.IsFloat() {
|
||||
var lf float64
|
||||
if lhs.IsFloat() {
|
||||
lf = lhs.AsFloat()
|
||||
} else if lhs.IsInt() {
|
||||
lf = float64(lhs.AsInt())
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
var rf float64
|
||||
if rhs.IsFloat() {
|
||||
rf = rhs.AsFloat()
|
||||
} else if rhs.IsInt() {
|
||||
rf = float64(rhs.AsInt())
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return lf == rf
|
||||
}
|
||||
if lhs.IsInt() {
|
||||
if rhs.IsInt() {
|
||||
return lhs.AsInt() == rhs.AsInt()
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsInt() {
|
||||
return false
|
||||
}
|
||||
if lhs.IsString() {
|
||||
if rhs.IsString() {
|
||||
return lhs.AsString() == rhs.AsString()
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsString() {
|
||||
return false
|
||||
}
|
||||
if lhs.IsBool() {
|
||||
if rhs.IsBool() {
|
||||
return lhs.AsBool() == rhs.AsBool()
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsBool() {
|
||||
return false
|
||||
}
|
||||
if lhs.IsList() {
|
||||
if rhs.IsList() {
|
||||
return ListEquals(lhs.AsList(), rhs.AsList())
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsList() {
|
||||
return false
|
||||
}
|
||||
if lhs.IsMap() {
|
||||
if rhs.IsMap() {
|
||||
return lhs.AsMap().Equals(rhs.AsMap())
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsMap() {
|
||||
return false
|
||||
}
|
||||
if lhs.IsNull() {
|
||||
if rhs.IsNull() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} else if rhs.IsNull() {
|
||||
return false
|
||||
}
|
||||
// No field is set, on either objects.
|
||||
return true
|
||||
}
|
||||
|
||||
// ToString returns a human-readable representation of the value.
|
||||
func ToString(v Value) string {
|
||||
if v.IsNull() {
|
||||
return "null"
|
||||
}
|
||||
switch {
|
||||
case v.IsFloat():
|
||||
return fmt.Sprintf("%v", v.AsFloat())
|
||||
case v.IsInt():
|
||||
return fmt.Sprintf("%v", v.AsInt())
|
||||
case v.IsString():
|
||||
return fmt.Sprintf("%q", v.AsString())
|
||||
case v.IsBool():
|
||||
return fmt.Sprintf("%v", v.AsBool())
|
||||
case v.IsList():
|
||||
strs := []string{}
|
||||
for i := 0; i < v.AsList().Length(); i++ {
|
||||
strs = append(strs, ToString(v.AsList().At(i)))
|
||||
}
|
||||
return "[" + strings.Join(strs, ",") + "]"
|
||||
case v.IsMap():
|
||||
strs := []string{}
|
||||
v.AsMap().Iterate(func(k string, v Value) bool {
|
||||
strs = append(strs, fmt.Sprintf("%v=%v", k, ToString(v)))
|
||||
return true
|
||||
})
|
||||
return strings.Join(strs, "")
|
||||
}
|
||||
// No field is set, on either objects.
|
||||
return "{{undefined}}"
|
||||
}
|
||||
|
||||
// Less provides a total ordering for Value (so that they can be sorted, even
|
||||
// if they are of different types).
|
||||
func Less(lhs, rhs Value) bool {
|
||||
return Compare(lhs, rhs) == -1
|
||||
}
|
||||
|
||||
// Compare provides a total ordering for Value (so that they can be
|
||||
// sorted, even if they are of different types). The result will be 0 if
|
||||
// v==rhs, -1 if v < rhs, and +1 if v > rhs.
|
||||
func Compare(lhs, rhs Value) int {
|
||||
if lhs.IsFloat() {
|
||||
if !rhs.IsFloat() {
|
||||
// Extra: compare floats and ints numerically.
|
||||
if rhs.IsInt() {
|
||||
return FloatCompare(lhs.AsFloat(), float64(rhs.AsInt()))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
return FloatCompare(lhs.AsFloat(), rhs.AsFloat())
|
||||
} else if rhs.IsFloat() {
|
||||
// Extra: compare floats and ints numerically.
|
||||
if lhs.IsInt() {
|
||||
return FloatCompare(float64(lhs.AsInt()), rhs.AsFloat())
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
if lhs.IsInt() {
|
||||
if !rhs.IsInt() {
|
||||
return -1
|
||||
}
|
||||
return IntCompare(lhs.AsInt(), rhs.AsInt())
|
||||
} else if rhs.IsInt() {
|
||||
return 1
|
||||
}
|
||||
|
||||
if lhs.IsString() {
|
||||
if !rhs.IsString() {
|
||||
return -1
|
||||
}
|
||||
return strings.Compare(lhs.AsString(), rhs.AsString())
|
||||
} else if rhs.IsString() {
|
||||
return 1
|
||||
}
|
||||
|
||||
if lhs.IsBool() {
|
||||
if !rhs.IsBool() {
|
||||
return -1
|
||||
}
|
||||
return BoolCompare(lhs.AsBool(), rhs.AsBool())
|
||||
} else if rhs.IsBool() {
|
||||
return 1
|
||||
}
|
||||
|
||||
if lhs.IsList() {
|
||||
if !rhs.IsList() {
|
||||
return -1
|
||||
}
|
||||
return ListCompare(lhs.AsList(), rhs.AsList())
|
||||
} else if rhs.IsList() {
|
||||
return 1
|
||||
}
|
||||
if lhs.IsMap() {
|
||||
if !rhs.IsMap() {
|
||||
return -1
|
||||
}
|
||||
return MapCompare(lhs.AsMap(), rhs.AsMap())
|
||||
} else if rhs.IsMap() {
|
||||
return 1
|
||||
}
|
||||
if lhs.IsNull() {
|
||||
if !rhs.IsNull() {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
} else if rhs.IsNull() {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Invalid Value-- nothing is set.
|
||||
return 0
|
||||
}
|
||||
319
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valuereflect.go
generated
vendored
Normal file
319
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valuereflect.go
generated
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var reflectPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &valueReflect{}
|
||||
},
|
||||
}
|
||||
|
||||
// NewValueReflect creates a Value backed by an "interface{}" type,
|
||||
// typically an structured object in Kubernetes world that is uses reflection to expose.
|
||||
// The provided "interface{}" value must be a pointer so that the value can be modified via reflection.
|
||||
// The provided "interface{}" may contain structs and types that are converted to Values
|
||||
// by the jsonMarshaler interface.
|
||||
func NewValueReflect(value interface{}) (Value, error) {
|
||||
if value == nil {
|
||||
return NewValueInterface(nil), nil
|
||||
}
|
||||
v := reflect.ValueOf(value)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
// The root value to reflect on must be a pointer so that map.Set() and map.Delete() operations are possible.
|
||||
return nil, fmt.Errorf("value provided to NewValueReflect must be a pointer")
|
||||
}
|
||||
return wrapValueReflect(nil, nil, v)
|
||||
}
|
||||
|
||||
func wrapValueReflect(parentMap, parentMapKey *reflect.Value, value reflect.Value) (Value, error) {
|
||||
// TODO: conversion of json.Marshaller interface types is expensive. This can be mostly optimized away by
|
||||
// introducing conversion functions that do not require going through JSON and using those here.
|
||||
if marshaler, ok := getMarshaler(value); ok {
|
||||
return toUnstructured(marshaler, value)
|
||||
}
|
||||
value = dereference(value)
|
||||
val := reflectPool.Get().(*valueReflect)
|
||||
val.Value = value
|
||||
val.ParentMap = parentMap
|
||||
val.ParentMapKey = parentMapKey
|
||||
return Value(val), nil
|
||||
}
|
||||
|
||||
func mustWrapValueReflect(value reflect.Value) Value {
|
||||
v, err := wrapValueReflect(nil, nil, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func mustWrapValueReflectMapItem(parentMap, parentMapKey *reflect.Value, value reflect.Value) Value {
|
||||
v, err := wrapValueReflect(parentMap, parentMapKey, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func dereference(val reflect.Value) reflect.Value {
|
||||
kind := val.Kind()
|
||||
if (kind == reflect.Interface || kind == reflect.Ptr) && !safeIsNil(val) {
|
||||
return val.Elem()
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
type valueReflect struct {
|
||||
ParentMap *reflect.Value
|
||||
ParentMapKey *reflect.Value
|
||||
Value reflect.Value
|
||||
}
|
||||
|
||||
func (r valueReflect) IsMap() bool {
|
||||
return r.isKind(reflect.Map, reflect.Struct)
|
||||
}
|
||||
|
||||
func (r valueReflect) IsList() bool {
|
||||
typ := r.Value.Type()
|
||||
return typ.Kind() == reflect.Slice && !(typ.Elem().Kind() == reflect.Uint8)
|
||||
}
|
||||
|
||||
func (r valueReflect) IsBool() bool {
|
||||
return r.isKind(reflect.Bool)
|
||||
}
|
||||
|
||||
func (r valueReflect) IsInt() bool {
|
||||
// Uint64 deliberately excluded, see valueUnstructured.Int.
|
||||
return r.isKind(reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8)
|
||||
}
|
||||
|
||||
func (r valueReflect) IsFloat() bool {
|
||||
return r.isKind(reflect.Float64, reflect.Float32)
|
||||
}
|
||||
|
||||
func (r valueReflect) IsString() bool {
|
||||
kind := r.Value.Kind()
|
||||
if kind == reflect.String {
|
||||
return true
|
||||
}
|
||||
if kind == reflect.Slice && r.Value.Type().Elem().Kind() == reflect.Uint8 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r valueReflect) IsNull() bool {
|
||||
return safeIsNil(r.Value)
|
||||
}
|
||||
|
||||
func (r valueReflect) isKind(kinds ...reflect.Kind) bool {
|
||||
kind := r.Value.Kind()
|
||||
for _, k := range kinds {
|
||||
if kind == k {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO find a cleaner way to avoid panics from reflect.IsNil()
|
||||
func safeIsNil(v reflect.Value) bool {
|
||||
k := v.Kind()
|
||||
switch k {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r valueReflect) AsMap() Map {
|
||||
val := r.Value
|
||||
switch val.Kind() {
|
||||
case reflect.Struct:
|
||||
return structReflect{r}
|
||||
case reflect.Map:
|
||||
return mapReflect{r}
|
||||
default:
|
||||
panic("value is not a map or struct")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *valueReflect) Recycle() {
|
||||
reflectPool.Put(r)
|
||||
}
|
||||
|
||||
func (r valueReflect) AsList() List {
|
||||
if r.IsList() {
|
||||
return listReflect{r.Value}
|
||||
}
|
||||
panic("value is not a list")
|
||||
}
|
||||
|
||||
func (r valueReflect) AsBool() bool {
|
||||
if r.IsBool() {
|
||||
return r.Value.Bool()
|
||||
}
|
||||
panic("value is not a bool")
|
||||
}
|
||||
|
||||
func (r valueReflect) AsInt() int64 {
|
||||
if r.isKind(reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8) {
|
||||
return r.Value.Int()
|
||||
}
|
||||
if r.isKind(reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8) {
|
||||
return int64(r.Value.Uint())
|
||||
}
|
||||
|
||||
panic("value is not an int")
|
||||
}
|
||||
|
||||
func (r valueReflect) AsFloat() float64 {
|
||||
if r.IsFloat() {
|
||||
return r.Value.Float()
|
||||
}
|
||||
panic("value is not a float")
|
||||
}
|
||||
|
||||
func (r valueReflect) AsString() string {
|
||||
kind := r.Value.Kind()
|
||||
if kind == reflect.String {
|
||||
return r.Value.String()
|
||||
}
|
||||
if kind == reflect.Slice && r.Value.Type().Elem().Kind() == reflect.Uint8 {
|
||||
return base64.StdEncoding.EncodeToString(r.Value.Bytes())
|
||||
}
|
||||
panic("value is not a string")
|
||||
}
|
||||
|
||||
func (r valueReflect) Unstructured() interface{} {
|
||||
val := r.Value
|
||||
switch {
|
||||
case r.IsNull():
|
||||
return nil
|
||||
case val.Kind() == reflect.Struct:
|
||||
return structReflect{r}.Unstructured()
|
||||
case val.Kind() == reflect.Map:
|
||||
return mapReflect{r}.Unstructured()
|
||||
case r.IsList():
|
||||
return listReflect{Value: r.Value}.Unstructured()
|
||||
case r.IsString():
|
||||
return r.AsString()
|
||||
case r.IsInt():
|
||||
return r.AsInt()
|
||||
case r.IsBool():
|
||||
return r.AsBool()
|
||||
case r.IsFloat():
|
||||
return r.AsFloat()
|
||||
default:
|
||||
panic(fmt.Sprintf("value of type %s is not a supported by value reflector", val.Type()))
|
||||
}
|
||||
}
|
||||
|
||||
// The below getMarshaler and toUnstructured functions are based on
|
||||
// https://github.com/kubernetes/kubernetes/blob/40df9f82d0572a123f5ad13f48312978a2ff5877/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L509
|
||||
// and should somehow be consolidated with it
|
||||
|
||||
var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem()
|
||||
|
||||
func getMarshaler(v reflect.Value) (json.Marshaler, bool) {
|
||||
// Check value receivers if v is not a pointer and pointer receivers if v is a pointer
|
||||
if v.Type().Implements(marshalerType) {
|
||||
return v.Interface().(json.Marshaler), true
|
||||
}
|
||||
// Check pointer receivers if v is not a pointer
|
||||
if v.Kind() != reflect.Ptr && v.CanAddr() {
|
||||
v = v.Addr()
|
||||
if v.Type().Implements(marshalerType) {
|
||||
return v.Interface().(json.Marshaler), true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var (
|
||||
nullBytes = []byte("null")
|
||||
trueBytes = []byte("true")
|
||||
falseBytes = []byte("false")
|
||||
)
|
||||
|
||||
func toUnstructured(marshaler json.Marshaler, sv reflect.Value) (Value, error) {
|
||||
data, err := marshaler.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case len(data) == 0:
|
||||
return nil, fmt.Errorf("error decoding from json: empty value")
|
||||
|
||||
case bytes.Equal(data, nullBytes):
|
||||
// We're done - we don't need to store anything.
|
||||
return NewValueInterface(nil), nil
|
||||
|
||||
case bytes.Equal(data, trueBytes):
|
||||
return NewValueInterface(true), nil
|
||||
|
||||
case bytes.Equal(data, falseBytes):
|
||||
return NewValueInterface(false), nil
|
||||
|
||||
case data[0] == '"':
|
||||
var result string
|
||||
err := json.Unmarshal(data, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding string from json: %v", err)
|
||||
}
|
||||
return NewValueInterface(result), nil
|
||||
|
||||
case data[0] == '{':
|
||||
result := make(map[string]interface{})
|
||||
err := json.Unmarshal(data, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding object from json: %v", err)
|
||||
}
|
||||
return NewValueInterface(result), nil
|
||||
|
||||
case data[0] == '[':
|
||||
result := make([]interface{}, 0)
|
||||
err := json.Unmarshal(data, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding array from json: %v", err)
|
||||
}
|
||||
return NewValueInterface(result), nil
|
||||
|
||||
default:
|
||||
var (
|
||||
resultInt int64
|
||||
resultFloat float64
|
||||
err error
|
||||
)
|
||||
if err = json.Unmarshal(data, &resultInt); err == nil {
|
||||
return NewValueInterface(resultInt), nil
|
||||
}
|
||||
if err = json.Unmarshal(data, &resultFloat); err == nil {
|
||||
return NewValueInterface(resultFloat), nil
|
||||
}
|
||||
return nil, fmt.Errorf("error decoding number from json: %v", err)
|
||||
}
|
||||
}
|
||||
177
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valueunstructured.go
generated
vendored
Normal file
177
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valueunstructured.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package value
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var viPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &valueUnstructured{}
|
||||
},
|
||||
}
|
||||
|
||||
// NewValueInterface creates a Value backed by an "interface{}" type,
|
||||
// typically an unstructured object in Kubernetes world.
|
||||
// interface{} must be one of: map[string]interface{}, map[interface{}]interface{}, []interface{}, int types, float types,
|
||||
// string or boolean. Nested interface{} must also be one of these types.
|
||||
func NewValueInterface(v interface{}) Value {
|
||||
vi := viPool.Get().(*valueUnstructured)
|
||||
vi.Value = v
|
||||
return Value(vi)
|
||||
}
|
||||
|
||||
type valueUnstructured struct {
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsMap() bool {
|
||||
if _, ok := v.Value.(map[string]interface{}); ok {
|
||||
return true
|
||||
}
|
||||
if _, ok := v.Value.(map[interface{}]interface{}); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsMap() Map {
|
||||
if v.Value == nil {
|
||||
panic("invalid nil")
|
||||
}
|
||||
switch t := v.Value.(type) {
|
||||
case map[string]interface{}:
|
||||
return mapUnstructuredString(t)
|
||||
case map[interface{}]interface{}:
|
||||
return mapUnstructuredInterface(t)
|
||||
}
|
||||
panic(fmt.Errorf("not a map: %#v", v))
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsList() bool {
|
||||
if v.Value == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := v.Value.([]interface{})
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsList() List {
|
||||
return listUnstructured(v.Value.([]interface{}))
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsFloat() bool {
|
||||
if v.Value == nil {
|
||||
return false
|
||||
} else if _, ok := v.Value.(float64); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(float32); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsFloat() float64 {
|
||||
if f, ok := v.Value.(float32); ok {
|
||||
return float64(f)
|
||||
}
|
||||
return v.Value.(float64)
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsInt() bool {
|
||||
if v.Value == nil {
|
||||
return false
|
||||
} else if _, ok := v.Value.(int); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(int8); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(int16); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(int32); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(int64); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(uint); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(uint8); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(uint16); ok {
|
||||
return true
|
||||
} else if _, ok := v.Value.(uint32); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsInt() int64 {
|
||||
if i, ok := v.Value.(int); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(int8); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(int16); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(int32); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(uint); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(uint8); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(uint16); ok {
|
||||
return int64(i)
|
||||
} else if i, ok := v.Value.(uint32); ok {
|
||||
return int64(i)
|
||||
}
|
||||
return v.Value.(int64)
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsString() bool {
|
||||
if v.Value == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := v.Value.(string)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsString() string {
|
||||
return v.Value.(string)
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsBool() bool {
|
||||
if v.Value == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := v.Value.(bool)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v valueUnstructured) AsBool() bool {
|
||||
return v.Value.(bool)
|
||||
}
|
||||
|
||||
func (v valueUnstructured) IsNull() bool {
|
||||
return v.Value == nil
|
||||
}
|
||||
|
||||
func (v *valueUnstructured) Recycle() {
|
||||
viPool.Put(v)
|
||||
}
|
||||
|
||||
func (v valueUnstructured) Unstructured() interface{} {
|
||||
return v.Value
|
||||
}
|
||||
Reference in New Issue
Block a user