1
2
3
4
5
6
7 package bsoncodec_test
8
9 import (
10 "fmt"
11 "math"
12 "reflect"
13
14 "go.mongodb.org/mongo-driver/bson"
15 "go.mongodb.org/mongo-driver/bson/bsoncodec"
16 "go.mongodb.org/mongo-driver/bson/bsonrw"
17 "go.mongodb.org/mongo-driver/bson/bsontype"
18 )
19
20 func ExampleRegistry_customEncoder() {
21
22
23 type negatedInt int
24
25 negatedIntType := reflect.TypeOf(negatedInt(0))
26
27 negatedIntEncoder := func(
28 ec bsoncodec.EncodeContext,
29 vw bsonrw.ValueWriter,
30 val reflect.Value,
31 ) error {
32
33
34 if !val.IsValid() || val.Type() != negatedIntType {
35 return bsoncodec.ValueEncoderError{
36 Name: "negatedIntEncoder",
37 Types: []reflect.Type{negatedIntType},
38 Received: val,
39 }
40 }
41
42
43
44 negatedVal := val.Int() * -1
45 if math.MinInt32 <= negatedVal && negatedVal <= math.MaxInt32 {
46 return vw.WriteInt32(int32(negatedVal))
47 }
48 return vw.WriteInt64(negatedVal)
49 }
50
51 reg := bson.NewRegistry()
52 reg.RegisterTypeEncoder(
53 negatedIntType,
54 bsoncodec.ValueEncoderFunc(negatedIntEncoder))
55
56
57
58 type myDocument struct {
59 Int int
60 NegatedInt negatedInt
61 }
62 doc := myDocument{
63 Int: 1,
64 NegatedInt: 1,
65 }
66
67
68
69 b, err := bson.MarshalWithRegistry(reg, doc)
70 if err != nil {
71 panic(err)
72 }
73 fmt.Println(bson.Raw(b).String())
74
75 }
76
77 func ExampleRegistry_customDecoder() {
78
79
80
81 type lenientBool bool
82
83 lenientBoolType := reflect.TypeOf(lenientBool(true))
84
85 lenientBoolDecoder := func(
86 dc bsoncodec.DecodeContext,
87 vr bsonrw.ValueReader,
88 val reflect.Value,
89 ) error {
90
91
92 if !val.IsValid() || !val.CanSet() || val.Type() != lenientBoolType {
93 return bsoncodec.ValueDecoderError{
94 Name: "lenientBoolDecoder",
95 Types: []reflect.Type{lenientBoolType},
96 Received: val,
97 }
98 }
99
100 var result bool
101 switch vr.Type() {
102 case bsontype.Boolean:
103 b, err := vr.ReadBoolean()
104 if err != nil {
105 return err
106 }
107 result = b
108 case bsontype.Int32:
109 i32, err := vr.ReadInt32()
110 if err != nil {
111 return err
112 }
113 result = i32 != 0
114 case bsontype.Int64:
115 i64, err := vr.ReadInt64()
116 if err != nil {
117 return err
118 }
119 result = i64 != 0
120 default:
121 return fmt.Errorf(
122 "received invalid BSON type to decode into lenientBool: %s",
123 vr.Type())
124 }
125
126 val.SetBool(result)
127 return nil
128 }
129
130 reg := bson.NewRegistry()
131 reg.RegisterTypeDecoder(
132 lenientBoolType,
133 bsoncodec.ValueDecoderFunc(lenientBoolDecoder))
134
135
136
137 b, err := bson.Marshal(bson.M{"isOK": 1})
138 if err != nil {
139 panic(err)
140 }
141
142
143
144
145 type MyDocument struct {
146 IsOK lenientBool `bson:"isOK"`
147 }
148 var doc MyDocument
149 err = bson.UnmarshalWithRegistry(reg, b, &doc)
150 if err != nil {
151 panic(err)
152 }
153 fmt.Printf("%+v\n", doc)
154
155 }
156
157 func ExampleRegistry_RegisterKindEncoder() {
158
159
160
161
162 int32To64Encoder := func(
163 ec bsoncodec.EncodeContext,
164 vw bsonrw.ValueWriter,
165 val reflect.Value,
166 ) error {
167
168
169 if !val.IsValid() || val.Kind() != reflect.Int32 {
170 return bsoncodec.ValueEncoderError{
171 Name: "int32To64Encoder",
172 Kinds: []reflect.Kind{reflect.Int32},
173 Received: val,
174 }
175 }
176
177 return vw.WriteInt64(val.Int())
178 }
179
180
181
182 reg := bson.NewRegistry()
183 reg.RegisterKindEncoder(
184 reflect.Int32,
185 bsoncodec.ValueEncoderFunc(int32To64Encoder))
186
187
188
189 type myInt int32
190 type myDocument struct {
191 MyInt myInt
192 Int32 int32
193 Int64 int64
194 }
195 doc := myDocument{
196 Int32: 1,
197 Int64: 1,
198 MyInt: 1,
199 }
200
201
202
203 b, err := bson.MarshalWithRegistry(reg, doc)
204 if err != nil {
205 panic(err)
206 }
207 fmt.Println(bson.Raw(b).String())
208
209 }
210
211 func ExampleRegistry_RegisterKindDecoder() {
212
213
214
215
216
217 flexibleInt64KindDecoder := func(
218 dc bsoncodec.DecodeContext,
219 vr bsonrw.ValueReader,
220 val reflect.Value,
221 ) error {
222
223
224 if !val.IsValid() || !val.CanSet() || val.Kind() != reflect.Int64 {
225 return bsoncodec.ValueDecoderError{
226 Name: "flexibleInt64KindDecoder",
227 Kinds: []reflect.Kind{reflect.Int64},
228 Received: val,
229 }
230 }
231
232 var result int64
233 switch vr.Type() {
234 case bsontype.Int64:
235 i64, err := vr.ReadInt64()
236 if err != nil {
237 return err
238 }
239 result = i64
240 case bsontype.Int32:
241 i32, err := vr.ReadInt32()
242 if err != nil {
243 return err
244 }
245 result = int64(i32)
246 case bsontype.Double:
247 d, err := vr.ReadDouble()
248 if err != nil {
249 return err
250 }
251 i64 := int64(d)
252
253 if d != float64(i64) {
254 return fmt.Errorf("double %f is not an integer value", d)
255 }
256 result = i64
257 default:
258 return fmt.Errorf(
259 "received invalid BSON type to decode into int64: %s",
260 vr.Type())
261 }
262
263 val.SetInt(result)
264 return nil
265 }
266
267 reg := bson.NewRegistry()
268 reg.RegisterKindDecoder(
269 reflect.Int64,
270 bsoncodec.ValueDecoderFunc(flexibleInt64KindDecoder))
271
272
273
274 b, err := bson.Marshal(bson.M{"myInt": float64(8), "int64": int32(9)})
275 if err != nil {
276 panic(err)
277 }
278
279
280
281 type myInt int64
282 type myDocument struct {
283 MyInt myInt
284 Int64 int64
285 }
286 var doc myDocument
287 err = bson.UnmarshalWithRegistry(reg, b, &doc)
288 if err != nil {
289 panic(err)
290 }
291 fmt.Printf("%+v\n", doc)
292
293 }
294
View as plain text