blob: 658856add04b29ad39c189db35cc0c440778a4db [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// BSON library for Go
2//
3// Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
4//
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are met:
9//
10// 1. Redistributions of source code must retain the above copyright notice, this
11// list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright notice,
13// this list of conditions and the following disclaimer in the documentation
14// and/or other materials provided with the distribution.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26// gobson - BSON library for Go.
27
28package bson
29
30import (
31 "errors"
32 "fmt"
33 "io"
34 "math"
35 "net/url"
36 "reflect"
37 "strconv"
38 "sync"
39 "time"
40)
41
42type decoder struct {
43 in []byte
44 i int
45 docType reflect.Type
46}
47
48var typeM = reflect.TypeOf(M{})
49
50func newDecoder(in []byte) *decoder {
51 return &decoder{in, 0, typeM}
52}
53
54// --------------------------------------------------------------------------
55// Some helper functions.
56
57func corrupted() {
58 panic("Document is corrupted")
59}
60
61// --------------------------------------------------------------------------
62// Unmarshaling of documents.
63
64const (
65 setterUnknown = iota
66 setterNone
67 setterType
68 setterAddr
69)
70
71var setterStyles map[reflect.Type]int
72var setterIface reflect.Type
73var setterMutex sync.RWMutex
74
75func init() {
76 var iface Setter
77 setterIface = reflect.TypeOf(&iface).Elem()
78 setterStyles = make(map[reflect.Type]int)
79}
80
81func setterStyle(outt reflect.Type) int {
82 setterMutex.RLock()
83 style := setterStyles[outt]
84 setterMutex.RUnlock()
85 if style != setterUnknown {
86 return style
87 }
88
89 setterMutex.Lock()
90 defer setterMutex.Unlock()
91 if outt.Implements(setterIface) {
92 style = setterType
93 } else if reflect.PtrTo(outt).Implements(setterIface) {
94 style = setterAddr
95 } else {
96 style = setterNone
97 }
98 setterStyles[outt] = style
99 return style
100}
101
102func getSetter(outt reflect.Type, out reflect.Value) Setter {
103 style := setterStyle(outt)
104 if style == setterNone {
105 return nil
106 }
107 if style == setterAddr {
108 if !out.CanAddr() {
109 return nil
110 }
111 out = out.Addr()
112 } else if outt.Kind() == reflect.Ptr && out.IsNil() {
113 out.Set(reflect.New(outt.Elem()))
114 }
115 return out.Interface().(Setter)
116}
117
118func clearMap(m reflect.Value) {
119 var none reflect.Value
120 for _, k := range m.MapKeys() {
121 m.SetMapIndex(k, none)
122 }
123}
124
125func (d *decoder) readDocTo(out reflect.Value) {
126 var elemType reflect.Type
127 outt := out.Type()
128 outk := outt.Kind()
129
130 for {
131 if outk == reflect.Ptr && out.IsNil() {
132 out.Set(reflect.New(outt.Elem()))
133 }
134 if setter := getSetter(outt, out); setter != nil {
135 raw := d.readRaw(ElementDocument)
136 err := setter.SetBSON(raw)
137 if _, ok := err.(*TypeError); err != nil && !ok {
138 panic(err)
139 }
140 return
141 }
142 if outk == reflect.Ptr {
143 out = out.Elem()
144 outt = out.Type()
145 outk = out.Kind()
146 continue
147 }
148 break
149 }
150
151 var fieldsMap map[string]fieldInfo
152 var inlineMap reflect.Value
153 if outt == typeRaw {
154 out.Set(reflect.ValueOf(d.readRaw(ElementDocument)))
155 return
156 }
157
158 origout := out
159 if outk == reflect.Interface {
160 if d.docType.Kind() == reflect.Map {
161 mv := reflect.MakeMap(d.docType)
162 out.Set(mv)
163 out = mv
164 } else {
165 dv := reflect.New(d.docType).Elem()
166 out.Set(dv)
167 out = dv
168 }
169 outt = out.Type()
170 outk = outt.Kind()
171 }
172
173 docType := d.docType
174 keyType := typeString
175 convertKey := false
176 switch outk {
177 case reflect.Map:
178 keyType = outt.Key()
179 if keyType != typeString {
180 convertKey = true
181 }
182 elemType = outt.Elem()
183 if elemType == typeIface {
184 d.docType = outt
185 }
186 if out.IsNil() {
187 out.Set(reflect.MakeMap(out.Type()))
188 } else if out.Len() > 0 {
189 clearMap(out)
190 }
191 case reflect.Struct:
192 sinfo, err := getStructInfo(out.Type())
193 if err != nil {
194 panic(err)
195 }
196 fieldsMap = sinfo.FieldsMap
197 out.Set(sinfo.Zero)
198 if sinfo.InlineMap != -1 {
199 inlineMap = out.Field(sinfo.InlineMap)
200 if !inlineMap.IsNil() && inlineMap.Len() > 0 {
201 clearMap(inlineMap)
202 }
203 elemType = inlineMap.Type().Elem()
204 if elemType == typeIface {
205 d.docType = inlineMap.Type()
206 }
207 }
208 case reflect.Slice:
209 switch outt.Elem() {
210 case typeDocElem:
211 origout.Set(d.readDocElems(outt))
212 return
213 case typeRawDocElem:
214 origout.Set(d.readRawDocElems(outt))
215 return
216 }
217 fallthrough
218 default:
219 panic("Unsupported document type for unmarshalling: " + out.Type().String())
220 }
221
222 end := int(d.readInt32())
223 end += d.i - 4
224 if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
225 corrupted()
226 }
227 for d.in[d.i] != '\x00' {
228 kind := d.readByte()
229 name := d.readCStr()
230 if d.i >= end {
231 corrupted()
232 }
233
234 switch outk {
235 case reflect.Map:
236 e := reflect.New(elemType).Elem()
237 if d.readElemTo(e, kind) {
238 k := reflect.ValueOf(name)
239 if convertKey {
240 mapKeyType := out.Type().Key()
241 mapKeyKind := mapKeyType.Kind()
242
243 switch mapKeyKind {
244 case reflect.Int:
245 fallthrough
246 case reflect.Int8:
247 fallthrough
248 case reflect.Int16:
249 fallthrough
250 case reflect.Int32:
251 fallthrough
252 case reflect.Int64:
253 fallthrough
254 case reflect.Uint:
255 fallthrough
256 case reflect.Uint8:
257 fallthrough
258 case reflect.Uint16:
259 fallthrough
260 case reflect.Uint32:
261 fallthrough
262 case reflect.Uint64:
263 fallthrough
264 case reflect.Float32:
265 fallthrough
266 case reflect.Float64:
267 parsed := d.parseMapKeyAsFloat(k, mapKeyKind)
268 k = reflect.ValueOf(parsed)
269 case reflect.String:
270 mapKeyType = keyType
271 default:
272 panic("BSON map must have string or decimal keys. Got: " + outt.String())
273 }
274
275 k = k.Convert(mapKeyType)
276 }
277 out.SetMapIndex(k, e)
278 }
279 case reflect.Struct:
280 if info, ok := fieldsMap[name]; ok {
281 if info.Inline == nil {
282 d.readElemTo(out.Field(info.Num), kind)
283 } else {
284 d.readElemTo(out.FieldByIndex(info.Inline), kind)
285 }
286 } else if inlineMap.IsValid() {
287 if inlineMap.IsNil() {
288 inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
289 }
290 e := reflect.New(elemType).Elem()
291 if d.readElemTo(e, kind) {
292 inlineMap.SetMapIndex(reflect.ValueOf(name), e)
293 }
294 } else {
295 d.dropElem(kind)
296 }
297 case reflect.Slice:
298 }
299
300 if d.i >= end {
301 corrupted()
302 }
303 }
304 d.i++ // '\x00'
305 if d.i != end {
306 corrupted()
307 }
308 d.docType = docType
309}
310
311func (decoder) parseMapKeyAsFloat(k reflect.Value, mapKeyKind reflect.Kind) float64 {
312 parsed, err := strconv.ParseFloat(k.String(), 64)
313 if err != nil {
314 panic("Map key is defined to be a decimal type (" + mapKeyKind.String() + ") but got error " +
315 err.Error())
316 }
317
318 return parsed
319}
320
321func (d *decoder) readArrayDocTo(out reflect.Value) {
322 end := int(d.readInt32())
323 end += d.i - 4
324 if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
325 corrupted()
326 }
327 i := 0
328 l := out.Len()
329 for d.in[d.i] != '\x00' {
330 if i >= l {
331 panic("Length mismatch on array field")
332 }
333 kind := d.readByte()
334 for d.i < end && d.in[d.i] != '\x00' {
335 d.i++
336 }
337 if d.i >= end {
338 corrupted()
339 }
340 d.i++
341 d.readElemTo(out.Index(i), kind)
342 if d.i >= end {
343 corrupted()
344 }
345 i++
346 }
347 if i != l {
348 panic("Length mismatch on array field")
349 }
350 d.i++ // '\x00'
351 if d.i != end {
352 corrupted()
353 }
354}
355
356func (d *decoder) readSliceDoc(t reflect.Type) interface{} {
357 tmp := make([]reflect.Value, 0, 8)
358 elemType := t.Elem()
359 if elemType == typeRawDocElem {
360 d.dropElem(ElementArray)
361 return reflect.Zero(t).Interface()
362 }
363 if elemType == typeRaw {
364 return d.readSliceOfRaw()
365 }
366
367 end := int(d.readInt32())
368 end += d.i - 4
369 if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
370 corrupted()
371 }
372 for d.in[d.i] != '\x00' {
373 kind := d.readByte()
374 for d.i < end && d.in[d.i] != '\x00' {
375 d.i++
376 }
377 if d.i >= end {
378 corrupted()
379 }
380 d.i++
381 e := reflect.New(elemType).Elem()
382 if d.readElemTo(e, kind) {
383 tmp = append(tmp, e)
384 }
385 if d.i >= end {
386 corrupted()
387 }
388 }
389 d.i++ // '\x00'
390 if d.i != end {
391 corrupted()
392 }
393
394 n := len(tmp)
395 slice := reflect.MakeSlice(t, n, n)
396 for i := 0; i != n; i++ {
397 slice.Index(i).Set(tmp[i])
398 }
399 return slice.Interface()
400}
401
402func BSONElementSize(kind byte, offset int, buffer []byte) (int, error) {
403 switch kind {
404 case ElementFloat64: // Float64
405 return 8, nil
406 case ElementJavaScriptWithoutScope: // JavaScript without scope
407 fallthrough
408 case ElementSymbol: // Symbol
409 fallthrough
410 case ElementString: // UTF-8 string
411 size, err := getSize(offset, buffer)
412 if err != nil {
413 return 0, err
414 }
415 if size < 1 {
416 return 0, errors.New("String size can't be less then one byte")
417 }
418 size += 4
419 if offset+size > len(buffer) {
420 return 0, io.ErrUnexpectedEOF
421 }
422 if buffer[offset+size-1] != 0 {
423 return 0, errors.New("Invalid string: non zero-terminated")
424 }
425 return size, nil
426 case ElementArray: // Array
427 fallthrough
428 case ElementDocument: // Document
429 size, err := getSize(offset, buffer)
430 if err != nil {
431 return 0, err
432 }
433 if size < 5 {
434 return 0, errors.New("Declared document size is too small")
435 }
436 return size, nil
437 case ElementBinary: // Binary
438 size, err := getSize(offset, buffer)
439 if err != nil {
440 return 0, err
441 }
442 if size < 0 {
443 return 0, errors.New("Binary data size can't be negative")
444 }
445 return size + 5, nil
446 case Element06: // Undefined (obsolete, but still seen in the wild)
447 return 0, nil
448 case ElementObjectId: // ObjectId
449 return 12, nil
450 case ElementBool: // Bool
451 return 1, nil
452 case ElementDatetime: // Timestamp
453 return 8, nil
454 case ElementNil: // Nil
455 return 0, nil
456 case ElementRegEx: // RegEx
457 end := offset
458 for i := 0; i < 2; i++ {
459 for end < len(buffer) && buffer[end] != '\x00' {
460 end++
461 }
462 end++
463 }
464 if end > len(buffer) {
465 return 0, io.ErrUnexpectedEOF
466 }
467 return end - offset, nil
468 case ElementDBPointer: // DBPointer
469 size, err := getSize(offset, buffer)
470 if err != nil {
471 return 0, err
472 }
473 if size < 1 {
474 return 0, errors.New("String size can't be less then one byte")
475 }
476 return size + 12 + 4, nil
477 case ElementJavaScriptWithScope: // JavaScript with scope
478 size, err := getSize(offset, buffer)
479 if err != nil {
480 return 0, err
481 }
482 if size < 4+5+5 {
483 return 0, errors.New("Declared document element is too small")
484 }
485 return size, nil
486 case ElementInt32: // Int32
487 return 4, nil
488 case ElementTimestamp: // Mongo-specific timestamp
489 return 8, nil
490 case ElementInt64: // Int64
491 return 8, nil
492 case ElementDecimal128: // Decimal128
493 return 16, nil
494 case ElementMaxKey: // Max key
495 return 0, nil
496 case ElementMinKey: // Min key
497 return 0, nil
498 default:
499 return 0, errors.New(fmt.Sprintf("Unknown element kind (0x%02X)", kind))
500 }
501}
502
503func (d *decoder) readRaw(kind byte) Raw {
504 size, err := BSONElementSize(kind, d.i, d.in)
505 if err != nil {
506 corrupted()
507 }
508 if d.i+size > len(d.in) {
509 corrupted()
510 }
511 d.i += size
512 return Raw{
513 Kind: kind,
514 Data: d.in[d.i-size : d.i],
515 }
516}
517
518func (d *decoder) readSliceOfRaw() interface{} {
519 tmp := make([]Raw, 0, 8)
520 end := int(d.readInt32())
521 end += d.i - 4
522 if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
523 corrupted()
524 }
525 for d.in[d.i] != '\x00' {
526 kind := d.readByte()
527 for d.i < end && d.in[d.i] != '\x00' {
528 d.i++
529 }
530 if d.i >= end {
531 corrupted()
532 }
533 d.i++
534 e := d.readRaw(kind)
535 tmp = append(tmp, e)
536 if d.i >= end {
537 corrupted()
538 }
539 }
540 d.i++ // '\x00'
541 if d.i != end {
542 corrupted()
543 }
544 return tmp
545}
546
547var typeSlice = reflect.TypeOf([]interface{}{})
548var typeIface = typeSlice.Elem()
549
550func (d *decoder) readDocElems(typ reflect.Type) reflect.Value {
551 docType := d.docType
552 d.docType = typ
553 slice := make([]DocElem, 0, 8)
554 d.readDocWith(func(kind byte, name string) {
555 e := DocElem{Name: name}
556 v := reflect.ValueOf(&e.Value)
557 if d.readElemTo(v.Elem(), kind) {
558 slice = append(slice, e)
559 }
560 })
561 slicev := reflect.New(typ).Elem()
562 slicev.Set(reflect.ValueOf(slice))
563 d.docType = docType
564 return slicev
565}
566
567func (d *decoder) readRawDocElems(typ reflect.Type) reflect.Value {
568 docType := d.docType
569 d.docType = typ
570 slice := make([]RawDocElem, 0, 8)
571 d.readDocWith(func(kind byte, name string) {
572 e := RawDocElem{Name: name, Value: d.readRaw(kind)}
573 slice = append(slice, e)
574 })
575 slicev := reflect.New(typ).Elem()
576 slicev.Set(reflect.ValueOf(slice))
577 d.docType = docType
578 return slicev
579}
580
581func (d *decoder) readDocWith(f func(kind byte, name string)) {
582 end := int(d.readInt32())
583 end += d.i - 4
584 if end <= d.i || end > len(d.in) || d.in[end-1] != '\x00' {
585 corrupted()
586 }
587 for d.in[d.i] != '\x00' {
588 kind := d.readByte()
589 name := d.readCStr()
590 if d.i >= end {
591 corrupted()
592 }
593 f(kind, name)
594 if d.i >= end {
595 corrupted()
596 }
597 }
598 d.i++ // '\x00'
599 if d.i != end {
600 corrupted()
601 }
602}
603
604// --------------------------------------------------------------------------
605// Unmarshaling of individual elements within a document.
606func (d *decoder) dropElem(kind byte) {
607 size, err := BSONElementSize(kind, d.i, d.in)
608 if err != nil {
609 corrupted()
610 }
611 if d.i+size > len(d.in) {
612 corrupted()
613 }
614 d.i += size
615}
616
617// Attempt to decode an element from the document and put it into out.
618// If the types are not compatible, the returned ok value will be
619// false and out will be unchanged.
620func (d *decoder) readElemTo(out reflect.Value, kind byte) (good bool) {
621 outt := out.Type()
622
623 if outt == typeRaw {
624 out.Set(reflect.ValueOf(d.readRaw(kind)))
625 return true
626 }
627
628 if outt == typeRawPtr {
629 raw := d.readRaw(kind)
630 out.Set(reflect.ValueOf(&raw))
631 return true
632 }
633
634 if kind == ElementDocument {
635 // Delegate unmarshaling of documents.
636 outt := out.Type()
637 outk := out.Kind()
638 switch outk {
639 case reflect.Interface, reflect.Ptr, reflect.Struct, reflect.Map:
640 d.readDocTo(out)
641 return true
642 }
643 if setterStyle(outt) != setterNone {
644 d.readDocTo(out)
645 return true
646 }
647 if outk == reflect.Slice {
648 switch outt.Elem() {
649 case typeDocElem:
650 out.Set(d.readDocElems(outt))
651 case typeRawDocElem:
652 out.Set(d.readRawDocElems(outt))
653 default:
654 d.dropElem(kind)
655 }
656 return true
657 }
658 d.dropElem(kind)
659 return true
660 }
661
662 if setter := getSetter(outt, out); setter != nil {
663 err := setter.SetBSON(d.readRaw(kind))
664 if err == ErrSetZero {
665 out.Set(reflect.Zero(outt))
666 return true
667 }
668 if err == nil {
669 return true
670 }
671 if _, ok := err.(*TypeError); !ok {
672 panic(err)
673 }
674 return false
675 }
676
677 var in interface{}
678
679 switch kind {
680 case ElementFloat64:
681 in = d.readFloat64()
682 case ElementString:
683 in = d.readStr()
684 case ElementDocument:
685 panic("Can't happen. Handled above.")
686 case ElementArray:
687 outt := out.Type()
688 if setterStyle(outt) != setterNone {
689 // Skip the value so its data is handed to the setter below.
690 d.dropElem(kind)
691 break
692 }
693 for outt.Kind() == reflect.Ptr {
694 outt = outt.Elem()
695 }
696 switch outt.Kind() {
697 case reflect.Array:
698 d.readArrayDocTo(out)
699 return true
700 case reflect.Slice:
701 in = d.readSliceDoc(outt)
702 default:
703 in = d.readSliceDoc(typeSlice)
704 }
705 case ElementBinary:
706 b := d.readBinary()
707 if b.Kind == BinaryGeneric || b.Kind == BinaryBinaryOld {
708 in = b.Data
709 } else {
710 in = b
711 }
712 case Element06: // Undefined (obsolete, but still seen in the wild)
713 in = Undefined
714 case ElementObjectId:
715 in = ObjectId(d.readBytes(12))
716 case ElementBool:
717 in = d.readBool()
718 case ElementDatetime: // Timestamp
719 // MongoDB handles timestamps as milliseconds.
720 i := d.readInt64()
721 if i == -62135596800000 {
722 in = time.Time{} // In UTC for convenience.
723 } else {
724 in = time.Unix(i/1e3, i%1e3*1e6).UTC()
725 }
726 case ElementNil:
727 in = nil
728 case ElementRegEx:
729 in = d.readRegEx()
730 case ElementDBPointer:
731 in = DBPointer{Namespace: d.readStr(), Id: ObjectId(d.readBytes(12))}
732 case ElementJavaScriptWithoutScope:
733 in = JavaScript{Code: d.readStr()}
734 case ElementSymbol:
735 in = Symbol(d.readStr())
736 case ElementJavaScriptWithScope:
737 start := d.i
738 l := int(d.readInt32())
739 js := JavaScript{d.readStr(), make(M)}
740 d.readDocTo(reflect.ValueOf(js.Scope))
741 if d.i != start+l {
742 corrupted()
743 }
744 in = js
745 case ElementInt32:
746 in = int(d.readInt32())
747 case ElementTimestamp: // Mongo-specific timestamp
748 in = MongoTimestamp(d.readInt64())
749 case ElementInt64:
750 switch out.Type() {
751 case typeTimeDuration:
752 in = time.Duration(time.Duration(d.readInt64()) * time.Millisecond)
753 default:
754 in = d.readInt64()
755 }
756 case ElementDecimal128:
757 in = Decimal128{
758 l: uint64(d.readInt64()),
759 h: uint64(d.readInt64()),
760 }
761 case ElementMaxKey:
762 in = MaxKey
763 case ElementMinKey:
764 in = MinKey
765 default:
766 panic(fmt.Sprintf("Unknown element kind (0x%02X)", kind))
767 }
768
769 if in == nil {
770 out.Set(reflect.Zero(outt))
771 return true
772 }
773
774 outk := outt.Kind()
775
776 // Dereference and initialize pointer if necessary.
777 first := true
778 for outk == reflect.Ptr {
779 if !out.IsNil() {
780 out = out.Elem()
781 } else {
782 elem := reflect.New(outt.Elem())
783 if first {
784 // Only set if value is compatible.
785 first = false
786 defer func(out, elem reflect.Value) {
787 if good {
788 out.Set(elem)
789 }
790 }(out, elem)
791 } else {
792 out.Set(elem)
793 }
794 out = elem
795 }
796 outt = out.Type()
797 outk = outt.Kind()
798 }
799
800 inv := reflect.ValueOf(in)
801 if outt == inv.Type() {
802 out.Set(inv)
803 return true
804 }
805
806 switch outk {
807 case reflect.Interface:
808 out.Set(inv)
809 return true
810 case reflect.String:
811 switch inv.Kind() {
812 case reflect.String:
813 out.SetString(inv.String())
814 return true
815 case reflect.Slice:
816 if b, ok := in.([]byte); ok {
817 out.SetString(string(b))
818 return true
819 }
820 case reflect.Int, reflect.Int64:
821 if outt == typeJSONNumber {
822 out.SetString(strconv.FormatInt(inv.Int(), 10))
823 return true
824 }
825 case reflect.Float64:
826 if outt == typeJSONNumber {
827 out.SetString(strconv.FormatFloat(inv.Float(), 'f', -1, 64))
828 return true
829 }
830 }
831 case reflect.Slice, reflect.Array:
832 // Remember, array (0x04) slices are built with the correct
833 // element type. If we are here, must be a cross BSON kind
834 // conversion (e.g. 0x05 unmarshalling on string).
835 if outt.Elem().Kind() != reflect.Uint8 {
836 break
837 }
838 switch inv.Kind() {
839 case reflect.String:
840 slice := []byte(inv.String())
841 out.Set(reflect.ValueOf(slice))
842 return true
843 case reflect.Slice:
844 switch outt.Kind() {
845 case reflect.Array:
846 reflect.Copy(out, inv)
847 case reflect.Slice:
848 out.SetBytes(inv.Bytes())
849 }
850 return true
851 }
852 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
853 switch inv.Kind() {
854 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
855 out.SetInt(inv.Int())
856 return true
857 case reflect.Float32, reflect.Float64:
858 out.SetInt(int64(inv.Float()))
859 return true
860 case reflect.Bool:
861 if inv.Bool() {
862 out.SetInt(1)
863 } else {
864 out.SetInt(0)
865 }
866 return true
867 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
868 panic("can't happen: no uint types in BSON (!?)")
869 }
870 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
871 switch inv.Kind() {
872 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
873 out.SetUint(uint64(inv.Int()))
874 return true
875 case reflect.Float32, reflect.Float64:
876 out.SetUint(uint64(inv.Float()))
877 return true
878 case reflect.Bool:
879 if inv.Bool() {
880 out.SetUint(1)
881 } else {
882 out.SetUint(0)
883 }
884 return true
885 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
886 panic("Can't happen. No uint types in BSON.")
887 }
888 case reflect.Float32, reflect.Float64:
889 switch inv.Kind() {
890 case reflect.Float32, reflect.Float64:
891 out.SetFloat(inv.Float())
892 return true
893 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
894 out.SetFloat(float64(inv.Int()))
895 return true
896 case reflect.Bool:
897 if inv.Bool() {
898 out.SetFloat(1)
899 } else {
900 out.SetFloat(0)
901 }
902 return true
903 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
904 panic("Can't happen. No uint types in BSON?")
905 }
906 case reflect.Bool:
907 switch inv.Kind() {
908 case reflect.Bool:
909 out.SetBool(inv.Bool())
910 return true
911 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
912 out.SetBool(inv.Int() != 0)
913 return true
914 case reflect.Float32, reflect.Float64:
915 out.SetBool(inv.Float() != 0)
916 return true
917 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
918 panic("Can't happen. No uint types in BSON?")
919 }
920 case reflect.Struct:
921 if outt == typeURL && inv.Kind() == reflect.String {
922 u, err := url.Parse(inv.String())
923 if err != nil {
924 panic(err)
925 }
926 out.Set(reflect.ValueOf(u).Elem())
927 return true
928 }
929 if outt == typeBinary {
930 if b, ok := in.([]byte); ok {
931 out.Set(reflect.ValueOf(Binary{Data: b}))
932 return true
933 }
934 }
935 }
936
937 return false
938}
939
940// --------------------------------------------------------------------------
941// Parsers of basic types.
942
943func (d *decoder) readRegEx() RegEx {
944 re := RegEx{}
945 re.Pattern = d.readCStr()
946 re.Options = d.readCStr()
947 return re
948}
949
950func (d *decoder) readBinary() Binary {
951 l := d.readInt32()
952 b := Binary{}
953 b.Kind = d.readByte()
954 if b.Kind == BinaryBinaryOld && l > 4 {
955 // Weird obsolete format with redundant length.
956 rl := d.readInt32()
957 if rl != l-4 {
958 corrupted()
959 }
960 l = rl
961 }
962 b.Data = d.readBytes(l)
963 return b
964}
965
966func (d *decoder) readStr() string {
967 l := d.readInt32()
968 b := d.readBytes(l - 1)
969 if d.readByte() != '\x00' {
970 corrupted()
971 }
972 return string(b)
973}
974
975func (d *decoder) readCStr() string {
976 start := d.i
977 end := start
978 l := len(d.in)
979 for ; end != l; end++ {
980 if d.in[end] == '\x00' {
981 break
982 }
983 }
984 d.i = end + 1
985 if d.i > l {
986 corrupted()
987 }
988 return string(d.in[start:end])
989}
990
991func (d *decoder) readBool() bool {
992 b := d.readByte()
993 if b == 0 {
994 return false
995 }
996 if b == 1 {
997 return true
998 }
999 panic(fmt.Sprintf("encoded boolean must be 1 or 0, found %d", b))
1000}
1001
1002func (d *decoder) readFloat64() float64 {
1003 return math.Float64frombits(uint64(d.readInt64()))
1004}
1005
1006func (d *decoder) readInt32() int32 {
1007 b := d.readBytes(4)
1008 return int32((uint32(b[0]) << 0) |
1009 (uint32(b[1]) << 8) |
1010 (uint32(b[2]) << 16) |
1011 (uint32(b[3]) << 24))
1012}
1013
1014func getSize(offset int, b []byte) (int, error) {
1015 if offset+4 > len(b) {
1016 return 0, io.ErrUnexpectedEOF
1017 }
1018 return int((uint32(b[offset]) << 0) |
1019 (uint32(b[offset+1]) << 8) |
1020 (uint32(b[offset+2]) << 16) |
1021 (uint32(b[offset+3]) << 24)), nil
1022}
1023
1024func (d *decoder) readInt64() int64 {
1025 b := d.readBytes(8)
1026 return int64((uint64(b[0]) << 0) |
1027 (uint64(b[1]) << 8) |
1028 (uint64(b[2]) << 16) |
1029 (uint64(b[3]) << 24) |
1030 (uint64(b[4]) << 32) |
1031 (uint64(b[5]) << 40) |
1032 (uint64(b[6]) << 48) |
1033 (uint64(b[7]) << 56))
1034}
1035
1036func (d *decoder) readByte() byte {
1037 i := d.i
1038 d.i++
1039 if d.i > len(d.in) {
1040 corrupted()
1041 }
1042 return d.in[i]
1043}
1044
1045func (d *decoder) readBytes(length int32) []byte {
1046 if length < 0 {
1047 corrupted()
1048 }
1049 start := d.i
1050 d.i += int(length)
1051 if d.i < start || d.i > len(d.in) {
1052 corrupted()
1053 }
1054 return d.in[start : start+int(length)]
1055}