podman

Форк
0
445 строк · 9.8 Кб
1
// Copyright (C) MongoDB, Inc. 2017-present.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4
// not use this file except in compliance with the License. You may obtain
5
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6

7
package bsonrw
8

9
import (
10
	"fmt"
11
	"io"
12

13
	"go.mongodb.org/mongo-driver/bson/bsontype"
14
	"go.mongodb.org/mongo-driver/bson/primitive"
15
	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
16
)
17

18
// Copier is a type that allows copying between ValueReaders, ValueWriters, and
19
// []byte values.
20
type Copier struct{}
21

22
// NewCopier creates a new copier with the given registry. If a nil registry is provided
23
// a default registry is used.
24
func NewCopier() Copier {
25
	return Copier{}
26
}
27

28
// CopyDocument handles copying a document from src to dst.
29
func CopyDocument(dst ValueWriter, src ValueReader) error {
30
	return Copier{}.CopyDocument(dst, src)
31
}
32

33
// CopyDocument handles copying one document from the src to the dst.
34
func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
35
	dr, err := src.ReadDocument()
36
	if err != nil {
37
		return err
38
	}
39

40
	dw, err := dst.WriteDocument()
41
	if err != nil {
42
		return err
43
	}
44

45
	return c.copyDocumentCore(dw, dr)
46
}
47

48
// CopyArrayFromBytes copies the values from a BSON array represented as a
49
// []byte to a ValueWriter.
50
func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
51
	aw, err := dst.WriteArray()
52
	if err != nil {
53
		return err
54
	}
55

56
	err = c.CopyBytesToArrayWriter(aw, src)
57
	if err != nil {
58
		return err
59
	}
60

61
	return aw.WriteArrayEnd()
62
}
63

64
// CopyDocumentFromBytes copies the values from a BSON document represented as a
65
// []byte to a ValueWriter.
66
func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
67
	dw, err := dst.WriteDocument()
68
	if err != nil {
69
		return err
70
	}
71

72
	err = c.CopyBytesToDocumentWriter(dw, src)
73
	if err != nil {
74
		return err
75
	}
76

77
	return dw.WriteDocumentEnd()
78
}
79

80
type writeElementFn func(key string) (ValueWriter, error)
81

82
// CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an
83
// ArrayWriter.
84
func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
85
	wef := func(_ string) (ValueWriter, error) {
86
		return dst.WriteArrayElement()
87
	}
88

89
	return c.copyBytesToValueWriter(src, wef)
90
}
91

92
// CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
93
// DocumentWriter.
94
func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
95
	wef := func(key string) (ValueWriter, error) {
96
		return dst.WriteDocumentElement(key)
97
	}
98

99
	return c.copyBytesToValueWriter(src, wef)
100
}
101

102
func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
103
	// TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
104
	length, rem, ok := bsoncore.ReadLength(src)
105
	if !ok {
106
		return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src))
107
	}
108
	if len(src) < int(length) {
109
		return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length)
110
	}
111
	rem = rem[:length-4]
112

113
	var t bsontype.Type
114
	var key string
115
	var val bsoncore.Value
116
	for {
117
		t, rem, ok = bsoncore.ReadType(rem)
118
		if !ok {
119
			return io.EOF
120
		}
121
		if t == bsontype.Type(0) {
122
			if len(rem) != 0 {
123
				return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem)
124
			}
125
			break
126
		}
127

128
		key, rem, ok = bsoncore.ReadKey(rem)
129
		if !ok {
130
			return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
131
		}
132

133
		// write as either array element or document element using writeElementFn
134
		vw, err := wef(key)
135
		if err != nil {
136
			return err
137
		}
138

139
		val, rem, ok = bsoncore.ReadValue(rem, t)
140
		if !ok {
141
			return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
142
		}
143
		err = c.CopyValueFromBytes(vw, t, val.Data)
144
		if err != nil {
145
			return err
146
		}
147
	}
148
	return nil
149
}
150

151
// CopyDocumentToBytes copies an entire document from the ValueReader and
152
// returns it as bytes.
153
func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) {
154
	return c.AppendDocumentBytes(nil, src)
155
}
156

