Skip to content

Commit cf335e0

Browse files
authored
Merge pull request #129 from apelisse/perf/new-value-rebased
Perf/new value rebased
2 parents fda0dd5 + 53b71b4 commit cf335e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1769
-1879
lines changed

fieldpath/element.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type PathElement struct {
3434

3535
// Key selects the list element which has fields matching those given.
3636
// The containing object must be an associative list with map typed
37-
// elements.
37+
// elements. They are sorted alphabetically.
3838
Key *value.FieldList
3939

4040
// Value selects the list element with the given value. The containing
@@ -71,7 +71,7 @@ func (e PathElement) Less(rhs PathElement) bool {
7171
if rhs.Value == nil {
7272
return true
7373
}
74-
return e.Value.Less(*rhs.Value)
74+
return value.Less(*e.Value, *rhs.Value)
7575
} else if rhs.Value != nil {
7676
return false
7777
}
@@ -103,12 +103,12 @@ func (e PathElement) String() string {
103103
case e.Key != nil:
104104
strs := make([]string, len(*e.Key))
105105
for i, k := range *e.Key {
106-
strs[i] = fmt.Sprintf("%v=%v", k.Name, k.Value)
106+
strs[i] = fmt.Sprintf("%v=%v", k.Name, value.ToString(k.Value))
107107
}
108108
// Keys are supposed to be sorted.
109109
return "[" + strings.Join(strs, ",") + "]"
110110
case e.Value != nil:
111-
return fmt.Sprintf("[=%v]", e.Value)
111+
return fmt.Sprintf("[=%v]", value.ToString(*e.Value))
112112
case e.Index != nil:
113113
return fmt.Sprintf("[%v]", *e.Index)
114114
default:
@@ -127,10 +127,7 @@ func KeyByFields(nameValues ...interface{}) *value.FieldList {
127127
}
128128
out := value.FieldList{}
129129
for i := 0; i < len(nameValues)-1; i += 2 {
130-
out = append(out, value.Field{
131-
Name: nameValues[i].(string),
132-
Value: nameValues[i+1].(value.Value),
133-
})
130+
out = append(out, value.Field{Name: nameValues[i].(string), Value: value.NewValueInterface(nameValues[i+1])})
134131
}
135132
out.Sort()
136133
return &out

fieldpath/element_test.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ func TestPathElementSet(t *testing.T) {
6262
})
6363
}
6464

65-
func strptr(s string) *string { return &s }
66-
func intptr(i int) *int { return &i }
67-
func valptr(i int) *value.Value { v := value.IntValue(i); return &v }
65+
func strptr(s string) *string { return &s }
66+
func intptr(i int) *int { return &i }
67+
func valptr(i interface{}) *value.Value {
68+
v := value.NewValueInterface(i)
69+
return &v
70+
}
6871

