1
2
3
4
5
6
7 package bsonrw
8
9 import (
10 "errors"
11 "fmt"
12 "io"
13
14 "go.mongodb.org/mongo-driver/bson/bsontype"
15 "go.mongodb.org/mongo-driver/bson/primitive"
16 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
17 )
18
19
20
21
22
23
24 type Copier struct{}
25
26
27
28
29
30
31 func NewCopier() Copier {
32 return Copier{}
33 }
34
35
36
37
38
39 func CopyDocument(dst ValueWriter, src ValueReader) error {
40 return Copier{}.CopyDocument(dst, src)
41 }
42
43
44
45
46
47 func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
48 dr, err := src.ReadDocument()
49 if err != nil {
50 return err
51 }
52
53 dw, err := dst.WriteDocument()
54 if err != nil {
55 return err
56 }
57
58 return c.copyDocumentCore(dw, dr)
59 }
60
61
62
63
64
65
66 func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
67 aw, err := dst.WriteArray()
68 if err != nil {
69 return err
70 }
71
72 err = c.CopyBytesToArrayWriter(aw, src)
73 if err != nil {
74 return err
75 }
76
77 return aw.WriteArrayEnd()
78 }
79
80
81
82
83
84
85 func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
86 dw, err := dst.WriteDocument()
87 if err != nil {
88 return err
89 }
90
91 err = c.CopyBytesToDocumentWriter(dw, src)
92 if err != nil {
93 return err
94 }
95
96 return dw.WriteDocumentEnd()
97 }
98
99 type writeElementFn func(key string) (ValueWriter, error)
100
101
102
103
104
105
106 func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
107 wef := func(_ string) (ValueWriter, error) {
108 return dst.WriteArrayElement()
109 }
110
111 return c.copyBytesToValueWriter(src, wef)
112 }
113
114
115
116
117
118
119 func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
120 wef := func(key string) (ValueWriter, error) {
121 return dst.WriteDocumentElement(key)
122 }
123
124 return c.copyBytesToValueWriter(src, wef)
125 }
126
127 func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
128
129 length, rem, ok := bsoncore.ReadLength(src)
130 if !ok {
131 return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src))
132 }
133 if len(src) < int(length) {
134 return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length)
135 }
136 rem = rem[:length-4]
137
138 var t bsontype.Type
139 var key string
140 var val bsoncore.Value
141 for {
142 t, rem, ok = bsoncore.ReadType(rem)
143 if !ok {
144 return io.EOF
145 }
146 if t == bsontype.Type(0) {
147 if len(rem) != 0 {
148 return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem)
149 }
150 break
151 }
152
153 key, rem, ok = bsoncore.ReadKey(rem)
154 if !ok {
155 return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
156 }
157
158
159 vw, err := wef(key)
160 if err != nil {
161 return err
162 }
163
164 val, rem, ok = bsoncore.ReadValue(rem, t)
165 if !ok {
166 return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
167 }
168 err = c.CopyValueFromBytes(vw, t, val.Data)
169 if err != nil {
170 return err
171 }
172 }
173 return nil
174 }
175
176
177
178
179
180
181 func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) {
182 return c.AppendDocumentBytes(nil, src)
183 }
184
185
186
187
188
189
190 func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) {
191 if br, ok := src.(BytesReader); ok {
192 _, dst, err := br.ReadValueBytes(dst)
193 return dst, err
194 }
195
196 vw := vwPool.Get().(*valueWriter)
197 defer putValueWriter(vw)
198
199 vw.reset(dst)
200
201 err := c.CopyDocument(vw, src)
202 dst = vw.buf
203 return dst, err
204 }
205
206
207
208
209
210 func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
211 if br, ok := src.(BytesReader); ok {
212 _, dst, err := br.ReadValueBytes(dst)
213 return dst, err
214 }
215
216 vw := vwPool.Get().(*valueWriter)
217 defer putValueWriter(vw)
218
219 vw.reset(dst)
220
221 err := c.copyArray(vw, src)
222 dst = vw.buf
223 return dst, err
224 }
225
226
227
228
229 func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
230 if wvb, ok := dst.(BytesWriter); ok {
231 return wvb.WriteValueBytes(t, src)
232 }
233
234 vr := vrPool.Get().(*valueReader)
235 defer vrPool.Put(vr)
236
237 vr.reset(src)
238 vr.pushElement(t)
239
240 return c.CopyValue(dst, vr)
241 }
242
243
244
245
246
247 func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) {
248 return c.AppendValueBytes(nil, src)
249 }
250
251
252
253
254
255
256 func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) {
257 if br, ok := src.(BytesReader); ok {
258 return br.ReadValueBytes(dst)
259 }
260
261 vw := vwPool.Get().(*valueWriter)
262 defer putValueWriter(vw)
263
264 start := len(dst)
265
266 vw.reset(dst)
267 vw.push(mElement)
268
269 err := c.CopyValue(vw, src)
270 if err != nil {
271 return 0, dst, err
272 }
273
274 return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil
275 }
276
277
278
279
280
281 func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error {
282 var err error
283 switch src.Type() {
284 case bsontype.Double:
285 var f64 float64
286 f64, err = src.ReadDouble()
287 if err != nil {
288 break
289 }
290 err = dst.WriteDouble(f64)
291 case bsontype.String:
292 var str string
293 str, err = src.ReadString()
294 if err != nil {
295 return err
296 }
297 err = dst.WriteString(str)
298 case bsontype.EmbeddedDocument:
299 err = c.CopyDocument(dst, src)
300 case bsontype.Array:
301 err = c.copyArray(dst, src)
302 case bsontype.Binary:
303 var data []byte
304 var subtype byte
305 data, subtype, err = src.ReadBinary()
306 if err != nil {
307 break
308 }
309 err = dst.WriteBinaryWithSubtype(data, subtype)
310 case bsontype.Undefined:
311 err = src.ReadUndefined()
312 if err != nil {
313 break
314 }
315 err = dst.WriteUndefined()
316 case bsontype.ObjectID:
317 var oid primitive.ObjectID
318 oid, err = src.ReadObjectID()
319 if err != nil {
320 break
321 }
322 err = dst.WriteObjectID(oid)
323 case bsontype.Boolean:
324 var b bool
325 b, err = src.ReadBoolean()
326 if err != nil {
327 break
328 }
329 err = dst.WriteBoolean(b)
330 case bsontype.DateTime:
331 var dt int64
332 dt, err = src.ReadDateTime()
333 if err != nil {
334 break
335 }
336 err = dst.WriteDateTime(dt)
337 case bsontype.Null:
338 err = src.ReadNull()
339 if err != nil {
340 break
341 }
342 err = dst.WriteNull()
343 case bsontype.Regex:
344 var pattern, options string
345 pattern, options, err = src.ReadRegex()
346 if err != nil {
347 break
348 }
349 err = dst.WriteRegex(pattern, options)
350 case bsontype.DBPointer:
351 var ns string
352 var pointer primitive.ObjectID
353 ns, pointer, err = src.ReadDBPointer()
354 if err != nil {
355 break
356 }
357 err = dst.WriteDBPointer(ns, pointer)
358 case bsontype.JavaScript:
359 var js string
360 js, err = src.ReadJavascript()
361 if err != nil {
362 break
363 }
364 err = dst.WriteJavascript(js)
365 case bsontype.Symbol:
366 var symbol string
367 symbol, err = src.ReadSymbol()
368 if err != nil {
369 break
370 }
371 err = dst.WriteSymbol(symbol)
372 case bsontype.CodeWithScope:
373 var code string
374 var srcScope DocumentReader
375 code, srcScope, err = src.ReadCodeWithScope()
376 if err != nil {
377 break
378 }
379
380 var dstScope DocumentWriter
381 dstScope, err = dst.WriteCodeWithScope(code)
382 if err != nil {
383 break
384 }
385 err = c.copyDocumentCore(dstScope, srcScope)
386 case bsontype.Int32:
387 var i32 int32
388 i32, err = src.ReadInt32()
389 if err != nil {
390 break
391 }
392 err = dst.WriteInt32(i32)
393 case bsontype.Timestamp:
394 var t, i uint32
395 t, i, err = src.ReadTimestamp()
396 if err != nil {
397 break
398 }
399 err = dst.WriteTimestamp(t, i)
400 case bsontype.Int64:
401 var i64 int64
402 i64, err = src.ReadInt64()
403 if err != nil {
404 break
405 }
406 err = dst.WriteInt64(i64)
407 case bsontype.Decimal128:
408 var d128 primitive.Decimal128
409 d128, err = src.ReadDecimal128()
410 if err != nil {
411 break
412 }
413 err = dst.WriteDecimal128(d128)
414 case bsontype.MinKey:
415 err = src.ReadMinKey()
416 if err != nil {
417 break
418 }
419 err = dst.WriteMinKey()
420 case bsontype.MaxKey:
421 err = src.ReadMaxKey()
422 if err != nil {
423 break
424 }
425 err = dst.WriteMaxKey()
426 default:
427 err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type())
428 }
429
430 return err
431 }
432
433 func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
434 ar, err := src.ReadArray()
435 if err != nil {
436 return err
437 }
438
439 aw, err := dst.WriteArray()
440 if err != nil {
441 return err
442 }
443
444 for {
445 vr, err := ar.ReadValue()
446 if errors.Is(err, ErrEOA) {
447 break
448 }
449 if err != nil {
450 return err
451 }
452
453 vw, err := aw.WriteArrayElement()
454 if err != nil {
455 return err
456 }
457
458 err = c.CopyValue(vw, vr)
459 if err != nil {
460 return err
461 }
462 }
463
464 return aw.WriteArrayEnd()
465 }
466
467 func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
468 for {
469 key, vr, err := dr.ReadElement()
470 if errors.Is(err, ErrEOD) {
471 break
472 }
473 if err != nil {
474 return err
475 }
476
477 vw, err := dw.WriteDocumentElement(key)
478 if err != nil {
479 return err
480 }
481
482 err = c.CopyValue(vw, vr)
483 if err != nil {
484 return err
485 }
486 }
487
488 return dw.WriteDocumentEnd()
489 }
490
View as plain text