...
1
2
3
4
5
6
7 package bson
8
9 import (
10 "errors"
11 "fmt"
12 "reflect"
13 "sync"
14
15 "go.mongodb.org/mongo-driver/bson/bsoncodec"
16 "go.mongodb.org/mongo-driver/bson/bsonrw"
17 )
18
19
20 var ErrDecodeToNil = errors.New("cannot Decode to nil value")
21
22
23
24
25 var decPool = sync.Pool{
26 New: func() interface{} {
27 return new(Decoder)
28 },
29 }
30
31
32
33 type Decoder struct {
34 dc bsoncodec.DecodeContext
35 vr bsonrw.ValueReader
36
37
38
39 defaultDocumentM bool
40 defaultDocumentD bool
41
42 binaryAsSlice bool
43 useJSONStructTags bool
44 useLocalTimeZone bool
45 zeroMaps bool
46 zeroStructs bool
47 }
48
49
50 func NewDecoder(vr bsonrw.ValueReader) (*Decoder, error) {
51 if vr == nil {
52 return nil, errors.New("cannot create a new Decoder with a nil ValueReader")
53 }
54
55 return &Decoder{
56 dc: bsoncodec.DecodeContext{Registry: DefaultRegistry},
57 vr: vr,
58 }, nil
59 }
60
61
62
63
64
65 func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (*Decoder, error) {
66 if dc.Registry == nil {
67 dc.Registry = DefaultRegistry
68 }
69 if vr == nil {
70 return nil, errors.New("cannot create a new Decoder with a nil ValueReader")
71 }
72
73 return &Decoder{
74 dc: dc,
75 vr: vr,
76 }, nil
77 }
78
79
80
81
82
83 func (d *Decoder) Decode(val interface{}) error {
84 if unmarshaler, ok := val.(Unmarshaler); ok {
85
86 buf, err := bsonrw.Copier{}.CopyDocumentToBytes(d.vr)
87 if err != nil {
88 return err
89 }
90 return unmarshaler.UnmarshalBSON(buf)
91 }
92
93 rval := reflect.ValueOf(val)
94 switch rval.Kind() {
95 case reflect.Ptr:
96 if rval.IsNil() {
97 return ErrDecodeToNil
98 }
99 rval = rval.Elem()
100 case reflect.Map:
101 if rval.IsNil() {
102 return ErrDecodeToNil
103 }
104 default:
105 return fmt.Errorf("argument to Decode must be a pointer or a map, but got %v", rval)
106 }
107 decoder, err := d.dc.LookupDecoder(rval.Type())
108 if err != nil {
109 return err
110 }
111
112 if d.defaultDocumentM {
113 d.dc.DefaultDocumentM()
114 }
115 if d.defaultDocumentD {
116 d.dc.DefaultDocumentD()
117 }
118 if d.binaryAsSlice {
119 d.dc.BinaryAsSlice()
120 }
121 if d.useJSONStructTags {
122 d.dc.UseJSONStructTags()
123 }
124 if d.useLocalTimeZone {
125 d.dc.UseLocalTimeZone()
126 }
127 if d.zeroMaps {
128 d.dc.ZeroMaps()
129 }
130 if d.zeroStructs {
131 d.dc.ZeroStructs()
132 }
133
134 return decoder.DecodeValue(d.dc, d.vr, rval)
135 }
136
137
138
139 func (d *Decoder) Reset(vr bsonrw.ValueReader) error {
140
141 d.vr = vr
142 return nil
143 }
144
145
146 func (d *Decoder) SetRegistry(r *bsoncodec.Registry) error {
147
148 d.dc.Registry = r
149 return nil
150 }
151
152
153
154
155 func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error {
156
157 d.dc = dc
158 return nil
159 }
160
161
162
163 func (d *Decoder) DefaultDocumentM() {
164 d.defaultDocumentM = true
165 }
166
167
168
169 func (d *Decoder) DefaultDocumentD() {
170 d.defaultDocumentD = true
171 }
172
173
174
175
176 func (d *Decoder) AllowTruncatingDoubles() {
177 d.dc.Truncate = true
178 }
179
180
181
182 func (d *Decoder) BinaryAsSlice() {
183 d.binaryAsSlice = true
184 }
185
186
187
188 func (d *Decoder) UseJSONStructTags() {
189 d.useJSONStructTags = true
190 }
191
192
193
194 func (d *Decoder) UseLocalTimeZone() {
195 d.useLocalTimeZone = true
196 }
197
198
199
200 func (d *Decoder) ZeroMaps() {
201 d.zeroMaps = true
202 }
203
204
205
206 func (d *Decoder) ZeroStructs() {
207 d.zeroStructs = true
208 }
209
View as plain text