You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

decoder.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. package bson
  7. import (
  8. "errors"
  9. "fmt"
  10. "reflect"
  11. "sync"
  12. "go.mongodb.org/mongo-driver/bson/bsoncodec"
  13. "go.mongodb.org/mongo-driver/bson/bsonrw"
  14. )
  15. // ErrDecodeToNil is the error returned when trying to decode to a nil value
  16. var ErrDecodeToNil = errors.New("cannot Decode to nil value")
  17. // This pool is used to keep the allocations of Decoders down. This is only used for the Marshal*
  18. // methods and is not consumable from outside of this package. The Decoders retrieved from this pool
  19. // must have both Reset and SetRegistry called on them.
  20. var decPool = sync.Pool{
  21. New: func() interface{} {
  22. return new(Decoder)
  23. },
  24. }
  25. // A Decoder reads and decodes BSON documents from a stream. It reads from a bsonrw.ValueReader as
  26. // the source of BSON data.
  27. type Decoder struct {
  28. dc bsoncodec.DecodeContext
  29. vr bsonrw.ValueReader
  30. }
  31. // NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr.
  32. func NewDecoder(vr bsonrw.ValueReader) (*Decoder, error) {
  33. if vr == nil {
  34. return nil, errors.New("cannot create a new Decoder with a nil ValueReader")
  35. }
  36. return &Decoder{
  37. dc: bsoncodec.DecodeContext{Registry: DefaultRegistry},
  38. vr: vr,
  39. }, nil
  40. }
  41. // NewDecoderWithContext returns a new decoder that uses DecodeContext dc to read from vr.
  42. func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (*Decoder, error) {
  43. if dc.Registry == nil {
  44. dc.Registry = DefaultRegistry
  45. }
  46. if vr == nil {
  47. return nil, errors.New("cannot create a new Decoder with a nil ValueReader")
  48. }
  49. return &Decoder{
  50. dc: dc,
  51. vr: vr,
  52. }, nil
  53. }
  54. // Decode reads the next BSON document from the stream and decodes it into the
  55. // value pointed to by val.
  56. //
  57. // The documentation for Unmarshal contains details about of BSON into a Go
  58. // value.
  59. func (d *Decoder) Decode(val interface{}) error {
  60. if unmarshaler, ok := val.(Unmarshaler); ok {
  61. // TODO(skriptble): Reuse a []byte here and use the AppendDocumentBytes method.
  62. buf, err := bsonrw.Copier{}.CopyDocumentToBytes(d.vr)
  63. if err != nil {
  64. return err
  65. }
  66. return unmarshaler.UnmarshalBSON(buf)
  67. }
  68. rval := reflect.ValueOf(val)
  69. if rval.Kind() != reflect.Ptr {
  70. return fmt.Errorf("argument to Decode must be a pointer to a type, but got %v", rval)
  71. }
  72. if rval.IsNil() {
  73. return ErrDecodeToNil
  74. }
  75. rval = rval.Elem()
  76. decoder, err := d.dc.LookupDecoder(rval.Type())
  77. if err != nil {
  78. return err
  79. }
  80. return decoder.DecodeValue(d.dc, d.vr, rval)
  81. }
  82. // Reset will reset the state of the decoder, using the same *DecodeContext used in
  83. // the original construction but using vr for reading.
  84. func (d *Decoder) Reset(vr bsonrw.ValueReader) error {
  85. d.vr = vr
  86. return nil
  87. }
  88. // SetRegistry replaces the current registry of the decoder with r.
  89. func (d *Decoder) SetRegistry(r *bsoncodec.Registry) error {
  90. d.dc.Registry = r
  91. return nil
  92. }
  93. // SetContext replaces the current registry of the decoder with dc.
  94. func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error {
  95. d.dc = dc
  96. return nil
  97. }