6972
func TestPathElementLess(t *testing.T) {
7073
table := []struct {
@@ -91,7 +94,7 @@ func TestPathElementLess(t *testing.T) {
9194
}, {
9295
name: "FieldName-3",
9396
a: PathElement{FieldName: strptr("capybara")},
94-
b: PathElement{Key: KeyByFields("dog", value.IntValue(3))},
97+
b: PathElement{Key: KeyByFields("dog", 3)},
9598
}, {
9699
name: "FieldName-4",
97100
a: PathElement{FieldName: strptr("elephant")},
@@ -102,28 +105,28 @@ func TestPathElementLess(t *testing.T) {
102105
b: PathElement{Index: intptr(5)},
103106
}, {
104107
name: "Key-1",
105-
a: PathElement{Key: KeyByFields("goat", value.IntValue(1))},
106-
b: PathElement{Key: KeyByFields("goat", value.IntValue(1))},
108+
a: PathElement{Key: KeyByFields("goat", 1)},
109+
b: PathElement{Key: KeyByFields("goat", 1)},
107110
eq: true,
108111
}, {
109112
name: "Key-2",
110-
a: PathElement{Key: KeyByFields("horse", value.IntValue(1))},
111-
b: PathElement{Key: KeyByFields("horse", value.IntValue(2))},
113+
a: PathElement{Key: KeyByFields("horse", 1)},
114+
b: PathElement{Key: KeyByFields("horse", 2)},
112115
}, {
113116
name: "Key-3",
114-
a: PathElement{Key: KeyByFields("ibex", value.IntValue(1))},
115-
b: PathElement{Key: KeyByFields("jay", value.IntValue(1))},
117+
a: PathElement{Key: KeyByFields("ibex", 1)},
118+
b: PathElement{Key: KeyByFields("jay", 1)},
116119
}, {
117120
name: "Key-4",
118-
a: PathElement{Key: KeyByFields("kite", value.IntValue(1))},
119-
b: PathElement{Key: KeyByFields("kite", value.IntValue(1), "kite-2", value.IntValue(1))},
121+
a: PathElement{Key: KeyByFields("kite", 1)},
122+
b: PathElement{Key: KeyByFields("kite", 1, "kite-2", 1)},
120123
}, {
121124
name: "Key-5",
122-
a: PathElement{Key: KeyByFields("kite", value.IntValue(1))},
125+
a: PathElement{Key: KeyByFields("kite", 1)},
123126
b: PathElement{Value: valptr(1)},
124127
}, {
125128
name: "Key-6",
126-
a: PathElement{Key: KeyByFields("kite", value.IntValue(1))},
129+
a: PathElement{Key: KeyByFields("kite", 1)},
127130
b: PathElement{Index: intptr(5)},
128131
}, {
129132
name: "Value-1",
@@ -156,15 +159,15 @@ func TestPathElementLess(t *testing.T) {
156159
tt := table[i]
157160
if tt.eq {
158161
if tt.a.Less(tt.b) {
159-
t.Errorf("oops, a < b: %#v, %#v", tt.a, tt.b)
162+
t.Errorf("oops, a < b: %#v (%v), %#v (%v)", tt.a, tt.a, tt.b, tt.b)
160163
}
161164
} else {
162165
if !tt.a.Less(tt.b) {
163-
t.Errorf("oops, a >= b: %#v, %#v", tt.a, tt.b)
166+
t.Errorf("oops, a >= b: %#v (%v), %#v (%v)", tt.a, tt.a, tt.b, tt.b)
164167
}
165168
}
166169
if tt.b.Less(tt.b) {
167-
t.Errorf("oops, b < a: %#v, %#v", tt.b, tt.a)
170+
t.Errorf("oops, b < a: %#v (%v), %#v (%v)", tt.b, tt.b, tt.a, tt.a)
168171
}
169172
})
170173
}

fieldpath/fromvalue.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,37 +43,37 @@ type objectWalker struct {
4343

4444
func (w *objectWalker) walk() {
4545
switch {
46-
case w.value.Null:
47-
case w.value.FloatValue != nil:
48-
case w.value.IntValue != nil:
49-
case w.value.StringValue != nil:
50-
case w.value.BooleanValue != nil:
46+
case w.value.IsNull():
47+
case w.value.IsFloat():
48+
case w.value.IsInt():
49+
case w.value.IsString():
50+
case w.value.IsBool():
5151
// All leaf fields handled the same way (after the switch
5252
// statement).
5353

5454
// Descend
55-
case w.value.ListValue != nil:
55+
case w.value.IsList():
5656
// If the list were atomic, we'd break here, but we don't have
5757
// a schema, so we can't tell.
58-
59-
for i, child := range w.value.ListValue.Items {
58+
list := w.value.List()
59+
for i := 0; i < list.Length(); i++ {
6060
w2 := *w
61-
w2.path = append(w.path, GuessBestListPathElement(i, child))
62-
w2.value = child
61+
w2.path = append(w.path, GuessBestListPathElement(i, list.At(i)))
62+
w2.value = list.At(i)
6363
w2.walk()
6464
}
6565
return
66-
case w.value.MapValue != nil:
66+
case w.value.IsMap():
6767
// If the map/struct were atomic, we'd break here, but we don't
6868
// have a schema, so we can't tell.
6969

70-
for i := range w.value.MapValue.Items {
71-
child := w.value.MapValue.Items[i]
70+
w.value.Map().Iterate(func(k string, val value.Value) bool {
7271
w2 := *w
73-
w2.path = append(w.path, PathElement{FieldName: &child.Name})
74-
w2.value = child.Value
72+
w2.path = append(w.path, PathElement{FieldName: &k})
73+
w2.value = val
7574
w2.walk()
76-
}
75+
return true
76+
})
7777
return
7878
}
7979

@@ -97,7 +97,7 @@ var AssociativeListCandidateFieldNames = []string{
9797
// whether item has any of the fields listed in
9898
// AssociativeListCandidateFieldNames which have scalar values.
9999
func GuessBestListPathElement(index int, item value.Value) PathElement {
100-
if item.MapValue == nil {
100+
if !item.IsMap() {
101101
// Non map items could be parts of sets or regular "atomic"
102102
// lists. We won't try to guess whether something should be a
103103
// set or not.
@@ -106,15 +106,15 @@ func GuessBestListPathElement(index int, item value.Value) PathElement {
106106

107107
var keys value.FieldList
108108
for _, name := range AssociativeListCandidateFieldNames {
109-
f, ok := item.MapValue.Get(name)
109+
f, ok := item.Map().Get(name)
110110
if !ok {
111111
continue
112112
}
113113
// only accept primitive/scalar types as keys.
114-
if f.Value.Null || f.Value.MapValue != nil || f.Value.ListValue != nil {
114+
if f.IsNull() || f.IsMap() || f.IsList() {
115115
continue
116116
}
117-
keys = append(keys, *f)
117+
keys = append(keys, value.Field{Name: name, Value: f})
118118
}
119119
if len(keys) > 0 {
120120
keys.Sort()

fieldpath/fromvalue_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package fieldpath
1919
import (
2020
"testing"
2121

22+
"gopkg.in/yaml.v2"
2223
"sigs.k8s.io/structured-merge-diff/value"
2324
)
2425

@@ -31,19 +32,19 @@ func TestFromValue(t *testing.T) {
3132
{`{"a": [{"a": null}]}`, NewSet(
3233
MakePathOrDie("a", 0, "a"),
3334
)}, {`{"a": [{"id": a}]}`, NewSet(
34-
MakePathOrDie("a", KeyByFields("id", value.StringValue("a")), "id"),
35+
MakePathOrDie("a", KeyByFields("id", "a"), "id"),
3536
)}, {`{"a": [{"name": a}]}`, NewSet(
36-
MakePathOrDie("a", KeyByFields("name", value.StringValue("a")), "name"),
37+
MakePathOrDie("a", KeyByFields("name", "a"), "name"),
3738
)}, {`{"a": [{"key": a}]}`, NewSet(
38-
MakePathOrDie("a", KeyByFields("key", value.StringValue("a")), "key"),
39+
MakePathOrDie("a", KeyByFields("key", "a"), "key"),
3940
)}, {`{"a": [{"name": "a", "key": "b"}]}`, NewSet(
4041
MakePathOrDie("a", KeyByFields(
41-
"key", value.StringValue("b"),
42-
"name", value.StringValue("a"),
42+
"key", "b",
43+
"name", "a",
4344
), "key"),
4445
MakePathOrDie("a", KeyByFields(
45-
"key", value.StringValue("b"),
46-
"name", value.StringValue("a"),
46+
"key", "b",
47+
"name", "a",
4748
), "name"),
4849
)}, {`{"a": [5]}`, NewSet(
4950
MakePathOrDie("a", 0),
@@ -65,11 +66,12 @@ func TestFromValue(t *testing.T) {
6566
tt := tt
6667
t.Run(tt.objYAML, func(t *testing.T) {
6768
t.Parallel()
68-
v, err := value.FromYAML([]byte(tt.objYAML))
69+
var v interface{}
70+
err := yaml.Unmarshal([]byte(tt.objYAML), &v)
6971
if err != nil {
7072
t.Fatalf("couldn't parse: %v", err)
7173
}
72-
got := SetFromValue(v)
74+
got := SetFromValue(value.NewValueInterface(v))
7375
if !got.Equals(tt.set) {
7476
t.Errorf("wanted\n%s\nbut got\n%s\n", tt.set, got)
7577
}

fieldpath/managers.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ limitations under the License.
1313

1414
package fieldpath
1515

16+
import (
17+
"fmt"
18+
"strings"
19+
)
20+
1621
// APIVersion describes the version of an object or of a fieldset.
1722
type APIVersion string
1823

@@ -95,3 +100,14 @@ func (lhs ManagedFields) Difference(rhs ManagedFields) ManagedFields {
95100

96101
return diff
97102
}
103+
104+
func (lhs ManagedFields) String() string {
105+
s := strings.Builder{}
106+
for k, v := range lhs {
107+
fmt.Fprintf(&s, "%s:\n", k)
108+
fmt.Fprintf(&s, "- Applied: %v\n", v.Applied())
109+
fmt.Fprintf(&s, "- APIVersion: %v\n", v.APIVersion())
110+
fmt.Fprintf(&s, "- Set: %v\n", v.Set())
111+
}
112+
return s.String()
113+
}

fieldpath/path_test.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import (
2222
"sigs.k8s.io/structured-merge-diff/value"
2323
)
2424

25+
var (
26+
_V = value.NewValueInterface
27+
)
28+
2529
func TestPathString(t *testing.T) {
2630
table := []struct {
2731
name string
@@ -31,16 +35,20 @@ func TestPathString(t *testing.T) {
3135
{"basic1", MakePathOrDie("foo", 1), ".foo[1]"},
3236
{"basic2", MakePathOrDie("foo", "bar", 1, "baz"), ".foo.bar[1].baz"},
3337
{"associative-list-ref", MakePathOrDie("foo", KeyByFields(
34-
"a", value.StringValue("b"),
35-
"c", value.IntValue(1),
36-
"d", value.FloatValue(1.5),
37-
"e", value.BooleanValue(true),
38+
// This makes sure we test all types: string,
39+
// floats, integers and booleans.
40+
"a", "b",
41+
"c", 1,
42+
"d", 1.5,
43+
"e", true,
3844
)), `.foo[a="b",c=1,d=1.5,e=true]`},
3945
{"sets", MakePathOrDie("foo",
40-
value.StringValue("b"),
41-
value.IntValue(5),
42-
value.BooleanValue(false),
43-
value.FloatValue(3.14159),
46+
// This makes sure we test all types: string,
47+
// floats, integers and booleans.
48+
_V("b"),
49+
_V(5),
50+
_V(false),
51+
_V(3.14159),
4452
), `.foo[="b"][=5][=false][=3.14159]`},
4553
}
4654
for _, tt := range table {

fieldpath/pathelementmap.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ func (s *PathElementValueMap) Get(pe PathElement) (value.Value, bool) {
7676
return !s.members[i].PathElement.Less(pe)
7777
})
7878
if loc == len(s.members) {
79-
return value.Value{}, false
79+
return nil, false
8080
}
8181
if s.members[loc].PathElement.Equals(pe) {
8282
return s.members[loc].Value, true
8383
}
84-
return value.Value{}, false
84+
return nil, false
8585
}

fieldpath/pathelementmap_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@ func TestPathElementValueMap(t *testing.T) {
2929
t.Fatal("Unexpected path-element found in empty map")
3030
}
3131

32-
m.Insert(PathElement{FieldName: strptr("carrot")}, value.StringValue("knife"))
33-
m.Insert(PathElement{FieldName: strptr("chive")}, value.IntValue(2))
32+
m.Insert(PathElement{FieldName: strptr("carrot")}, value.NewValueInterface("knife"))
33+
m.Insert(PathElement{FieldName: strptr("chive")}, value.NewValueInterface(2))
3434

3535
if _, ok := m.Get(PathElement{FieldName: strptr("onion")}); ok {
3636
t.Fatal("Unexpected path-element in map")
3737
}
3838

3939
if val, ok := m.Get(PathElement{FieldName: strptr("carrot")}); !ok {
4040
t.Fatal("Missing path-element in map")
41-
} else if !val.Equals(value.StringValue("knife")) {
41+
} else if !value.Equals(val, value.NewValueInterface("knife")) {
4242
t.Fatalf("Unexpected value found: %#v", val)
4343
}
4444

4545
if val, ok := m.Get(PathElement{FieldName: strptr("chive")}); !ok {
4646
t.Fatal("Missing path-element in map")
47-
} else if !val.Equals(value.IntValue(2)) {
47+
} else if !value.Equals(val, value.NewValueInterface(2)) {
4848
t.Fatalf("Unexpected value found: %#v", val)
4949
}
5050
}

fieldpath/serialize-pe.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func DeserializePathElement(s string) (PathElement, error) {
8484
iter := readPool.BorrowIterator(b)
8585
defer readPool.ReturnIterator(iter)
8686
fields := value.FieldList{}
87+
8788
iter.ReadObjectCB(func(iter *jsoniter.Iterator, key string) bool {
8889
v, err := value.ReadJSONIter(iter)
8990
if err != nil {
@@ -134,19 +135,20 @@ func serializePathElementToWriter(w io.Writer, pe PathElement) error {
134135
return err
135136
}
136137
stream.WriteObjectStart()
138+
137139
for i, field := range *pe.Key {
138140
if i > 0 {
139141
stream.WriteMore()
140142
}
141143
stream.WriteObjectField(field.Name)
142-
field.Value.WriteJSONStream(stream)
144+
value.WriteJSONStream(field.Value, stream)
143145
}
144146
stream.WriteObjectEnd()
145147
case pe.Value != nil:
146148
if _, err := stream.Write(peValueSepBytes); err != nil {
147149
return err
148150
}
149-
pe.Value.WriteJSONStream(stream)
151+
value.WriteJSONStream(*pe.Value, stream)
150152
case pe.Index != nil:
151153
if _, err := stream.Write(peIndexSepBytes); err != nil {
152154
return err

0 commit comments

Comments
 (0)