157
// AppendDocumentBytes functions the same as CopyDocumentToBytes, but will
158
// append the result to dst.
159
func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) {
160
	if br, ok := src.(BytesReader); ok {
161
		_, dst, err := br.ReadValueBytes(dst)
162
		return dst, err
163
	}
164

165
	vw := vwPool.Get().(*valueWriter)
166
	defer vwPool.Put(vw)
167

168
	vw.reset(dst)
169

170
	err := c.CopyDocument(vw, src)
171
	dst = vw.buf
172
	return dst, err
173
}
174

175
// AppendArrayBytes copies an array from the ValueReader to dst.
176
func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
177
	if br, ok := src.(BytesReader); ok {
178
		_, dst, err := br.ReadValueBytes(dst)
179
		return dst, err
180
	}
181

182
	vw := vwPool.Get().(*valueWriter)
183
	defer vwPool.Put(vw)
184

185
	vw.reset(dst)
186

187
	err := c.copyArray(vw, src)
188
	dst = vw.buf
189
	return dst, err
190
}
191

192
// CopyValueFromBytes will write the value represtend by t and src to dst.
193
func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
194
	if wvb, ok := dst.(BytesWriter); ok {
195
		return wvb.WriteValueBytes(t, src)
196
	}
197

198
	vr := vrPool.Get().(*valueReader)
199
	defer vrPool.Put(vr)
200

201
	vr.reset(src)
202
	vr.pushElement(t)
203

204
	return c.CopyValue(dst, vr)
205
}
206

207
// CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a
208
// []byte.
209
func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) {
210
	return c.AppendValueBytes(nil, src)
211
}
212

213
// AppendValueBytes functions the same as CopyValueToBytes, but will append the
214
// result to dst.
215
func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) {
216
	if br, ok := src.(BytesReader); ok {
217
		return br.ReadValueBytes(dst)
218
	}
219

220
	vw := vwPool.Get().(*valueWriter)
221
	defer vwPool.Put(vw)
222

223
	start := len(dst)
224

225
	vw.reset(dst)
226
	vw.push(mElement)
227

228
	err := c.CopyValue(vw, src)
229
	if err != nil {
230
		return 0, dst, err
231
	}
232

233
	return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil
234
}
235

