123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- 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.emitContentsV1(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) emitContentsV1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error {
- mi, ci := 0, 0
- first := true
- preWrite := func() {
- if first {
- first = false
- return
- }
- stream.WriteMore()
- }
- if includeSelf && !(len(s.Members.members) == 0 && len(s.Children.members) == 0) {
- preWrite()
- stream.WriteObjectField(".")
- stream.WriteEmptyObject()
- }
- for mi < len(s.Members.members) && ci < len(s.Children.members) {
- mpe := s.Members.members[mi]
- cpe := s.Children.members[ci].pathElement
- if c := mpe.Compare(cpe); c < 0 {
- preWrite()
- if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
- return err
- }
- stream.WriteObjectField(r.unsafeString())
- stream.WriteEmptyObject()
- mi++
- } else if c > 0 {
- preWrite()
- if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
- return err
- }
- stream.WriteObjectField(r.unsafeString())
- stream.WriteObjectStart()
- if err := s.Children.members[ci].set.emitContentsV1(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.emitContentsV1(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.emitContentsV1(false, stream, r); err != nil {
- return err
- }
- stream.WriteObjectEnd()
- ci++
- }
- 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, _ := readIterV1(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 readIterV1(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 := readIterV1(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
- }
|