Skip to content

Commit 4fcd01b

Browse files
author
roman.tarasov
committed
fix pointers' decoding
1 parent 29a4d7d commit 4fcd01b

File tree

2 files changed

+1628
-180
lines changed

2 files changed

+1628
-180
lines changed

bson/decode.go

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ func (d *decoder) createEmptyValue(r Reader, t reflect.Type) (reflect.Value, err
306306
func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer reflect.Type) (reflect.Value, error) {
307307
var val reflect.Value
308308

309+
isPtr := (containerType.Kind() == reflect.Ptr)
310+
309311
for containerType.Kind() == reflect.Ptr {
310312
containerType = containerType.Elem()
311313
}
@@ -375,6 +377,7 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
375377
val = reflect.ValueOf(f)
376378
case tJSONNumber:
377379
val = reflect.ValueOf(strconv.FormatFloat(f, 'f', -1, 64)).Convert(tJSONNumber)
380+
378381
default:
379382
return val, nil
380383
}
@@ -384,6 +387,13 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
384387
switch containerType {
385388
case tString, tEmpty:
386389
val = reflect.ValueOf(str)
390+
case tJSONNumber:
391+
_, err := strconv.ParseFloat(str, 64)
392+
if err != nil {
393+
return val, err
394+
}
395+
val = reflect.ValueOf(str).Convert(tJSONNumber)
396+
387397
case tURL:
388398
u, err := url.Parse(str)
389399
if err != nil {
@@ -394,14 +404,24 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
394404
return val, nil
395405
}
396406
case 0x4:
407+
postProcess := func(isPtr bool, valueToProcess reflect.Value) reflect.Value {
408+
if !isPtr {
409+
return valueToProcess
410+
}
411+
valPtr := reflect.New(valueToProcess.Type())
412+
valPtr.Elem().Set(valueToProcess)
413+
return valPtr
414+
}
415+
397416
if containerType == tEmpty {
398417
d := newDecoder(bytes.NewBuffer(v.ReaderArray()))
399418
newVal, err := d.decodeBSONArrayToSlice(tEmptySlice)
400419
if err != nil {
401420
return val, err
402421
}
403422

404-
val = newVal
423+
val = postProcess(isPtr, newVal)
424+
isPtr = false
405425

406426
break
407427
}
@@ -413,7 +433,8 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
413433
return val, err
414434
}
415435

416-
val = newVal
436+
val = postProcess(isPtr, newVal)
437+
isPtr = false
417438

418439
break
419440
}
@@ -425,7 +446,8 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
425446
return val, err
426447
}
427448

428-
val = newVal
449+
val = postProcess(isPtr, newVal)
450+
isPtr = false
429451

430452
break
431453
}
@@ -453,6 +475,12 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
453475

454476
if reflect.PtrTo(typeToCreate) == empty.Type() {
455477
empty = empty.Elem()
478+
if isPtr {
479+
valPtr := reflect.New(empty.Type())
480+
valPtr.Elem().Set(empty)
481+
empty = valPtr
482+
isPtr = false
483+
}
456484
}
457485

458486
val = empty
@@ -495,6 +523,7 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
495523
} else {
496524
val = reflect.ValueOf(v.DateTime())
497525
}
526+
498527
case 0xA:
499528
if containerType != tEmpty {
500529
return val, nil
@@ -576,7 +605,6 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
576605
}
577606

578607
val = reflect.ValueOf(uint(i))
579-
580608
case tEmpty, tInt32, tInt64, tInt, tFloat32, tFloat64:
581609
val = reflect.ValueOf(i).Convert(containerType)
582610
case tJSONNumber:
@@ -669,6 +697,11 @@ func (d *decoder) getReflectValue(v *Value, containerType reflect.Type, outer re
669697
return val, fmt.Errorf("invalid BSON type: %s", v.Type())
670698
}
671699

700+
if isPtr && val.IsValid() && !val.CanAddr() {
701+
valPtr := reflect.New(val.Type())
702+
valPtr.Elem().Set(val)
703+
val = valPtr
704+
}
672705
return val, nil
673706
}
674707

@@ -739,7 +772,11 @@ func (d *decoder) decodeBSONArrayToSlice(sliceType reflect.Type) (reflect.Value,
739772
}
740773

741774
if sliceType.Elem().Kind() == reflect.Ptr {
742-
elem = elem.Addr()
775+
if elem.CanAddr() {
776+
elem = elem.Addr()
777+
} else {
778+
elem = elem.Elem().Addr()
779+
}
743780
}
744781
out.Index(i).Set(elem)
745782
}
@@ -875,7 +912,11 @@ func (d *decoder) decodeIntoStruct(structVal reflect.Value) error {
875912

876913
if v != zeroVal {
877914
if field.Type().Kind() == reflect.Ptr {
878-
v = v.Addr()
915+
if v.CanAddr() {
916+
v = v.Addr()
917+
} else {
918+
v = v.Elem().Addr()
919+
}
879920
}
880921

881922
field.Set(v)

0 commit comments

Comments
 (0)