...
1
2
3
4
5
6
7 package bsoncodec
8
9 import (
10 "reflect"
11
12 "go.mongodb.org/mongo-driver/bson/bsonoptions"
13 "go.mongodb.org/mongo-driver/bson/bsonrw"
14 "go.mongodb.org/mongo-driver/bson/bsontype"
15 "go.mongodb.org/mongo-driver/bson/primitive"
16 )
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 type EmptyInterfaceCodec struct {
37
38
39
40
41 DecodeBinaryAsSlice bool
42 }
43
44 var (
45 defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
46
47
48
49
50 _ typeDecoder = defaultEmptyInterfaceCodec
51 )
52
53
54
55
56
57 func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec {
58 interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...)
59
60 codec := EmptyInterfaceCodec{}
61 if interfaceOpt.DecodeBinaryAsSlice != nil {
62 codec.DecodeBinaryAsSlice = *interfaceOpt.DecodeBinaryAsSlice
63 }
64 return &codec
65 }
66
67
68 func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
69 if !val.IsValid() || val.Type() != tEmpty {
70 return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val}
71 }
72
73 if val.IsNil() {
74 return vw.WriteNull()
75 }
76 encoder, err := ec.LookupEncoder(val.Elem().Type())
77 if err != nil {
78 return err
79 }
80
81 return encoder.EncodeValue(ec, vw, val.Elem())
82 }
83
84 func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType bsontype.Type) (reflect.Type, error) {
85 isDocument := valueType == bsontype.Type(0) || valueType == bsontype.EmbeddedDocument
86 if isDocument {
87 if dc.defaultDocumentType != nil {
88
89
90 return dc.defaultDocumentType, nil
91 }
92 if dc.Ancestor != nil {
93
94
95
96 return dc.Ancestor, nil
97 }
98 }
99
100 rtype, err := dc.LookupTypeMapEntry(valueType)
101 if err == nil {
102 return rtype, nil
103 }
104
105 if isDocument {
106
107
108 var lookupType bsontype.Type
109 switch valueType {
110 case bsontype.Type(0):
111 lookupType = bsontype.EmbeddedDocument
112 case bsontype.EmbeddedDocument:
113 lookupType = bsontype.Type(0)
114 }
115
116 rtype, err = dc.LookupTypeMapEntry(lookupType)
117 if err == nil {
118 return rtype, nil
119 }
120 }
121
122 return nil, err
123 }
124
125 func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
126 if t != tEmpty {
127 return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)}
128 }
129
130 rtype, err := eic.getEmptyInterfaceDecodeType(dc, vr.Type())
131 if err != nil {
132 switch vr.Type() {
133 case bsontype.Null:
134 return reflect.Zero(t), vr.ReadNull()
135 default:
136 return emptyValue, err
137 }
138 }
139
140 decoder, err := dc.LookupDecoder(rtype)
141 if err != nil {
142 return emptyValue, err
143 }
144
145 elem, err := decodeTypeOrValue(decoder, dc, vr, rtype)
146 if err != nil {
147 return emptyValue, err
148 }
149
150 if (eic.DecodeBinaryAsSlice || dc.binaryAsSlice) && rtype == tBinary {
151 binElem := elem.Interface().(primitive.Binary)
152 if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld {
153 elem = reflect.ValueOf(binElem.Data)
154 }
155 }
156
157 return elem, nil
158 }
159
160
161 func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
162 if !val.CanSet() || val.Type() != tEmpty {
163 return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val}
164 }
165
166 elem, err := eic.decodeType(dc, vr, val.Type())
167 if err != nil {
168 return err
169 }
170
171 val.Set(elem)
172 return nil
173 }
174
View as plain text