Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions fieldpath/serialize-pe.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io"
"strconv"
"strings"
"unsafe"

jsoniter "github.com/json-iterator/go"
"sigs.k8s.io/structured-merge-diff/value"
Expand Down Expand Up @@ -55,20 +56,18 @@ var (
)

// DeserializePathElement parses a serialized path element
func DeserializePathElement(s string) (PathElement, error) {
b := []byte(s)
func DeserializePathElement(b []byte) (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)
return PathElement{}, fmt.Errorf("missing colon: %s", b)
}
switch typeSep[0] {
case peFieldSepBytes[0]:
// Slice s rather than convert b, to save on
// allocations.
str := s[2:]
str := string(b)
return PathElement{
FieldName: &str,
}, nil
Expand All @@ -92,7 +91,7 @@ func DeserializePathElement(s string) (PathElement, error) {
}
return PathElement{Key: v.MapValue}, nil
case peIndexSepBytes[0]:
i, err := strconv.Atoi(s[2:])
i, err := strconv.Atoi(*(*string)(unsafe.Pointer(&b)))
if err != nil {
return PathElement{}, err
}
Expand Down
6 changes: 3 additions & 3 deletions fieldpath/serialize-pe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestPathElementRoundTrip(t *testing.T) {

for _, test := range tests {
t.Run(test, func(t *testing.T) {
pe, err := DeserializePathElement(test)
pe, err := DeserializePathElement([]byte(test))
if err != nil {
t.Fatalf("Failed to create path element: %v", err)
}
Expand All @@ -54,7 +54,7 @@ func TestPathElementRoundTrip(t *testing.T) {
}

func TestPathElementIgnoreUnknown(t *testing.T) {
_, err := DeserializePathElement("r:Hello")
_, err := DeserializePathElement([]byte("r:Hello"))
if err != ErrUnknownPathElementType {
t.Fatalf("Unknown qualifiers must not return an invalid path element")
}
Expand All @@ -75,7 +75,7 @@ func TestDeserializePathElementError(t *testing.T) {

for _, test := range tests {
t.Run(test, func(t *testing.T) {
pe, err := DeserializePathElement(test)
pe, err := DeserializePathElement([]byte(test))
if err == nil {
t.Fatalf("Expected error, no error found. got: %#v, %s", pe, pe)
}
Expand Down
19 changes: 10 additions & 9 deletions fieldpath/serialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reus
}

// 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)
func (s *Set) FromJSON(b []byte) error {
iter := readPool.BorrowIterator(b)
defer readPool.ReturnIterator(iter)

found, _ := readIter_v1(iter)
found, _, _ := readIter_v1(iter, nil)
if found == nil {
*s = Set{}
} else {
Expand All @@ -179,9 +179,9 @@ func (s *Set) FromJSON(r io.Reader) 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 == "." {
func readIter_v1(iter *jsoniter.Iterator, buf []byte) (children *Set, isMember bool, bufout []byte) {
iter.ReadMapCBFieldAsBytes(buf, func(iter *jsoniter.Iterator, key []byte) bool {
if len(key) == 1 && key[0] == '.' {
isMember = true
iter.Skip()
return true
Expand All @@ -198,7 +198,8 @@ func readIter_v1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
iter.Skip()
return true
}
grandchildren, childIsMember := readIter_v1(iter)
grandchildren, childIsMember, key := readIter_v1(iter, key)
buf = key
if childIsMember {
if children == nil {
children = &Set{}
Expand Down Expand Up @@ -233,5 +234,5 @@ func readIter_v1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
isMember = true
}

return children, isMember
return children, isMember, buf
}
8 changes: 3 additions & 5 deletions fieldpath/serialize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ limitations under the License.
package fieldpath

import (
"bytes"
"fmt"
"strings"
"testing"
)

Expand All @@ -35,7 +33,7 @@ func TestSerializeV1(t *testing.T) {
continue
}
x2 := NewSet()
err = x2.FromJSON(bytes.NewReader(b))
err = x2.FromJSON(b)
if err != nil {
t.Errorf("Failed to deserialize %s: %v\n%#v", b, err, x)
}
Expand All @@ -54,7 +52,7 @@ func TestSerializeV1GoldenData(t *testing.T) {
for i, str := range examples {
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
x := NewSet()
err := x.FromJSON(strings.NewReader(str))
err := x.FromJSON([]byte(str))
if err != nil {
t.Errorf("Failed to deserialize %s: %v\n%#v", str, err, x)
}
Expand All @@ -74,7 +72,7 @@ func TestDropUnknown(t *testing.T) {
input := `{"f:aaa":{},"r:aab":{}}`
expect := `{"f:aaa":{}}`
x := NewSet()
err := x.FromJSON(strings.NewReader(input))
err := x.FromJSON([]byte(input))
if err != nil {
t.Errorf("Failed to deserialize %s: %v\n%#v", input, err, x)
}
Expand Down
3 changes: 1 addition & 2 deletions fieldpath/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package fieldpath

import (
"bytes"
"fmt"
"math/rand"
"testing"
Expand Down Expand Up @@ -111,7 +110,7 @@ func BenchmarkFieldSet(b *testing.B) {
b.ReportAllocs()
s := NewSet()
for i := 0; i < b.N; i++ {
s.FromJSON(bytes.NewReader(serialized[rand.Intn(len(serialized))]))
s.FromJSON(serialized[rand.Intn(len(serialized))])
}
})

Expand Down
2 changes: 1 addition & 1 deletion value/fastjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func ReadJSONIter(iter *jsoniter.Iterator) (Value, error) {
return Value{ListValue: list}, iter.Error
case jsoniter.ObjectValue:
m := &Map{}
iter.ReadObjectCB(func(iter *jsoniter.Iterator, key string) bool {
iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool {
v, err := ReadJSONIter(iter)
if err != nil {
iter.Error = err
Expand Down
7 changes: 4 additions & 3 deletions value/unstructured_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ func TestToFromJSON(t *testing.T) {
`[]`,
`{}`,
`{"a":[null,1.2],"b":"something"}`,
//`{"a\"":[null,1.2],"a\u2029oeu":"something"}`,
}

for i, j := range js {
Expand All @@ -176,7 +177,7 @@ func TestToFromJSON(t *testing.T) {
if err != nil {
t.Fatalf("failed to marshal into json: %v", err)
}
if !reflect.DeepEqual(j, string(o)) {
if j != string(o) {
t.Fatalf("Failed to round-trip.\ninput: %#v\noutput: %#v", j, string(o))
}
})
Expand All @@ -189,8 +190,8 @@ func TestToFromJSON(t *testing.T) {
if err != nil {
t.Fatalf("failed to marshal into json: %v", err)
}
if !reflect.DeepEqual(j, string(o)) {
t.Fatalf("Failed to round-trip.\ninput: %#v\noutput: %#v", j, string(o))
if j != string(o) {
t.Fatalf("Failed to round-trip.\ninput: %#v\noutput: %#v", j, string(o))
}
})
}
Expand Down