mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-06-10 10:15:57 +00:00
vendor: Update vendor logic
This commit is contained in:
parent
c6ac5cbc87
commit
4ca64b85f0
1540 changed files with 265304 additions and 91616 deletions
182
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/element.go
generated
vendored
182
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/element.go
generated
vendored
|
|
@ -35,7 +35,7 @@ type PathElement struct {
|
|||
// Key selects the list element which has fields matching those given.
|
||||
// The containing object must be an associative list with map typed
|
||||
// elements.
|
||||
Key []value.Field
|
||||
Key *value.FieldList
|
||||
|
||||
// Value selects the list element with the given value. The containing
|
||||
// object must be an associative list with a primitive typed element
|
||||
|
|
@ -47,19 +47,65 @@ type PathElement struct {
|
|||
Index *int
|
||||
}
|
||||
|
||||
// Less provides an order for path elements.
|
||||
func (e PathElement) Less(rhs PathElement) bool {
|
||||
if e.FieldName != nil {
|
||||
if rhs.FieldName == nil {
|
||||
return true
|
||||
}
|
||||
return *e.FieldName < *rhs.FieldName
|
||||
} else if rhs.FieldName != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if e.Key != nil {
|
||||
if rhs.Key == nil {
|
||||
return true
|
||||
}
|
||||
return e.Key.Less(*rhs.Key)
|
||||
} else if rhs.Key != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if e.Value != nil {
|
||||
if rhs.Value == nil {
|
||||
return true
|
||||
}
|
||||
return e.Value.Less(*rhs.Value)
|
||||
} else if rhs.Value != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if e.Index != nil {
|
||||
if rhs.Index == nil {
|
||||
return true
|
||||
}
|
||||
return *e.Index < *rhs.Index
|
||||
} else if rhs.Index != nil {
|
||||
// Yes, I know the next statement is the same. But this way
|
||||
// the obvious way of extending the function wil be bug-free.
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Equals returns true if both path elements are equal.
|
||||
func (e PathElement) Equals(rhs PathElement) bool {
|
||||
return !e.Less(rhs) && !rhs.Less(e)
|
||||
}
|
||||
|
||||
// String presents the path element as a human-readable string.
|
||||
func (e PathElement) String() string {
|
||||
switch {
|
||||
case e.FieldName != nil:
|
||||
return "." + *e.FieldName
|
||||
case len(e.Key) > 0:
|
||||
strs := make([]string, len(e.Key))
|
||||
for i, k := range e.Key {
|
||||
case e.Key != nil:
|
||||
strs := make([]string, len(*e.Key))
|
||||
for i, k := range *e.Key {
|
||||
strs[i] = fmt.Sprintf("%v=%v", k.Name, k.Value)
|
||||
}
|
||||
// The order must be canonical, since we use the string value
|
||||
// in a set structure.
|
||||
sort.Strings(strs)
|
||||
// Keys are supposed to be sorted.
|
||||
return "[" + strings.Join(strs, ",") + "]"
|
||||
case e.Value != nil:
|
||||
return fmt.Sprintf("[=%v]", e.Value)
|
||||
|
|
@ -75,79 +121,124 @@ func (e PathElement) String() string {
|
|||
// names (type must be string) with values (type must be value.Value). If these
|
||||
// conditions are not met, KeyByFields will panic--it's intended for static
|
||||
// construction and shouldn't have user-produced values passed to it.
|
||||
func KeyByFields(nameValues ...interface{}) []value.Field {
|
||||
func KeyByFields(nameValues ...interface{}) *value.FieldList {
|
||||
if len(nameValues)%2 != 0 {
|
||||
panic("must have a value for every name")
|
||||
}
|
||||
out := []value.Field{}
|
||||
out := value.FieldList{}
|
||||
for i := 0; i < len(nameValues)-1; i += 2 {
|
||||
out = append(out, value.Field{
|
||||
Name: nameValues[i].(string),
|
||||
Value: nameValues[i+1].(value.Value),
|
||||
})
|
||||
}
|
||||
return out
|
||||
out.Sort()
|
||||
return &out
|
||||
}
|
||||
|
||||
// PathElementSet is a set of path elements.
|
||||
// TODO: serialize as a list.
|
||||
type PathElementSet struct {
|
||||
// The strange construction is because there's no way to test
|
||||
// PathElements for equality (it can't be used as a key for a map).
|
||||
members map[string]PathElement
|
||||
members sortedPathElements
|
||||
}
|
||||
|
||||
func MakePathElementSet(size int) PathElementSet {
|
||||
return PathElementSet{
|
||||
members: make(sortedPathElements, 0, size),
|
||||
}
|
||||
}
|
||||
|
||||
type sortedPathElements []PathElement
|
||||
|
||||
// Implement the sort interface; this would permit bulk creation, which would
|
||||
// be faster than doing it one at a time via Insert.
|
||||
func (spe sortedPathElements) Len() int { return len(spe) }
|
||||
func (spe sortedPathElements) Less(i, j int) bool { return spe[i].Less(spe[j]) }
|
||||
func (spe sortedPathElements) Swap(i, j int) { spe[i], spe[j] = spe[j], spe[i] }
|
||||
|
||||
// Insert adds pe to the set.
|
||||
func (s *PathElementSet) Insert(pe PathElement) {
|
||||
serialized := pe.String()
|
||||
if s.members == nil {
|
||||
s.members = map[string]PathElement{
|
||||
serialized: pe,
|
||||
}
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
s.members = append(s.members, pe)
|
||||
return
|
||||
}
|
||||
if _, ok := s.members[serialized]; !ok {
|
||||
s.members[serialized] = pe
|
||||
if s.members[loc].Equals(pe) {
|
||||
return
|
||||
}
|
||||
s.members = append(s.members, PathElement{})
|
||||
copy(s.members[loc+1:], s.members[loc:])
|
||||
s.members[loc] = pe
|
||||
}
|
||||
|
||||
// Union returns a set containing elements that appear in either s or s2.
|
||||
func (s *PathElementSet) Union(s2 *PathElementSet) *PathElementSet {
|
||||
out := &PathElementSet{
|
||||
members: map[string]PathElement{},
|
||||
out := &PathElementSet{}
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.members) {
|
||||
if s.members[i].Less(s2.members[j]) {
|
||||
out.members = append(out.members, s.members[i])
|
||||
i++
|
||||
} else {
|
||||
out.members = append(out.members, s2.members[j])
|
||||
if !s2.members[j].Less(s.members[i]) {
|
||||
i++
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
for k, v := range s.members {
|
||||
out.members[k] = v
|
||||
|
||||
if i < len(s.members) {
|
||||
out.members = append(out.members, s.members[i:]...)
|
||||
}
|
||||
for k, v := range s2.members {
|
||||
out.members[k] = v
|
||||
if j < len(s2.members) {
|
||||
out.members = append(out.members, s2.members[j:]...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Intersection returns a set containing elements which appear in both s and s2.
|
||||
func (s *PathElementSet) Intersection(s2 *PathElementSet) *PathElementSet {
|
||||
out := &PathElementSet{
|
||||
members: map[string]PathElement{},
|
||||
}
|
||||
for k, v := range s.members {
|
||||
if _, ok := s2.members[k]; ok {
|
||||
out.members[k] = v
|
||||
out := &PathElementSet{}
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.members) {
|
||||
if s.members[i].Less(s2.members[j]) {
|
||||
i++
|
||||
} else {
|
||||
if !s2.members[j].Less(s.members[i]) {
|
||||
out.members = append(out.members, s.members[i])
|
||||
i++
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Difference returns a set containing elements which appear in s but not in s2.
|
||||
func (s *PathElementSet) Difference(s2 *PathElementSet) *PathElementSet {
|
||||
out := &PathElementSet{
|
||||
members: map[string]PathElement{},
|
||||
}
|
||||
for k, v := range s.members {
|
||||
if _, ok := s2.members[k]; !ok {
|
||||
out.members[k] = v
|
||||
out := &PathElementSet{}
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.members) {
|
||||
if s.members[i].Less(s2.members[j]) {
|
||||
out.members = append(out.members, s.members[i])
|
||||
i++
|
||||
} else {
|
||||
if !s2.members[j].Less(s.members[i]) {
|
||||
i++
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
if i < len(s.members) {
|
||||
out.members = append(out.members, s.members[i:]...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -156,11 +247,16 @@ func (s *PathElementSet) Size() int { return len(s.members) }
|
|||
|
||||
// Has returns true if pe is a member of the set.
|
||||
func (s *PathElementSet) Has(pe PathElement) bool {
|
||||
if s.members == nil {
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
return false
|
||||
}
|
||||
_, ok := s.members[pe.String()]
|
||||
return ok
|
||||
if s.members[loc].Equals(pe) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equals returns true if s and s2 have exactly the same members.
|
||||
|
|
@ -169,14 +265,14 @@ func (s *PathElementSet) Equals(s2 *PathElementSet) bool {
|
|||
return false
|
||||
}
|
||||
for k := range s.members {
|
||||
if _, ok := s2.members[k]; !ok {
|
||||
if !s.members[k].Equals(s2.members[k]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Iterate calls f for each PathElement in the set.
|
||||
// Iterate calls f for each PathElement in the set. The order is deterministic.
|
||||
func (s *PathElementSet) Iterate(f func(PathElement)) {
|
||||
for _, pe := range s.members {
|
||||
f(pe)
|
||||
|
|
|
|||
5
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/fromvalue.go
generated
vendored
5
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/fromvalue.go
generated
vendored
|
|
@ -104,7 +104,7 @@ func GuessBestListPathElement(index int, item value.Value) PathElement {
|
|||
return PathElement{Index: &index}
|
||||
}
|
||||
|
||||
var keys []value.Field
|
||||
var keys value.FieldList
|
||||
for _, name := range AssociativeListCandidateFieldNames {
|
||||
f, ok := item.MapValue.Get(name)
|
||||
if !ok {
|
||||
|
|
@ -117,7 +117,8 @@ func GuessBestListPathElement(index int, item value.Value) PathElement {
|
|||
keys = append(keys, *f)
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
return PathElement{Key: keys}
|
||||
keys.Sort()
|
||||
return PathElement{Key: &keys}
|
||||
}
|
||||
return PathElement{Index: &index}
|
||||
}
|
||||
|
|
|
|||
49
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/managers.go
generated
vendored
49
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/managers.go
generated
vendored
|
|
@ -16,16 +16,42 @@ package fieldpath
|
|||
// APIVersion describes the version of an object or of a fieldset.
|
||||
type APIVersion string
|
||||
|
||||
type VersionedSet interface {
|
||||
Set() *Set
|
||||
APIVersion() APIVersion
|
||||
Applied() bool
|
||||
}
|
||||
|
||||
// VersionedSet associates a version to a set.
|
||||
type VersionedSet struct {
|
||||
*Set
|
||||
APIVersion APIVersion
|
||||
Applied bool
|
||||
type versionedSet struct {
|
||||
set *Set
|
||||
apiVersion APIVersion
|
||||
applied bool
|
||||
}
|
||||
|
||||
func NewVersionedSet(set *Set, apiVersion APIVersion, applied bool) VersionedSet {
|
||||
return versionedSet{
|
||||
set: set,
|
||||
apiVersion: apiVersion,
|
||||
applied: applied,
|
||||
}
|
||||
}
|
||||
|
||||
func (v versionedSet) Set() *Set {
|
||||
return v.set
|
||||
}
|
||||
|
||||
func (v versionedSet) APIVersion() APIVersion {
|
||||
return v.apiVersion
|
||||
}
|
||||
|
||||
func (v versionedSet) Applied() bool {
|
||||
return v.applied
|
||||
}
|
||||
|
||||
// ManagedFields is a map from manager to VersionedSet (what they own in
|
||||
// what version).
|
||||
type ManagedFields map[string]*VersionedSet
|
||||
type ManagedFields map[string]VersionedSet
|
||||
|
||||
// Difference returns a symmetric difference between two Managers. If a
|
||||
// given user's entry has version X in lhs and version Y in rhs, then
|
||||
|
|
@ -37,7 +63,7 @@ func (lhs ManagedFields) Difference(rhs ManagedFields) ManagedFields {
|
|||
for manager, left := range lhs {
|
||||
right, ok := rhs[manager]
|
||||
if !ok {
|
||||
if !left.Empty() {
|
||||
if !left.Set().Empty() {
|
||||
diff[manager] = left
|
||||
}
|
||||
continue
|
||||
|
|
@ -46,17 +72,14 @@ func (lhs ManagedFields) Difference(rhs ManagedFields) ManagedFields {
|
|||
// If we have sets in both but their version
|
||||
// differs, we don't even diff and keep the
|
||||
// entire thing.
|
||||
if left.APIVersion != right.APIVersion {
|
||||
if left.APIVersion() != right.APIVersion() {
|
||||
diff[manager] = right
|
||||
continue
|
||||
}
|
||||
|
||||
newSet := left.Difference(right.Set).Union(right.Difference(left.Set))
|
||||
newSet := left.Set().Difference(right.Set()).Union(right.Set().Difference(left.Set()))
|
||||
if !newSet.Empty() {
|
||||
diff[manager] = &VersionedSet{
|
||||
Set: newSet,
|
||||
APIVersion: right.APIVersion,
|
||||
}
|
||||
diff[manager] = NewVersionedSet(newSet, right.APIVersion(), false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +88,7 @@ func (lhs ManagedFields) Difference(rhs ManagedFields) ManagedFields {
|
|||
// Already done
|
||||
continue
|
||||
}
|
||||
if !set.Empty() {
|
||||
if !set.Set().Empty() {
|
||||
diff[manager] = set
|
||||
}
|
||||
}
|
||||
|
|
|
|||
38
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/path.go
generated
vendored
38
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/path.go
generated
vendored
|
|
@ -35,6 +35,40 @@ func (fp Path) String() string {
|
|||
return strings.Join(strs, "")
|
||||
}
|
||||
|
||||
// Equals returns true if the two paths are equivalent.
|
||||
func (fp Path) Equals(fp2 Path) bool {
|
||||
return !fp.Less(fp2) && !fp2.Less(fp)
|
||||
}
|
||||
|
||||
// Less provides a lexical order for Paths.
|
||||
func (fp Path) Less(rhs Path) bool {
|
||||
i := 0
|
||||
for {
|
||||
if i >= len(fp) && i >= len(rhs) {
|
||||
// Paths are the same length and all items are equal.
|
||||
return false
|
||||
}
|
||||
if i >= len(fp) {
|
||||
// LHS is shorter.
|
||||
return true
|
||||
}
|
||||
if i >= len(rhs) {
|
||||
// RHS is shorter.
|
||||
return false
|
||||
}
|
||||
if fp[i].Less(rhs[i]) {
|
||||
// LHS is less; return
|
||||
return true
|
||||
}
|
||||
if rhs[i].Less(fp[i]) {
|
||||
// RHS is less; return
|
||||
return false
|
||||
}
|
||||
// The items are equal; continue.
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func (fp Path) Copy() Path {
|
||||
new := make(Path, len(fp))
|
||||
copy(new, fp)
|
||||
|
|
@ -54,8 +88,8 @@ func MakePath(parts ...interface{}) (Path, error) {
|
|||
fp = append(fp, PathElement{Index: &t})
|
||||
case string:
|
||||
fp = append(fp, PathElement{FieldName: &t})
|
||||
case []value.Field:
|
||||
if len(t) == 0 {
|
||||
case *value.FieldList:
|
||||
if len(*t) == 0 {
|
||||
return nil, fmt.Errorf("associative list key type path elements must have at least one key (got zero)")
|
||||
}
|
||||
fp = append(fp, PathElement{Key: t})
|
||||
|
|
|
|||
85
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/pathelementmap.go
generated
vendored
Normal file
85
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/pathelementmap.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
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 fieldpath
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/value"
|
||||
)
|
||||
|
||||
// PathElementValueMap is a map from PathElement to value.Value.
|
||||
//
|
||||
// TODO(apelisse): We have multiple very similar implementation of this
|
||||
// for PathElementSet and SetNodeMap, so we could probably share the
|
||||
// code.
|
||||
type PathElementValueMap struct {
|
||||
members sortedPathElementValues
|
||||
}
|
||||
|
||||
func MakePathElementValueMap(size int) PathElementValueMap {
|
||||
return PathElementValueMap{
|
||||
members: make(sortedPathElementValues, 0, size),
|
||||
}
|
||||
}
|
||||
|
||||
type pathElementValue struct {
|
||||
PathElement PathElement
|
||||
Value value.Value
|
||||
}
|
||||
|
||||
type sortedPathElementValues []pathElementValue
|
||||
|
||||
// Implement the sort interface; this would permit bulk creation, which would
|
||||
// be faster than doing it one at a time via Insert.
|
||||
func (spev sortedPathElementValues) Len() int { return len(spev) }
|
||||
func (spev sortedPathElementValues) Less(i, j int) bool {
|
||||
return spev[i].PathElement.Less(spev[j].PathElement)
|
||||
}
|
||||
func (spev sortedPathElementValues) Swap(i, j int) { spev[i], spev[j] = spev[j], spev[i] }
|
||||
|
||||
// Insert adds the pathelement and associated value in the map.
|
||||
func (s *PathElementValueMap) Insert(pe PathElement, v value.Value) {
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].PathElement.Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
s.members = append(s.members, pathElementValue{pe, v})
|
||||
return
|
||||
}
|
||||
if s.members[loc].PathElement.Equals(pe) {
|
||||
return
|
||||
}
|
||||
s.members = append(s.members, pathElementValue{})
|
||||
copy(s.members[loc+1:], s.members[loc:])
|
||||
s.members[loc] = pathElementValue{pe, v}
|
||||
}
|
||||
|
||||
// Get retrieves the value associated with the given PathElement from the map.
|
||||
// (nil, false) is returned if there is no such PathElement.
|
||||
func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) {
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].PathElement.Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
return value.Value{}, false
|
||||
}
|
||||
if s.members[loc].PathElement.Equals(pe) {
|
||||
return s.members[loc].Value, true
|
||||
}
|
||||
return value.Value{}, false
|
||||
}
|
||||
166
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/serialize-pe.go
generated
vendored
Normal file
166
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/serialize-pe.go
generated
vendored
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
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 fieldpath
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"sigs.k8s.io/structured-merge-diff/value"
|
||||
)
|
||||
|
||||
var ErrUnknownPathElementType = errors.New("unknown path element type")
|
||||
|
||||
const (
|
||||
// Field indicates that the content of this path element is a field's name
|
||||
peField = "f"
|
||||
|
||||
// Value indicates that the content of this path element is a field's value
|
||||
peValue = "v"
|
||||
|
||||
// Index indicates that the content of this path element is an index in an array
|
||||
peIndex = "i"
|
||||
|
||||
// Key indicates that the content of this path element is a key value map
|
||||
peKey = "k"
|
||||
|
||||
// Separator separates the type of a path element from the contents
|
||||
peSeparator = ":"
|
||||
)
|
||||
|
||||
var (
|
||||
peFieldSepBytes = []byte(peField + peSeparator)
|
||||
peValueSepBytes = []byte(peValue + peSeparator)
|
||||
peIndexSepBytes = []byte(peIndex + peSeparator)
|
||||
peKeySepBytes = []byte(peKey + peSeparator)
|
||||
peSepBytes = []byte(peSeparator)
|
||||
)
|
||||
|
||||
// DeserializePathElement parses a serialized path element
|
||||
func DeserializePathElement(s string) (PathElement, error) {
|
||||
b := []byte(s)
|
||||
if len(b) < 2 {
|
||||
return PathElement{}, errors.New("key must be 2 characters long:")
|
||||
}
|
||||
typeSep, b := b[:2], b[2:]
|
||||
if typeSep[1] != peSepBytes[0] {
|
||||
return PathElement{}, fmt.Errorf("missing colon: %v", s)
|
||||
}
|
||||
switch typeSep[0] {
|
||||
case peFieldSepBytes[0]:
|
||||
// Slice s rather than convert b, to save on
|
||||
// allocations.
|
||||
str := s[2:]
|
||||
return PathElement{
|
||||
FieldName: &str,
|
||||
}, nil
|
||||
case peValueSepBytes[0]:
|
||||
iter := readPool.BorrowIterator(b)
|
||||
defer readPool.ReturnIterator(iter)
|
||||
v, err := value.ReadJSONIter(iter)
|
||||
if err != nil {
|
||||
return PathElement{}, err
|
||||
}
|
||||
return PathElement{Value: &v}, nil
|
||||
case peKeySepBytes[0]:
|
||||
iter := readPool.BorrowIterator(b)
|
||||
defer readPool.ReturnIterator(iter)
|
||||
fields := value.FieldList{}
|
||||
iter.ReadObjectCB(func(iter *jsoniter.Iterator, key string) bool {
|
||||
v, err := value.ReadJSONIter(iter)
|
||||
if err != nil {
|
||||
iter.Error = err
|
||||
return false
|
||||
}
|
||||
fields = append(fields, value.Field{Name: key, Value: v})
|
||||
return true
|
||||
})
|
||||
fields.Sort()
|
||||
return PathElement{Key: &fields}, iter.Error
|
||||
case peIndexSepBytes[0]:
|
||||
i, err := strconv.Atoi(s[2:])
|
||||
if err != nil {
|
||||
return PathElement{}, err
|
||||
}
|
||||
return PathElement{
|
||||
Index: &i,
|
||||
}, nil
|
||||
default:
|
||||
return PathElement{}, ErrUnknownPathElementType
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
readPool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()
|
||||
writePool = jsoniter.NewStream(jsoniter.ConfigCompatibleWithStandardLibrary, nil, 1024).Pool()
|
||||
)
|
||||
|
||||
// SerializePathElement serializes a path element
|
||||
func SerializePathElement(pe PathElement) (string, error) {
|
||||
buf := strings.Builder{}
|
||||
err := serializePathElementToWriter(&buf, pe)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func serializePathElementToWriter(w io.Writer, pe PathElement) error {
|
||||
stream := writePool.BorrowStream(w)
|
||||
defer writePool.ReturnStream(stream)
|
||||
switch {
|
||||
case pe.FieldName != nil:
|
||||
if _, err := stream.Write(peFieldSepBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteRaw(*pe.FieldName)
|
||||
case pe.Key != nil:
|
||||
if _, err := stream.Write(peKeySepBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectStart()
|
||||
for i, field := range *pe.Key {
|
||||
if i > 0 {
|
||||
stream.WriteMore()
|
||||
}
|
||||
stream.WriteObjectField(field.Name)
|
||||
field.Value.WriteJSONStream(stream)
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
case pe.Value != nil:
|
||||
if _, err := stream.Write(peValueSepBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
pe.Value.WriteJSONStream(stream)
|
||||
case pe.Index != nil:
|
||||
if _, err := stream.Write(peIndexSepBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteInt(*pe.Index)
|
||||
default:
|
||||
return errors.New("invalid PathElement")
|
||||
}
|
||||
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 err
|
||||
}
|
||||
237
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/serialize.go
generated
vendored
Normal file
237
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/serialize.go
generated
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
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 fieldpath
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"unsafe"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func (s *Set) ToJSON() ([]byte, error) {
|
||||
buf := bytes.Buffer{}
|
||||
err := s.ToJSONStream(&buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (s *Set) ToJSONStream(w io.Writer) error {
|
||||
stream := writePool.BorrowStream(w)
|
||||
defer writePool.ReturnStream(stream)
|
||||
|
||||
var r reusableBuilder
|
||||
|
||||
stream.WriteObjectStart()
|
||||
err := s.emitContents_v1(false, stream, &r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
return stream.Flush()
|
||||
}
|
||||
|
||||
func manageMemory(stream *jsoniter.Stream) error {
|
||||
// Help jsoniter manage its buffers--without this, it does a bunch of
|
||||
// alloctaions that are not necessary. They were probably optimizing
|
||||
// for folks using the buffer directly.
|
||||
b := stream.Buffer()
|
||||
if len(b) > 4096 || cap(b)-len(b) < 2048 {
|
||||
if err := stream.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.SetBuffer(b[:0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type reusableBuilder struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
func (r *reusableBuilder) unsafeString() string {
|
||||
b := r.Bytes()
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
func (r *reusableBuilder) reset() *bytes.Buffer {
|
||||
r.Reset()
|
||||
return &r.Buffer
|
||||
}
|
||||
|
||||
func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error {
|
||||
mi, ci := 0, 0
|
||||
first := true
|
||||
preWrite := func() {
|
||||
if first {
|
||||
first = false
|
||||
return
|
||||
}
|
||||
stream.WriteMore()
|
||||
}
|
||||
|
||||
for mi < len(s.Members.members) && ci < len(s.Children.members) {
|
||||
mpe := s.Members.members[mi]
|
||||
cpe := s.Children.members[ci].pathElement
|
||||
|
||||
if mpe.Less(cpe) {
|
||||
preWrite()
|
||||
if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectField(r.unsafeString())
|
||||
stream.WriteEmptyObject()
|
||||
mi++
|
||||
} else if cpe.Less(mpe) {
|
||||
preWrite()
|
||||
if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectField(r.unsafeString())
|
||||
stream.WriteObjectStart()
|
||||
if err := s.Children.members[ci].set.emitContents_v1(false, stream, r); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
ci++
|
||||
} else {
|
||||
preWrite()
|
||||
if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectField(r.unsafeString())
|
||||
stream.WriteObjectStart()
|
||||
if err := s.Children.members[ci].set.emitContents_v1(true, stream, r); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
mi++
|
||||
ci++
|
||||
}
|
||||
}
|
||||
|
||||
for mi < len(s.Members.members) {
|
||||
mpe := s.Members.members[mi]
|
||||
|
||||
preWrite()
|
||||
if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectField(r.unsafeString())
|
||||
stream.WriteEmptyObject()
|
||||
mi++
|
||||
}
|
||||
|
||||
for ci < len(s.Children.members) {
|
||||
cpe := s.Children.members[ci].pathElement
|
||||
|
||||
preWrite()
|
||||
if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectField(r.unsafeString())
|
||||
stream.WriteObjectStart()
|
||||
if err := s.Children.members[ci].set.emitContents_v1(false, stream, r); err != nil {
|
||||
return err
|
||||
}
|
||||
stream.WriteObjectEnd()
|
||||
ci++
|
||||
}
|
||||
|
||||
if includeSelf && !first {
|
||||
preWrite()
|
||||
stream.WriteObjectField(".")
|
||||
stream.WriteEmptyObject()
|
||||
}
|
||||
return manageMemory(stream)
|
||||
}
|
||||
|
||||
// FromJSON clears s and reads a JSON formatted set structure.
|
||||
func (s *Set) FromJSON(r io.Reader) error {
|
||||
// The iterator pool is completely useless for memory management, grrr.
|
||||
iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, r, 4096)
|
||||
|
||||
found, _ := readIter_v1(iter)
|
||||
if found == nil {
|
||||
*s = Set{}
|
||||
} else {
|
||||
*s = *found
|
||||
}
|
||||
return iter.Error
|
||||
}
|
||||
|
||||
// returns true if this subtree is also (or only) a member of parent; s is nil
|
||||
// if there are no further children.
|
||||
func readIter_v1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
|
||||
iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool {
|
||||
if key == "." {
|
||||
isMember = true
|
||||
iter.Skip()
|
||||
return true
|
||||
}
|
||||
pe, err := DeserializePathElement(key)
|
||||
if err == ErrUnknownPathElementType {
|
||||
// Ignore these-- a future version maybe knows what
|
||||
// they are. We drop these completely rather than try
|
||||
// to preserve things we don't understand.
|
||||
iter.Skip()
|
||||
return true
|
||||
} else if err != nil {
|
||||
iter.ReportError("parsing key as path element", err.Error())
|
||||
iter.Skip()
|
||||
return true
|
||||
}
|
||||
grandchildren, childIsMember := readIter_v1(iter)
|
||||
if childIsMember {
|
||||
if children == nil {
|
||||
children = &Set{}
|
||||
}
|
||||
m := &children.Members.members
|
||||
// Since we expect that most of the time these will have been
|
||||
// serialized in the right order, we just verify that and append.
|
||||
appendOK := len(*m) == 0 || (*m)[len(*m)-1].Less(pe)
|
||||
if appendOK {
|
||||
*m = append(*m, pe)
|
||||
} else {
|
||||
children.Members.Insert(pe)
|
||||
}
|
||||
}
|
||||
if grandchildren != nil {
|
||||
if children == nil {
|
||||
children = &Set{}
|
||||
}
|
||||
// Since we expect that most of the time these will have been
|
||||
// serialized in the right order, we just verify that and append.
|
||||
m := &children.Children.members
|
||||
appendOK := len(*m) == 0 || (*m)[len(*m)-1].pathElement.Less(pe)
|
||||
if appendOK {
|
||||
*m = append(*m, setNode{pe, grandchildren})
|
||||
} else {
|
||||
*children.Children.Descend(pe) = *grandchildren
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if children == nil {
|
||||
isMember = true
|
||||
}
|
||||
|
||||
return children, isMember
|
||||
}
|
||||
131
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/set.go
generated
vendored
131
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/set.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package fieldpath
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -172,24 +173,33 @@ type setNode struct {
|
|||
|
||||
// SetNodeMap is a map of PathElement to subset.
|
||||
type SetNodeMap struct {
|
||||
members map[string]setNode
|
||||
members sortedSetNode
|
||||
}
|
||||
|
||||
type sortedSetNode []setNode
|
||||
|
||||
// Implement the sort interface; this would permit bulk creation, which would
|
||||
// be faster than doing it one at a time via Insert.
|
||||
func (s sortedSetNode) Len() int { return len(s) }
|
||||
func (s sortedSetNode) Less(i, j int) bool { return s[i].pathElement.Less(s[j].pathElement) }
|
||||
func (s sortedSetNode) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// Descend adds pe to the set if necessary, returning the associated subset.
|
||||
func (s *SetNodeMap) Descend(pe PathElement) *Set {
|
||||
serialized := pe.String()
|
||||
if s.members == nil {
|
||||
s.members = map[string]setNode{}
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].pathElement.Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
s.members = append(s.members, setNode{pathElement: pe, set: &Set{}})
|
||||
return s.members[loc].set
|
||||
}
|
||||
if n, ok := s.members[serialized]; ok {
|
||||
return n.set
|
||||
if s.members[loc].pathElement.Equals(pe) {
|
||||
return s.members[loc].set
|
||||
}
|
||||
ss := &Set{}
|
||||
s.members[serialized] = setNode{
|
||||
pathElement: pe,
|
||||
set: ss,
|
||||
}
|
||||
return ss
|
||||
s.members = append(s.members, setNode{})
|
||||
copy(s.members[loc+1:], s.members[loc:])
|
||||
s.members[loc] = setNode{pathElement: pe, set: &Set{}}
|
||||
return s.members[loc].set
|
||||
}
|
||||
|
||||
// Size returns the sum of the number of members of all subsets.
|
||||
|
|
@ -213,12 +223,14 @@ func (s *SetNodeMap) Empty() bool {
|
|||
|
||||
// Get returns (the associated set, true) or (nil, false) if there is none.
|
||||
func (s *SetNodeMap) Get(pe PathElement) (*Set, bool) {
|
||||
if s.members == nil {
|
||||
loc := sort.Search(len(s.members), func(i int) bool {
|
||||
return !s.members[i].pathElement.Less(pe)
|
||||
})
|
||||
if loc == len(s.members) {
|
||||
return nil, false
|
||||
}
|
||||
serialized := pe.String()
|
||||
if n, ok := s.members[serialized]; ok {
|
||||
return n.set, true
|
||||
if s.members[loc].pathElement.Equals(pe) {
|
||||
return s.members[loc].set, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
|
@ -229,12 +241,11 @@ func (s *SetNodeMap) Equals(s2 *SetNodeMap) bool {
|
|||
if len(s.members) != len(s2.members) {
|
||||
return false
|
||||
}
|
||||
for k, v := range s.members {
|
||||
v2, ok := s2.members[k]
|
||||
if !ok {
|
||||
for i := range s.members {
|
||||
if !s.members[i].pathElement.Equals(s2.members[i].pathElement) {
|
||||
return false
|
||||
}
|
||||
if !v.set.Equals(v2.set) {
|
||||
if !s.members[i].set.Equals(s2.members[i].set) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
@ -244,21 +255,28 @@ func (s *SetNodeMap) Equals(s2 *SetNodeMap) bool {
|
|||
// Union returns a SetNodeMap with members that appear in either s or s2.
|
||||
func (s *SetNodeMap) Union(s2 *SetNodeMap) *SetNodeMap {
|
||||
out := &SetNodeMap{}
|
||||
for k, sn := range s.members {
|
||||
pe := sn.pathElement
|
||||
if sn2, ok := s2.members[k]; ok {
|
||||
*out.Descend(pe) = *sn.set.Union(sn2.set)
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.members) {
|
||||
if s.members[i].pathElement.Less(s2.members[j].pathElement) {
|
||||
out.members = append(out.members, s.members[i])
|
||||
i++
|
||||
} else {
|
||||
*out.Descend(pe) = *sn.set
|
||||
if !s2.members[j].pathElement.Less(s.members[i].pathElement) {
|
||||
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set.Union(s2.members[j].set)})
|
||||
i++
|
||||
} else {
|
||||
out.members = append(out.members, s2.members[j])
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
for k, sn2 := range s2.members {
|
||||
pe := sn2.pathElement
|
||||
if _, ok := s.members[k]; ok {
|
||||
// already handled
|
||||
continue
|
||||
}
|
||||
*out.Descend(pe) = *sn2.set
|
||||
|
||||
if i < len(s.members) {
|
||||
out.members = append(out.members, s.members[i:]...)
|
||||
}
|
||||
if j < len(s2.members) {
|
||||
out.members = append(out.members, s2.members[j:]...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
@ -266,13 +284,20 @@ func (s *SetNodeMap) Union(s2 *SetNodeMap) *SetNodeMap {
|
|||
// Intersection returns a SetNodeMap with members that appear in both s and s2.
|
||||
func (s *SetNodeMap) Intersection(s2 *SetNodeMap) *SetNodeMap {
|
||||
out := &SetNodeMap{}
|
||||
for k, sn := range s.members {
|
||||
pe := sn.pathElement
|
||||
if sn2, ok := s2.members[k]; ok {
|
||||
i := *sn.set.Intersection(sn2.set)
|
||||
if !i.Empty() {
|
||||
*out.Descend(pe) = i
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.members) {
|
||||
if s.members[i].pathElement.Less(s2.members[j].pathElement) {
|
||||
i++
|
||||
} else {
|
||||
if !s2.members[j].pathElement.Less(s.members[i].pathElement) {
|
||||
res := s.members[i].set.Intersection(s2.members[j].set)
|
||||
if !res.Empty() {
|
||||
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: res})
|
||||
}
|
||||
i++
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
|
@ -281,18 +306,30 @@ func (s *SetNodeMap) Intersection(s2 *SetNodeMap) *SetNodeMap {
|
|||
// Difference returns a SetNodeMap with members that appear in s but not in s2.
|
||||
func (s *SetNodeMap) Difference(s2 *Set) *SetNodeMap {
|
||||
out := &SetNodeMap{}
|
||||
for k, sn := range s.members {
|
||||
pe := sn.pathElement
|
||||
if sn2, ok := s2.Children.members[k]; ok {
|
||||
diff := *sn.set.Difference(sn2.set)
|
||||
// We aren't permitted to add nodes with no elements.
|
||||
if !diff.Empty() {
|
||||
*out.Descend(pe) = diff
|
||||
}
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(s.members) && j < len(s2.Children.members) {
|
||||
if s.members[i].pathElement.Less(s2.Children.members[j].pathElement) {
|
||||
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: s.members[i].set})
|
||||
i++
|
||||
} else {
|
||||
*out.Descend(pe) = *sn.set
|
||||
if !s2.Children.members[j].pathElement.Less(s.members[i].pathElement) {
|
||||
|
||||
diff := s.members[i].set.Difference(s2.Children.members[j].set)
|
||||
// We aren't permitted to add nodes with no elements.
|
||||
if !diff.Empty() {
|
||||
out.members = append(out.members, setNode{pathElement: s.members[i].pathElement, set: diff})
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
if i < len(s.members) {
|
||||
out.members = append(out.members, s.members[i:]...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue