...
1
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
53
54
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
168 func (s *Set) FromJSON(r io.Reader) error {
169
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
182
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
193
194
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
209
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
222
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