default_value_encoders.go raw
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 bsoncodec
8
9 import (
10 "encoding/json"
11 "errors"
12 "fmt"
13 "math"
14 "net/url"
15 "reflect"
16 "sync"
17 "time"
18
19 "go.mongodb.org/mongo-driver/bson/bsonrw"
20 "go.mongodb.org/mongo-driver/bson/bsontype"
21 "go.mongodb.org/mongo-driver/bson/primitive"
22 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
23 )
24
25 var defaultValueEncoders DefaultValueEncoders
26
27 var bvwPool = bsonrw.NewBSONValueWriterPool()
28
29 var errInvalidValue = errors.New("cannot encode invalid element")
30
31 var sliceWriterPool = sync.Pool{
32 New: func() interface{} {
33 sw := make(bsonrw.SliceWriter, 0)
34 return &sw
35 },
36 }
37
38 func encodeElement(ec EncodeContext, dw bsonrw.DocumentWriter, e primitive.E) error {
39 vw, err := dw.WriteDocumentElement(e.Key)
40 if err != nil {
41 return err
42 }
43
44 if e.Value == nil {
45 return vw.WriteNull()
46 }
47 encoder, err := ec.LookupEncoder(reflect.TypeOf(e.Value))
48 if err != nil {
49 return err
50 }
51
52 err = encoder.EncodeValue(ec, vw, reflect.ValueOf(e.Value))
53 if err != nil {
54 return err
55 }
56 return nil
57 }
58
59 // DefaultValueEncoders is a namespace type for the default ValueEncoders used
60 // when creating a registry.
61 //
62 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
63 // value encoders registered.
64 type DefaultValueEncoders struct{}
65
66 // RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with
67 // the provided RegistryBuilder.
68 //
69 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
70 // value encoders registered.
71 func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) {
72 if rb == nil {
73 panic(errors.New("argument to RegisterDefaultEncoders must not be nil"))
74 }
75 rb.
76 RegisterTypeEncoder(tByteSlice, defaultByteSliceCodec).
77 RegisterTypeEncoder(tTime, defaultTimeCodec).
78 RegisterTypeEncoder(tEmpty, defaultEmptyInterfaceCodec).
79 RegisterTypeEncoder(tCoreArray, defaultArrayCodec).
80 RegisterTypeEncoder(tOID, ValueEncoderFunc(dve.ObjectIDEncodeValue)).
81 RegisterTypeEncoder(tDecimal, ValueEncoderFunc(dve.Decimal128EncodeValue)).
82 RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(dve.JSONNumberEncodeValue)).
83 RegisterTypeEncoder(tURL, ValueEncoderFunc(dve.URLEncodeValue)).
84 RegisterTypeEncoder(tJavaScript, ValueEncoderFunc(dve.JavaScriptEncodeValue)).
85 RegisterTypeEncoder(tSymbol, ValueEncoderFunc(dve.SymbolEncodeValue)).
86 RegisterTypeEncoder(tBinary, ValueEncoderFunc(dve.BinaryEncodeValue)).
87 RegisterTypeEncoder(tUndefined, ValueEncoderFunc(dve.UndefinedEncodeValue)).
88 RegisterTypeEncoder(tDateTime, ValueEncoderFunc(dve.DateTimeEncodeValue)).
89 RegisterTypeEncoder(tNull, ValueEncoderFunc(dve.NullEncodeValue)).
90 RegisterTypeEncoder(tRegex, ValueEncoderFunc(dve.RegexEncodeValue)).
91 RegisterTypeEncoder(tDBPointer, ValueEncoderFunc(dve.DBPointerEncodeValue)).
92 RegisterTypeEncoder(tTimestamp, ValueEncoderFunc(dve.TimestampEncodeValue)).
93 RegisterTypeEncoder(tMinKey, ValueEncoderFunc(dve.MinKeyEncodeValue)).
94 RegisterTypeEncoder(tMaxKey, ValueEncoderFunc(dve.MaxKeyEncodeValue)).
95 RegisterTypeEncoder(tCoreDocument, ValueEncoderFunc(dve.CoreDocumentEncodeValue)).
96 RegisterTypeEncoder(tCodeWithScope, ValueEncoderFunc(dve.CodeWithScopeEncodeValue)).
97 RegisterDefaultEncoder(reflect.Bool, ValueEncoderFunc(dve.BooleanEncodeValue)).
98 RegisterDefaultEncoder(reflect.Int, ValueEncoderFunc(dve.IntEncodeValue)).
99 RegisterDefaultEncoder(reflect.Int8, ValueEncoderFunc(dve.IntEncodeValue)).
100 RegisterDefaultEncoder(reflect.Int16, ValueEncoderFunc(dve.IntEncodeValue)).
101 RegisterDefaultEncoder(reflect.Int32, ValueEncoderFunc(dve.IntEncodeValue)).
102 RegisterDefaultEncoder(reflect.Int64, ValueEncoderFunc(dve.IntEncodeValue)).
103 RegisterDefaultEncoder(reflect.Uint, defaultUIntCodec).
104 RegisterDefaultEncoder(reflect.Uint8, defaultUIntCodec).
105 RegisterDefaultEncoder(reflect.Uint16, defaultUIntCodec).
106 RegisterDefaultEncoder(reflect.Uint32, defaultUIntCodec).
107 RegisterDefaultEncoder(reflect.Uint64, defaultUIntCodec).
108 RegisterDefaultEncoder(reflect.Float32, ValueEncoderFunc(dve.FloatEncodeValue)).
109 RegisterDefaultEncoder(reflect.Float64, ValueEncoderFunc(dve.FloatEncodeValue)).
110 RegisterDefaultEncoder(reflect.Array, ValueEncoderFunc(dve.ArrayEncodeValue)).
111 RegisterDefaultEncoder(reflect.Map, defaultMapCodec).
112 RegisterDefaultEncoder(reflect.Slice, defaultSliceCodec).
113 RegisterDefaultEncoder(reflect.String, defaultStringCodec).
114 RegisterDefaultEncoder(reflect.Struct, newDefaultStructCodec()).
115 RegisterDefaultEncoder(reflect.Ptr, NewPointerCodec()).
116 RegisterHookEncoder(tValueMarshaler, ValueEncoderFunc(dve.ValueMarshalerEncodeValue)).
117 RegisterHookEncoder(tMarshaler, ValueEncoderFunc(dve.MarshalerEncodeValue)).
118 RegisterHookEncoder(tProxy, ValueEncoderFunc(dve.ProxyEncodeValue))
119 }
120
121 // BooleanEncodeValue is the ValueEncoderFunc for bool types.
122 //
123 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
124 // value encoders registered.
125 func (dve DefaultValueEncoders) BooleanEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
126 if !val.IsValid() || val.Kind() != reflect.Bool {
127 return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val}
128 }
129 return vw.WriteBoolean(val.Bool())
130 }
131
132 func fitsIn32Bits(i int64) bool {
133 return math.MinInt32 <= i && i <= math.MaxInt32
134 }
135
136 // IntEncodeValue is the ValueEncoderFunc for int types.
137 //
138 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
139 // value encoders registered.
140 func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
141 switch val.Kind() {
142 case reflect.Int8, reflect.Int16, reflect.Int32:
143 return vw.WriteInt32(int32(val.Int()))
144 case reflect.Int:
145 i64 := val.Int()
146 if fitsIn32Bits(i64) {
147 return vw.WriteInt32(int32(i64))
148 }
149 return vw.WriteInt64(i64)
150 case reflect.Int64:
151 i64 := val.Int()
152 if ec.MinSize && fitsIn32Bits(i64) {
153 return vw.WriteInt32(int32(i64))
154 }
155 return vw.WriteInt64(i64)
156 }
157
158 return ValueEncoderError{
159 Name: "IntEncodeValue",
160 Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
161 Received: val,
162 }
163 }
164
165 // UintEncodeValue is the ValueEncoderFunc for uint types.
166 //
167 // Deprecated: UintEncodeValue is not registered by default. Use UintCodec.EncodeValue instead.
168 func (dve DefaultValueEncoders) UintEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
169 switch val.Kind() {
170 case reflect.Uint8, reflect.Uint16:
171 return vw.WriteInt32(int32(val.Uint()))
172 case reflect.Uint, reflect.Uint32, reflect.Uint64:
173 u64 := val.Uint()
174 if ec.MinSize && u64 <= math.MaxInt32 {
175 return vw.WriteInt32(int32(u64))
176 }
177 if u64 > math.MaxInt64 {
178 return fmt.Errorf("%d overflows int64", u64)
179 }
180 return vw.WriteInt64(int64(u64))
181 }
182
183 return ValueEncoderError{
184 Name: "UintEncodeValue",
185 Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
186 Received: val,
187 }
188 }
189
190 // FloatEncodeValue is the ValueEncoderFunc for float types.
191 //
192 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
193 // value encoders registered.
194 func (dve DefaultValueEncoders) FloatEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
195 switch val.Kind() {
196 case reflect.Float32, reflect.Float64:
197 return vw.WriteDouble(val.Float())
198 }
199
200 return ValueEncoderError{Name: "FloatEncodeValue", Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, Received: val}
201 }
202
203 // StringEncodeValue is the ValueEncoderFunc for string types.
204 //
205 // Deprecated: StringEncodeValue is not registered by default. Use StringCodec.EncodeValue instead.
206 func (dve DefaultValueEncoders) StringEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
207 if val.Kind() != reflect.String {
208 return ValueEncoderError{
209 Name: "StringEncodeValue",
210 Kinds: []reflect.Kind{reflect.String},
211 Received: val,
212 }
213 }
214
215 return vw.WriteString(val.String())
216 }
217
218 // ObjectIDEncodeValue is the ValueEncoderFunc for primitive.ObjectID.
219 //
220 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
221 // value encoders registered.
222 func (dve DefaultValueEncoders) ObjectIDEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
223 if !val.IsValid() || val.Type() != tOID {
224 return ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val}
225 }
226 return vw.WriteObjectID(val.Interface().(primitive.ObjectID))
227 }
228
229 // Decimal128EncodeValue is the ValueEncoderFunc for primitive.Decimal128.
230 //
231 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
232 // value encoders registered.
233 func (dve DefaultValueEncoders) Decimal128EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
234 if !val.IsValid() || val.Type() != tDecimal {
235 return ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: val}
236 }
237 return vw.WriteDecimal128(val.Interface().(primitive.Decimal128))
238 }
239
240 // JSONNumberEncodeValue is the ValueEncoderFunc for json.Number.
241 //
242 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
243 // value encoders registered.
244 func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
245 if !val.IsValid() || val.Type() != tJSONNumber {
246 return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val}
247 }
248 jsnum := val.Interface().(json.Number)
249
250 // Attempt int first, then float64
251 if i64, err := jsnum.Int64(); err == nil {
252 return dve.IntEncodeValue(ec, vw, reflect.ValueOf(i64))
253 }
254
255 f64, err := jsnum.Float64()
256 if err != nil {
257 return err
258 }
259
260 return dve.FloatEncodeValue(ec, vw, reflect.ValueOf(f64))
261 }
262
263 // URLEncodeValue is the ValueEncoderFunc for url.URL.
264 //
265 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
266 // value encoders registered.
267 func (dve DefaultValueEncoders) URLEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
268 if !val.IsValid() || val.Type() != tURL {
269 return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val}
270 }
271 u := val.Interface().(url.URL)
272 return vw.WriteString(u.String())
273 }
274
275 // TimeEncodeValue is the ValueEncoderFunc for time.TIme.
276 //
277 // Deprecated: TimeEncodeValue is not registered by default. Use TimeCodec.EncodeValue instead.
278 func (dve DefaultValueEncoders) TimeEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
279 if !val.IsValid() || val.Type() != tTime {
280 return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val}
281 }
282 tt := val.Interface().(time.Time)
283 dt := primitive.NewDateTimeFromTime(tt)
284 return vw.WriteDateTime(int64(dt))
285 }
286
287 // ByteSliceEncodeValue is the ValueEncoderFunc for []byte.
288 //
289 // Deprecated: ByteSliceEncodeValue is not registered by default. Use ByteSliceCodec.EncodeValue instead.
290 func (dve DefaultValueEncoders) ByteSliceEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
291 if !val.IsValid() || val.Type() != tByteSlice {
292 return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val}
293 }
294 if val.IsNil() {
295 return vw.WriteNull()
296 }
297 return vw.WriteBinary(val.Interface().([]byte))
298 }
299
300 // MapEncodeValue is the ValueEncoderFunc for map[string]* types.
301 //
302 // Deprecated: MapEncodeValue is not registered by default. Use MapCodec.EncodeValue instead.
303 func (dve DefaultValueEncoders) MapEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
304 if !val.IsValid() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String {
305 return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val}
306 }
307
308 if val.IsNil() {
309 // If we have a nill map but we can't WriteNull, that means we're probably trying to encode
310 // to a TopLevel document. We can't currently tell if this is what actually happened, but if
311 // there's a deeper underlying problem, the error will also be returned from WriteDocument,
312 // so just continue. The operations on a map reflection value are valid, so we can call
313 // MapKeys within mapEncodeValue without a problem.
314 err := vw.WriteNull()
315 if err == nil {
316 return nil
317 }
318 }
319
320 dw, err := vw.WriteDocument()
321 if err != nil {
322 return err
323 }
324
325 return dve.mapEncodeValue(ec, dw, val, nil)
326 }
327
328 // mapEncodeValue handles encoding of the values of a map. The collisionFn returns
329 // true if the provided key exists, this is mainly used for inline maps in the
330 // struct codec.
331 func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, val reflect.Value, collisionFn func(string) bool) error {
332
333 elemType := val.Type().Elem()
334 encoder, err := ec.LookupEncoder(elemType)
335 if err != nil && elemType.Kind() != reflect.Interface {
336 return err
337 }
338
339 keys := val.MapKeys()
340 for _, key := range keys {
341 if collisionFn != nil && collisionFn(key.String()) {
342 return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key)
343 }
344
345 currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key))
346 if lookupErr != nil && lookupErr != errInvalidValue {
347 return lookupErr
348 }
349
350 vw, err := dw.WriteDocumentElement(key.String())
351 if err != nil {
352 return err
353 }
354
355 if lookupErr == errInvalidValue {
356 err = vw.WriteNull()
357 if err != nil {
358 return err
359 }
360 continue
361 }
362
363 err = currEncoder.EncodeValue(ec, vw, currVal)
364 if err != nil {
365 return err
366 }
367 }
368
369 return dw.WriteDocumentEnd()
370 }
371
372 // ArrayEncodeValue is the ValueEncoderFunc for array types.
373 //
374 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
375 // value encoders registered.
376 func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
377 if !val.IsValid() || val.Kind() != reflect.Array {
378 return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val}
379 }
380
381 // If we have a []primitive.E we want to treat it as a document instead of as an array.
382 if val.Type().Elem() == tE {
383 dw, err := vw.WriteDocument()
384 if err != nil {
385 return err
386 }
387
388 for idx := 0; idx < val.Len(); idx++ {
389 e := val.Index(idx).Interface().(primitive.E)
390 err = encodeElement(ec, dw, e)
391 if err != nil {
392 return err
393 }
394 }
395
396 return dw.WriteDocumentEnd()
397 }
398
399 // If we have a []byte we want to treat it as a binary instead of as an array.
400 if val.Type().Elem() == tByte {
401 var byteSlice []byte
402 for idx := 0; idx < val.Len(); idx++ {
403 byteSlice = append(byteSlice, val.Index(idx).Interface().(byte))
404 }
405 return vw.WriteBinary(byteSlice)
406 }
407
408 aw, err := vw.WriteArray()
409 if err != nil {
410 return err
411 }
412
413 elemType := val.Type().Elem()
414 encoder, err := ec.LookupEncoder(elemType)
415 if err != nil && elemType.Kind() != reflect.Interface {
416 return err
417 }
418
419 for idx := 0; idx < val.Len(); idx++ {
420 currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
421 if lookupErr != nil && lookupErr != errInvalidValue {
422 return lookupErr
423 }
424
425 vw, err := aw.WriteArrayElement()
426 if err != nil {
427 return err
428 }
429
430 if lookupErr == errInvalidValue {
431 err = vw.WriteNull()
432 if err != nil {
433 return err
434 }
435 continue
436 }
437
438 err = currEncoder.EncodeValue(ec, vw, currVal)
439 if err != nil {
440 return err
441 }
442 }
443 return aw.WriteArrayEnd()
444 }
445
446 // SliceEncodeValue is the ValueEncoderFunc for slice types.
447 //
448 // Deprecated: SliceEncodeValue is not registered by default. Use SliceCodec.EncodeValue instead.
449 func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
450 if !val.IsValid() || val.Kind() != reflect.Slice {
451 return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val}
452 }
453
454 if val.IsNil() {
455 return vw.WriteNull()
456 }
457
458 // If we have a []primitive.E we want to treat it as a document instead of as an array.
459 if val.Type().ConvertibleTo(tD) {
460 d := val.Convert(tD).Interface().(primitive.D)
461
462 dw, err := vw.WriteDocument()
463 if err != nil {
464 return err
465 }
466
467 for _, e := range d {
468 err = encodeElement(ec, dw, e)
469 if err != nil {
470 return err
471 }
472 }
473
474 return dw.WriteDocumentEnd()
475 }
476
477 aw, err := vw.WriteArray()
478 if err != nil {
479 return err
480 }
481
482 elemType := val.Type().Elem()
483 encoder, err := ec.LookupEncoder(elemType)
484 if err != nil && elemType.Kind() != reflect.Interface {
485 return err
486 }
487
488 for idx := 0; idx < val.Len(); idx++ {
489 currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx))
490 if lookupErr != nil && lookupErr != errInvalidValue {
491 return lookupErr
492 }
493
494 vw, err := aw.WriteArrayElement()
495 if err != nil {
496 return err
497 }
498
499 if lookupErr == errInvalidValue {
500 err = vw.WriteNull()
501 if err != nil {
502 return err
503 }
504 continue
505 }
506
507 err = currEncoder.EncodeValue(ec, vw, currVal)
508 if err != nil {
509 return err
510 }
511 }
512 return aw.WriteArrayEnd()
513 }
514
515 func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) {
516 if origEncoder != nil || (currVal.Kind() != reflect.Interface) {
517 return origEncoder, currVal, nil
518 }
519 currVal = currVal.Elem()
520 if !currVal.IsValid() {
521 return nil, currVal, errInvalidValue
522 }
523 currEncoder, err := ec.LookupEncoder(currVal.Type())
524
525 return currEncoder, currVal, err
526 }
527
528 // EmptyInterfaceEncodeValue is the ValueEncoderFunc for interface{}.
529 //
530 // Deprecated: EmptyInterfaceEncodeValue is not registered by default. Use EmptyInterfaceCodec.EncodeValue instead.
531 func (dve DefaultValueEncoders) EmptyInterfaceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
532 if !val.IsValid() || val.Type() != tEmpty {
533 return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val}
534 }
535
536 if val.IsNil() {
537 return vw.WriteNull()
538 }
539 encoder, err := ec.LookupEncoder(val.Elem().Type())
540 if err != nil {
541 return err
542 }
543
544 return encoder.EncodeValue(ec, vw, val.Elem())
545 }
546
547 // ValueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations.
548 //
549 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
550 // value encoders registered.
551 func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
552 // Either val or a pointer to val must implement ValueMarshaler
553 switch {
554 case !val.IsValid():
555 return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val}
556 case val.Type().Implements(tValueMarshaler):
557 // If ValueMarshaler is implemented on a concrete type, make sure that val isn't a nil pointer
558 if isImplementationNil(val, tValueMarshaler) {
559 return vw.WriteNull()
560 }
561 case reflect.PtrTo(val.Type()).Implements(tValueMarshaler) && val.CanAddr():
562 val = val.Addr()
563 default:
564 return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val}
565 }
566
567 m, ok := val.Interface().(ValueMarshaler)
568 if !ok {
569 return vw.WriteNull()
570 }
571 t, data, err := m.MarshalBSONValue()
572 if err != nil {
573 return err
574 }
575 return bsonrw.Copier{}.CopyValueFromBytes(vw, t, data)
576 }
577
578 // MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations.
579 //
580 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
581 // value encoders registered.
582 func (dve DefaultValueEncoders) MarshalerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
583 // Either val or a pointer to val must implement Marshaler
584 switch {
585 case !val.IsValid():
586 return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val}
587 case val.Type().Implements(tMarshaler):
588 // If Marshaler is implemented on a concrete type, make sure that val isn't a nil pointer
589 if isImplementationNil(val, tMarshaler) {
590 return vw.WriteNull()
591 }
592 case reflect.PtrTo(val.Type()).Implements(tMarshaler) && val.CanAddr():
593 val = val.Addr()
594 default:
595 return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val}
596 }
597
598 m, ok := val.Interface().(Marshaler)
599 if !ok {
600 return vw.WriteNull()
601 }
602 data, err := m.MarshalBSON()
603 if err != nil {
604 return err
605 }
606 return bsonrw.Copier{}.CopyValueFromBytes(vw, bsontype.EmbeddedDocument, data)
607 }
608
609 // ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations.
610 //
611 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
612 // value encoders registered.
613 func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
614 // Either val or a pointer to val must implement Proxy
615 switch {
616 case !val.IsValid():
617 return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val}
618 case val.Type().Implements(tProxy):
619 // If Proxy is implemented on a concrete type, make sure that val isn't a nil pointer
620 if isImplementationNil(val, tProxy) {
621 return vw.WriteNull()
622 }
623 case reflect.PtrTo(val.Type()).Implements(tProxy) && val.CanAddr():
624 val = val.Addr()
625 default:
626 return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val}
627 }
628
629 m, ok := val.Interface().(Proxy)
630 if !ok {
631 return vw.WriteNull()
632 }
633 v, err := m.ProxyBSON()
634 if err != nil {
635 return err
636 }
637 if v == nil {
638 encoder, err := ec.LookupEncoder(nil)
639 if err != nil {
640 return err
641 }
642 return encoder.EncodeValue(ec, vw, reflect.ValueOf(nil))
643 }
644 vv := reflect.ValueOf(v)
645 switch vv.Kind() {
646 case reflect.Ptr, reflect.Interface:
647 vv = vv.Elem()
648 }
649 encoder, err := ec.LookupEncoder(vv.Type())
650 if err != nil {
651 return err
652 }
653 return encoder.EncodeValue(ec, vw, vv)
654 }
655
656 // JavaScriptEncodeValue is the ValueEncoderFunc for the primitive.JavaScript type.
657 //
658 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
659 // value encoders registered.
660 func (DefaultValueEncoders) JavaScriptEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
661 if !val.IsValid() || val.Type() != tJavaScript {
662 return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val}
663 }
664
665 return vw.WriteJavascript(val.String())
666 }
667
668 // SymbolEncodeValue is the ValueEncoderFunc for the primitive.Symbol type.
669 //
670 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
671 // value encoders registered.
672 func (DefaultValueEncoders) SymbolEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
673 if !val.IsValid() || val.Type() != tSymbol {
674 return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val}
675 }
676
677 return vw.WriteSymbol(val.String())
678 }
679
680 // BinaryEncodeValue is the ValueEncoderFunc for Binary.
681 //
682 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
683 // value encoders registered.
684 func (DefaultValueEncoders) BinaryEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
685 if !val.IsValid() || val.Type() != tBinary {
686 return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
687 }
688 b := val.Interface().(primitive.Binary)
689
690 return vw.WriteBinaryWithSubtype(b.Data, b.Subtype)
691 }
692
693 // UndefinedEncodeValue is the ValueEncoderFunc for Undefined.
694 //
695 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
696 // value encoders registered.
697 func (DefaultValueEncoders) UndefinedEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
698 if !val.IsValid() || val.Type() != tUndefined {
699 return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val}
700 }
701
702 return vw.WriteUndefined()
703 }
704
705 // DateTimeEncodeValue is the ValueEncoderFunc for DateTime.
706 //
707 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
708 // value encoders registered.
709 func (DefaultValueEncoders) DateTimeEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
710 if !val.IsValid() || val.Type() != tDateTime {
711 return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val}
712 }
713
714 return vw.WriteDateTime(val.Int())
715 }
716
717 // NullEncodeValue is the ValueEncoderFunc for Null.
718 //
719 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
720 // value encoders registered.
721 func (DefaultValueEncoders) NullEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
722 if !val.IsValid() || val.Type() != tNull {
723 return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val}
724 }
725
726 return vw.WriteNull()
727 }
728
729 // RegexEncodeValue is the ValueEncoderFunc for Regex.
730 //
731 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
732 // value encoders registered.
733 func (DefaultValueEncoders) RegexEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
734 if !val.IsValid() || val.Type() != tRegex {
735 return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val}
736 }
737
738 regex := val.Interface().(primitive.Regex)
739
740 return vw.WriteRegex(regex.Pattern, regex.Options)
741 }
742
743 // DBPointerEncodeValue is the ValueEncoderFunc for DBPointer.
744 //
745 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
746 // value encoders registered.
747 func (DefaultValueEncoders) DBPointerEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
748 if !val.IsValid() || val.Type() != tDBPointer {
749 return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val}
750 }
751
752 dbp := val.Interface().(primitive.DBPointer)
753
754 return vw.WriteDBPointer(dbp.DB, dbp.Pointer)
755 }
756
757 // TimestampEncodeValue is the ValueEncoderFunc for Timestamp.
758 //
759 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
760 // value encoders registered.
761 func (DefaultValueEncoders) TimestampEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
762 if !val.IsValid() || val.Type() != tTimestamp {
763 return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val}
764 }
765
766 ts := val.Interface().(primitive.Timestamp)
767
768 return vw.WriteTimestamp(ts.T, ts.I)
769 }
770
771 // MinKeyEncodeValue is the ValueEncoderFunc for MinKey.
772 //
773 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
774 // value encoders registered.
775 func (DefaultValueEncoders) MinKeyEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
776 if !val.IsValid() || val.Type() != tMinKey {
777 return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val}
778 }
779
780 return vw.WriteMinKey()
781 }
782
783 // MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey.
784 //
785 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
786 // value encoders registered.
787 func (DefaultValueEncoders) MaxKeyEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
788 if !val.IsValid() || val.Type() != tMaxKey {
789 return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val}
790 }
791
792 return vw.WriteMaxKey()
793 }
794
795 // CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document.
796 //
797 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
798 // value encoders registered.
799 func (DefaultValueEncoders) CoreDocumentEncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
800 if !val.IsValid() || val.Type() != tCoreDocument {
801 return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val}
802 }
803
804 cdoc := val.Interface().(bsoncore.Document)
805
806 return bsonrw.Copier{}.CopyDocumentFromBytes(vw, cdoc)
807 }
808
809 // CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope.
810 //
811 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default
812 // value encoders registered.
813 func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
814 if !val.IsValid() || val.Type() != tCodeWithScope {
815 return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val}
816 }
817
818 cws := val.Interface().(primitive.CodeWithScope)
819
820 dw, err := vw.WriteCodeWithScope(string(cws.Code))
821 if err != nil {
822 return err
823 }
824
825 sw := sliceWriterPool.Get().(*bsonrw.SliceWriter)
826 defer sliceWriterPool.Put(sw)
827 *sw = (*sw)[:0]
828
829 scopeVW := bvwPool.Get(sw)
830 defer bvwPool.Put(scopeVW)
831
832 encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope))
833 if err != nil {
834 return err
835 }
836
837 err = encoder.EncodeValue(ec, scopeVW, reflect.ValueOf(cws.Scope))
838 if err != nil {
839 return err
840 }
841
842 err = bsonrw.Copier{}.CopyBytesToDocumentWriter(dw, *sw)
843 if err != nil {
844 return err
845 }
846 return dw.WriteDocumentEnd()
847 }
848
849 // isImplementationNil returns if val is a nil pointer and inter is implemented on a concrete type
850 func isImplementationNil(val reflect.Value, inter reflect.Type) bool {
851 vt := val.Type()
852 for vt.Kind() == reflect.Ptr {
853 vt = vt.Elem()
854 }
855 return vt.Implements(inter) && val.Kind() == reflect.Ptr && val.IsNil()
856 }
857