236
// CopyValue will copy a single value from src to dst.
237
func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error {
238
	var err error
239
	switch src.Type() {
240
	case bsontype.Double:
241
		var f64 float64
242
		f64, err = src.ReadDouble()
243
		if err != nil {
244
			break
245
		}
246
		err = dst.WriteDouble(f64)
247
	case bsontype.String:
248
		var str string
249
		str, err = src.ReadString()
250
		if err != nil {
251
			return err
252
		}
253
		err = dst.WriteString(str)
254
	case bsontype.EmbeddedDocument:
255
		err = c.CopyDocument(dst, src)
256
	case bsontype.Array:
257
		err = c.copyArray(dst, src)
258
	case bsontype.Binary:
259
		var data []byte
260
		var subtype byte
261
		data, subtype, err = src.ReadBinary()
262
		if err != nil {
263
			break
264
		}
265
		err = dst.WriteBinaryWithSubtype(data, subtype)
266
	case bsontype.Undefined:
267
		err = src.ReadUndefined()
268
		if err != nil {
269
			break
270
		}
271
		err = dst.WriteUndefined()
272
	case bsontype.ObjectID:
273
		var oid primitive.ObjectID
274
		oid, err = src.ReadObjectID()
275
		if err != nil {
276
			break
277
		}
278
		err = dst.WriteObjectID(oid)
279
	case bsontype.Boolean:
280
		var b bool
281
		b, err = src.ReadBoolean()
282
		if err != nil {
283
			break
284
		}
285
		err = dst.WriteBoolean(b)
286
	case bsontype.DateTime:
287
		var dt int64
288
		dt, err = src.ReadDateTime()
289
		if err != nil {
290
			break
291
		}
292
		err = dst.WriteDateTime(dt)
293
	case bsontype.Null:
294
		err = src.ReadNull()
295
		if err != nil {
296
			break
297
		}
298
		err = dst.WriteNull()
299
	case bsontype.Regex:
300
		var pattern, options string
301
		pattern, options, err = src.ReadRegex()
302
		if err != nil {
303
			break
304
		}
305
		err = dst.WriteRegex(pattern, options)
306
	case bsontype.DBPointer:
307
		var ns string
308
		var pointer primitive.ObjectID
309
		ns, pointer, err = src.ReadDBPointer()
310
		if err != nil {
311
			break
312
		}
313
		err = dst.WriteDBPointer(ns, pointer)
314
	case bsontype.JavaScript:
315
		var js string
316
		js, err = src.ReadJavascript()
317
		if err != nil {
318
			break
319
		}
320
		err = dst.WriteJavascript(js)
321
	case bsontype.Symbol:
322
		var symbol string
323
		symbol, err = src.ReadSymbol()
324
		if err != nil {
325
			break
326
		}
327
		err = dst.WriteSymbol(symbol)
328
	case bsontype.CodeWithScope:
329
		var code string
330
		var srcScope DocumentReader
331
		code, srcScope, err = src.ReadCodeWithScope()
332
		if err != nil {
333
			break
334
		}
335

336
		var dstScope DocumentWriter
337
		dstScope, err = dst.WriteCodeWithScope(code)
338
		if err != nil {
339
			break
340
		}
341
		err = c.copyDocumentCore(dstScope, srcScope)
342
	case bsontype.Int32:
343
		var i32 int32
344
		i32, err = src.ReadInt32()
345
		if err != nil {
346
			break
347
		}
348
		err = dst.WriteInt32(i32)
349
	case bsontype.Timestamp:
350
		var t, i uint32
351
		t, i, err = src.ReadTimestamp()
352
		if err != nil {
353
			break
354
		}
355
		err = dst.WriteTimestamp(t, i)
356
	case bsontype.Int64:
357
		var i64 int64
358
		i64, err = src.ReadInt64()
359
		if err != nil {
360
			break
361
		}
362
		err = dst.WriteInt64(i64)
363
	case bsontype.Decimal128:
364
		var d128 primitive.Decimal128
365
		d128, err = src.ReadDecimal128()
366
		if err != nil {
367
			break
368
		}
369
		err = dst.WriteDecimal128(d128)
370
	case bsontype.MinKey:
371
		err = src.ReadMinKey()
372
		if err != nil {
373
			break
374
		}
375
		err = dst.WriteMinKey()
376
	case bsontype.MaxKey:
377
		err = src.ReadMaxKey()
378
		if err != nil {
379
			break
380
		}
381
		err = dst.WriteMaxKey()
382
	default:
383
		err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type())
384
	}
385

386
	return err
387
}
388

389
func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
390
	ar, err := src.ReadArray()
391
	if err != nil {
392
		return err
393
	}
394

395
	aw, err := dst.WriteArray()
396
	if err != nil {
397
		return err
398
	}
399

400
	for {
401
		vr, err := ar.ReadValue()
402
		if err == ErrEOA {
403
			break
404
		}
405
		if err != nil {
406
			return err
407
		}
408

409
		vw, err := aw.WriteArrayElement()
410
		if err != nil {
411
			return err
412
		}
413

414
		err = c.CopyValue(vw, vr)
415
		if err != nil {
416
			return err
417
		}
418
	}
419

420
	return aw.WriteArrayEnd()
421
}
422

423
func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
424
	for {
425
		key, vr, err := dr.ReadElement()
426
		if err == ErrEOD {
427
			break
428
		}
429
		if err != nil {
430
			return err
431
		}
432

433
		vw, err := dw.WriteDocumentElement(key)
434
		if err != nil {
435
			return err
436
		}
437

438
		err = c.CopyValue(vw, vr)
439
		if err != nil {
440
			return err
441
		}
442
	}
443

444
	return dw.WriteDocumentEnd()
445
}
446

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.