...

Source file src/sigs.k8s.io/structured-merge-diff/v4/fieldpath/serialize.go

Documentation: sigs.k8s.io/structured-merge-diff/v4/fieldpath

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fieldpath
    18  
    19  import (
    20  	"bytes"
    21  	"io"
    22  	"unsafe"
    23  
    24  	jsoniter "github.com/json-iterator/go"
    25  )
    26  
    27  func (s *Set) ToJSON() ([]byte, error) {
    28  	buf := bytes.Buffer{}
    29  	err := s.ToJSONStream(&buf)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	return buf.Bytes(), nil
    34  }
    35  
    36  func (s *Set) ToJSONStream(w io.Writer) error {
    37  	stream := writePool.BorrowStream(w)
    38  	defer writePool.ReturnStream(stream)
    39  
    40  	var r reusableBuilder
    41  
    42  	stream.WriteObjectStart()
    43  	err := s.emitContentsV1(false, stream, &r)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	stream.WriteObjectEnd()
    48  	return stream.Flush()
    49  }
    50  
    51  func manageMemory(stream *jsoniter.Stream) error {
    52  	// Help jsoniter manage its buffers--without this, it does a bunch of
    53  	// alloctaions that are not necessary. They were probably optimizing
    54  	// for folks using the buffer directly.
    55  	b := stream.Buffer()
    56  	if len(b) > 4096 || cap(b)-len(b) < 2048 {
    57  		if err := stream.Flush(); err != nil {
    58  			return err
    59  		}
    60  		stream.SetBuffer(b[:0])
    61  	}
    62  	return nil
    63  }
    64  
    65  type reusableBuilder struct {
    66  	bytes.Buffer
    67  }
    68  
    69  func (r *reusableBuilder) unsafeString() string {
    70  	b := r.Bytes()
    71  	return *(*string)(unsafe.Pointer(&b))
    72  }
    73  
    74  func (r *reusableBuilder) reset() *bytes.Buffer {
    75  	r.Reset()
    76  	return &r.Buffer
    77  }
    78  
    79  func (s *Set) emitContentsV1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error {
    80  	mi, ci := 0, 0
    81  	first := true
    82  	preWrite := func() {
    83  		if first {
    84  			first = false
    85  			return
    86  		}
    87  		stream.WriteMore()
    88  	}
    89  
    90  	if includeSelf && !(len(s.Members.members) == 0 && len(s.Children.members) == 0) {
    91  		preWrite()
    92  		stream.WriteObjectField(".")
    93  		stream.WriteEmptyObject()
    94  	}
    95  
    96  	for mi < len(s.Members.members) && ci < len(s.Children.members) {
    97  		mpe := s.Members.members[mi]
    98  		cpe := s.Children.members[ci].pathElement
    99  
   100  		if c := mpe.Compare(cpe); c < 0 {
   101  			preWrite()
   102  			if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
   103  				return err
   104  			}
   105  			stream.WriteObjectField(r.unsafeString())
   106  			stream.WriteEmptyObject()
   107  			mi++
   108  		} else if c > 0 {
   109  			preWrite()
   110  			if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
   111  				return err
   112  			}
   113  			stream.WriteObjectField(r.unsafeString())
   114  			stream.WriteObjectStart()
   115  			if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil {
   116  				return err
   117  			}
   118  			stream.WriteObjectEnd()
   119  			ci++
   120  		} else {
   121  			preWrite()
   122  			if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
   123  				return err
   124  			}
   125  			stream.WriteObjectField(r.unsafeString())
   126  			stream.WriteObjectStart()
   127  			if err := s.Children.members[ci].set.emitContentsV1(true, stream, r); err != nil {
   128  				return err
   129  			}
   130  			stream.WriteObjectEnd()
   131  			mi++
   132  			ci++
   133  		}
   134  	}
   135  
   136  	for mi < len(s.Members.members) {
   137  		mpe := s.Members.members[mi]
   138  
   139  		preWrite()
   140  		if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
   141  			return err
   142  		}
   143  		stream.WriteObjectField(r.unsafeString())
   144  		stream.WriteEmptyObject()
   145  		mi++
   146  	}
   147  
   148  	for ci < len(s.Children.members) {
   149  		cpe := s.Children.members[ci].pathElement
   150  
   151  		preWrite()
   152  		if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
   153  			return err
   154  		}
   155  		stream.WriteObjectField(r.unsafeString())
   156  		stream.WriteObjectStart()
   157  		if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil {
   158  			return err
   159  		}
   160  		stream.WriteObjectEnd()
   161  		ci++
   162  	}
   163  
   164  	return manageMemory(stream)
   165  }
   166  
   167  // FromJSON clears s and reads a JSON formatted set structure.
   168  func (s *Set) FromJSON(r io.Reader) error {
   169  	// The iterator pool is completely useless for memory management, grrr.
   170  	iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, r, 4096)
   171  
   172  	found, _ := readIterV1(iter)
   173  	if found == nil {
   174  		*s = Set{}
   175  	} else {
   176  		*s = *found
   177  	}
   178  	return iter.Error
   179  }
   180  
   181  // returns true if this subtree is also (or only) a member of parent; s is nil
   182  // if there are no further children.
   183  func readIterV1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
   184  	iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool {
   185  		if key == "." {
   186  			isMember = true
   187  			iter.Skip()
   188  			return true
   189  		}
   190  		pe, err := DeserializePathElement(key)
   191  		if err == ErrUnknownPathElementType {
   192  			// Ignore these-- a future version maybe knows what
   193  			// they are. We drop these completely rather than try
   194  			// to preserve things we don't understand.
   195  			iter.Skip()
   196  			return true
   197  		} else if err != nil {
   198  			iter.ReportError("parsing key as path element", err.Error())
   199  			iter.Skip()
   200  			return true
   201  		}
   202  		grandchildren, childIsMember := readIterV1(iter)
   203  		if childIsMember {
   204  			if children == nil {
   205  				children = &Set{}
   206  			}
   207  			m := &children.Members.members
   208  			// Since we expect that most of the time these will have been
   209  			// serialized in the right order, we just verify that and append.
   210  			appendOK := len(*m) == 0 || (*m)[len(*m)-1].Less(pe)
   211  			if appendOK {
   212  				*m = append(*m, pe)
   213  			} else {
   214  				children.Members.Insert(pe)
   215  			}
   216  		}
   217  		if grandchildren != nil {
   218  			if children == nil {
   219  				children = &Set{}
   220  			}
   221  			// Since we expect that most of the time these will have been
   222  			// serialized in the right order, we just verify that and append.
   223  			m := &children.Children.members
   224  			appendOK := len(*m) == 0 || (*m)[len(*m)-1].pathElement.Less(pe)
   225  			if appendOK {
   226  				*m = append(*m, setNode{pe, grandchildren})
   227  			} else {
   228  				*children.Children.Descend(pe) = *grandchildren
   229  			}
   230  		}
   231  		return true
   232  	})
   233  	if children == nil {
   234  		isMember = true
   235  	}
   236  
   237  	return children, isMember
   238  }
   239  

View as plain text