blob: 045c713012b908e778ce78d6f19e8e87ce32f14e [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001package bson
2
3import (
4 "bytes"
5 "encoding/base64"
6 "fmt"
7 "strconv"
8 "strings"
9 "time"
10
11 "github.com/globalsign/mgo/internal/json"
12)
13
14// UnmarshalJSON unmarshals a JSON value that may hold non-standard
15// syntax as defined in BSON's extended JSON specification.
16func UnmarshalJSON(data []byte, value interface{}) error {
17 d := json.NewDecoder(bytes.NewBuffer(data))
18 d.Extend(&jsonExt)
19 return d.Decode(value)
20}
21
22// MarshalJSON marshals a JSON value that may hold non-standard
23// syntax as defined in BSON's extended JSON specification.
24func MarshalJSON(value interface{}) ([]byte, error) {
25 var buf bytes.Buffer
26 e := json.NewEncoder(&buf)
27 e.Extend(&jsonExt)
28 err := e.Encode(value)
29 if err != nil {
30 return nil, err
31 }
32 return buf.Bytes(), nil
33}
34
35// jdec is used internally by the JSON decoding functions
36// so they may unmarshal functions without getting into endless
37// recursion due to keyed objects.
38func jdec(data []byte, value interface{}) error {
39 d := json.NewDecoder(bytes.NewBuffer(data))
40 d.Extend(&funcExt)
41 return d.Decode(value)
42}
43
44var jsonExt json.Extension
45var funcExt json.Extension
46
47// TODO
48// - Shell regular expressions ("/regexp/opts")
49
50func init() {
51 jsonExt.DecodeUnquotedKeys(true)
52 jsonExt.DecodeTrailingCommas(true)
53
54 funcExt.DecodeFunc("BinData", "$binaryFunc", "$type", "$binary")
55 jsonExt.DecodeKeyed("$binary", jdecBinary)
56 jsonExt.DecodeKeyed("$binaryFunc", jdecBinary)
57 jsonExt.EncodeType([]byte(nil), jencBinarySlice)
58 jsonExt.EncodeType(Binary{}, jencBinaryType)
59
60 funcExt.DecodeFunc("ISODate", "$dateFunc", "S")
61 funcExt.DecodeFunc("new Date", "$dateFunc", "S")
62 jsonExt.DecodeKeyed("$date", jdecDate)
63 jsonExt.DecodeKeyed("$dateFunc", jdecDate)
64 jsonExt.EncodeType(time.Time{}, jencDate)
65
66 funcExt.DecodeFunc("Timestamp", "$timestamp", "t", "i")
67 jsonExt.DecodeKeyed("$timestamp", jdecTimestamp)
68 jsonExt.EncodeType(MongoTimestamp(0), jencTimestamp)
69
70 funcExt.DecodeConst("undefined", Undefined)
71
72 jsonExt.DecodeKeyed("$regex", jdecRegEx)
73 jsonExt.EncodeType(RegEx{}, jencRegEx)
74
75 funcExt.DecodeFunc("ObjectId", "$oidFunc", "Id")
76 jsonExt.DecodeKeyed("$oid", jdecObjectId)
77 jsonExt.DecodeKeyed("$oidFunc", jdecObjectId)
78 jsonExt.EncodeType(ObjectId(""), jencObjectId)
79
80 funcExt.DecodeFunc("DBRef", "$dbrefFunc", "$ref", "$id")
81 jsonExt.DecodeKeyed("$dbrefFunc", jdecDBRef)
82
83 funcExt.DecodeFunc("NumberLong", "$numberLongFunc", "N")
84 jsonExt.DecodeKeyed("$numberLong", jdecNumberLong)
85 jsonExt.DecodeKeyed("$numberLongFunc", jdecNumberLong)
86 jsonExt.EncodeType(int64(0), jencNumberLong)
87 jsonExt.EncodeType(int(0), jencInt)
88
89 funcExt.DecodeConst("MinKey", MinKey)
90 funcExt.DecodeConst("MaxKey", MaxKey)
91 jsonExt.DecodeKeyed("$minKey", jdecMinKey)
92 jsonExt.DecodeKeyed("$maxKey", jdecMaxKey)
93 jsonExt.EncodeType(orderKey(0), jencMinMaxKey)
94
95 jsonExt.DecodeKeyed("$undefined", jdecUndefined)
96 jsonExt.EncodeType(Undefined, jencUndefined)
97
98 jsonExt.Extend(&funcExt)
99}
100
101func fbytes(format string, args ...interface{}) []byte {
102 var buf bytes.Buffer
103 fmt.Fprintf(&buf, format, args...)
104 return buf.Bytes()
105}
106
107func jdecBinary(data []byte) (interface{}, error) {
108 var v struct {
109 Binary []byte `json:"$binary"`
110 Type string `json:"$type"`
111 Func struct {
112 Binary []byte `json:"$binary"`
113 Type int64 `json:"$type"`
114 } `json:"$binaryFunc"`
115 }
116 err := jdec(data, &v)
117 if err != nil {
118 return nil, err
119 }
120
121 var binData []byte
122 var binKind int64
123 if v.Type == "" && v.Binary == nil {
124 binData = v.Func.Binary
125 binKind = v.Func.Type
126 } else if v.Type == "" {
127 return v.Binary, nil
128 } else {
129 binData = v.Binary
130 binKind, err = strconv.ParseInt(v.Type, 0, 64)
131 if err != nil {
132 binKind = -1
133 }
134 }
135
136 if binKind == 0 {
137 return binData, nil
138 }
139 if binKind < 0 || binKind > 255 {
140 return nil, fmt.Errorf("invalid type in binary object: %s", data)
141 }
142
143 return Binary{Kind: byte(binKind), Data: binData}, nil
144}
145
146func jencBinarySlice(v interface{}) ([]byte, error) {
147 in := v.([]byte)
148 out := make([]byte, base64.StdEncoding.EncodedLen(len(in)))
149 base64.StdEncoding.Encode(out, in)
150 return fbytes(`{"$binary":"%s","$type":"0x0"}`, out), nil
151}
152
153func jencBinaryType(v interface{}) ([]byte, error) {
154 in := v.(Binary)
155 out := make([]byte, base64.StdEncoding.EncodedLen(len(in.Data)))
156 base64.StdEncoding.Encode(out, in.Data)
157 return fbytes(`{"$binary":"%s","$type":"0x%x"}`, out, in.Kind), nil
158}
159
160const jdateFormat = "2006-01-02T15:04:05.999Z07:00"
161
162func jdecDate(data []byte) (interface{}, error) {
163 var v struct {
164 S string `json:"$date"`
165 Func struct {
166 S string
167 } `json:"$dateFunc"`
168 }
169 _ = jdec(data, &v)
170 if v.S == "" {
171 v.S = v.Func.S
172 }
173 if v.S != "" {
174 var errs []string
175 for _, format := range []string{jdateFormat, "2006-01-02"} {
176 t, err := time.Parse(format, v.S)
177 if err == nil {
178 return t, nil
179 }
180 errs = append(errs, err.Error())
181 }
182 return nil, fmt.Errorf("cannot parse date: %q [%s]", v.S, strings.Join(errs, ", "))
183 }
184
185 var vn struct {
186 Date struct {
187 N int64 `json:"$numberLong,string"`
188 } `json:"$date"`
189 Func struct {
190 S int64
191 } `json:"$dateFunc"`
192 }
193 err := jdec(data, &vn)
194 if err != nil {
195 return nil, fmt.Errorf("cannot parse date: %q", data)
196 }
197 n := vn.Date.N
198 if n == 0 {
199 n = vn.Func.S
200 }
201 return time.Unix(n/1000, n%1000*1e6).UTC(), nil
202}
203
204func jencDate(v interface{}) ([]byte, error) {
205 t := v.(time.Time)
206 return fbytes(`{"$date":%q}`, t.Format(jdateFormat)), nil
207}
208
209func jdecTimestamp(data []byte) (interface{}, error) {
210 var v struct {
211 Func struct {
212 T int32 `json:"t"`
213 I int32 `json:"i"`
214 } `json:"$timestamp"`
215 }
216 err := jdec(data, &v)
217 if err != nil {
218 return nil, err
219 }
220 return MongoTimestamp(uint64(v.Func.T)<<32 | uint64(uint32(v.Func.I))), nil
221}
222
223func jencTimestamp(v interface{}) ([]byte, error) {
224 ts := uint64(v.(MongoTimestamp))
225 return fbytes(`{"$timestamp":{"t":%d,"i":%d}}`, ts>>32, uint32(ts)), nil
226}
227
228func jdecRegEx(data []byte) (interface{}, error) {
229 var v struct {
230 Regex string `json:"$regex"`
231 Options string `json:"$options"`
232 }
233 err := jdec(data, &v)
234 if err != nil {
235 return nil, err
236 }
237 return RegEx{v.Regex, v.Options}, nil
238}
239
240func jencRegEx(v interface{}) ([]byte, error) {
241 re := v.(RegEx)
242 type regex struct {
243 Regex string `json:"$regex"`
244 Options string `json:"$options"`
245 }
246 return json.Marshal(regex{re.Pattern, re.Options})
247}
248
249func jdecObjectId(data []byte) (interface{}, error) {
250 var v struct {
251 Id string `json:"$oid"`
252 Func struct {
253 Id string
254 } `json:"$oidFunc"`
255 }
256 err := jdec(data, &v)
257 if err != nil {
258 return nil, err
259 }
260 if v.Id == "" {
261 v.Id = v.Func.Id
262 }
263 return ObjectIdHex(v.Id), nil
264}
265
266func jencObjectId(v interface{}) ([]byte, error) {
267 return fbytes(`{"$oid":"%s"}`, v.(ObjectId).Hex()), nil
268}
269
270func jdecDBRef(data []byte) (interface{}, error) {
271 // TODO Support unmarshaling $ref and $id into the input value.
272 var v struct {
273 Obj map[string]interface{} `json:"$dbrefFunc"`
274 }
275 // TODO Fix this. Must not be required.
276 v.Obj = make(map[string]interface{})
277 err := jdec(data, &v)
278 if err != nil {
279 return nil, err
280 }
281 return v.Obj, nil
282}
283
284func jdecNumberLong(data []byte) (interface{}, error) {
285 var v struct {
286 N int64 `json:"$numberLong,string"`
287 Func struct {
288 N int64 `json:",string"`
289 } `json:"$numberLongFunc"`
290 }
291 var vn struct {
292 N int64 `json:"$numberLong"`
293 Func struct {
294 N int64
295 } `json:"$numberLongFunc"`
296 }
297 err := jdec(data, &v)
298 if err != nil {
299 err = jdec(data, &vn)
300 v.N = vn.N
301 v.Func.N = vn.Func.N
302 }
303 if err != nil {
304 return nil, err
305 }
306 if v.N != 0 {
307 return v.N, nil
308 }
309 return v.Func.N, nil
310}
311
312func jencNumberLong(v interface{}) ([]byte, error) {
313 n := v.(int64)
314 f := `{"$numberLong":"%d"}`
315 if n <= 1<<53 {
316 f = `{"$numberLong":%d}`
317 }
318 return fbytes(f, n), nil
319}
320
321func jencInt(v interface{}) ([]byte, error) {
322 n := v.(int)
323 f := `{"$numberLong":"%d"}`
324 if int64(n) <= 1<<53 {
325 f = `%d`
326 }
327 return fbytes(f, n), nil
328}
329
330func jdecMinKey(data []byte) (interface{}, error) {
331 var v struct {
332 N int64 `json:"$minKey"`
333 }
334 err := jdec(data, &v)
335 if err != nil {
336 return nil, err
337 }
338 if v.N != 1 {
339 return nil, fmt.Errorf("invalid $minKey object: %s", data)
340 }
341 return MinKey, nil
342}
343
344func jdecMaxKey(data []byte) (interface{}, error) {
345 var v struct {
346 N int64 `json:"$maxKey"`
347 }
348 err := jdec(data, &v)
349 if err != nil {
350 return nil, err
351 }
352 if v.N != 1 {
353 return nil, fmt.Errorf("invalid $maxKey object: %s", data)
354 }
355 return MaxKey, nil
356}
357
358func jencMinMaxKey(v interface{}) ([]byte, error) {
359 switch v.(orderKey) {
360 case MinKey:
361 return []byte(`{"$minKey":1}`), nil
362 case MaxKey:
363 return []byte(`{"$maxKey":1}`), nil
364 }
365 panic(fmt.Sprintf("invalid $minKey/$maxKey value: %d", v))
366}
367
368func jdecUndefined(data []byte) (interface{}, error) {
369 var v struct {
370 B bool `json:"$undefined"`
371 }
372 err := jdec(data, &v)
373 if err != nil {
374 return nil, err
375 }
376 if !v.B {
377 return nil, fmt.Errorf("invalid $undefined object: %s", data)
378 }
379 return Undefined, nil
380}
381
382func jencUndefined(v interface{}) ([]byte, error) {
383 return []byte(`{"$undefined":true}`), nil
384}