Skip to content

Commit 41a95ff

Browse files
committed
What: add spec for array ops with []uint8 or []byte type
Why: * mongodb aquires array for $in/$nin/$all ops How: * encode with array for spec
1 parent 876956d commit 41a95ff

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

bson/bson_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ import (
3434
"errors"
3535
"net/url"
3636
"reflect"
37+
"strings"
3738
"testing"
3839
"time"
39-
"strings"
4040

4141
"github.com/globalsign/mgo/bson"
4242
. "gopkg.in/check.v1"
@@ -111,6 +111,10 @@ var sampleItems = []testItemType{
111111
{bson.M{"BSON": []interface{}{"awesome", float64(5.05), 1986}},
112112
"1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
113113
"awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
114+
{bson.M{"slice": []uint8{1, 2}},
115+
"\x13\x00\x00\x00\x05slice\x00\x02\x00\x00\x00\x00\x01\x02\x00"},
116+
{bson.M{"slice": []byte{1, 2}},
117+
"\x13\x00\x00\x00\x05slice\x00\x02\x00\x00\x00\x00\x01\x02\x00"},
114118
}
115119

116120
func (s *S) TestMarshalSampleItems(c *C) {
@@ -343,6 +347,27 @@ func (s *S) TestOneWayMarshalItems(c *C) {
343347
}
344348
}
345349

350+
// --------------------------------------------------------------------------
351+
// Some ops marshaling operations which would encode []uint8 or []byte in array.
352+
353+
var arrayOpsMarshalItems = []testItemType{
354+
{bson.M{"_": bson.M{"$in": []uint8{1, 2}}},
355+
"\x03_\x00\x1d\x00\x00\x00\x04$in\x00\x13\x00\x00\x00\x100\x00\x01\x00\x00\x00\x101\x00\x02\x00\x00\x00\x00\x00"},
356+
{bson.M{"_": bson.M{"$nin": []uint8{1, 2}}},
357+
"\x03_\x00\x1e\x00\x00\x00\x04$nin\x00\x13\x00\x00\x00\x100\x00\x01\x00\x00\x00\x101\x00\x02\x00\x00\x00\x00\x00"},
358+
{bson.M{"_": bson.M{"$all": []uint8{1, 2}}},
359+
"\x03_\x00\x1e\x00\x00\x00\x04$all\x00\x13\x00\x00\x00\x100\x00\x01\x00\x00\x00\x101\x00\x02\x00\x00\x00\x00\x00"},
360+
}
361+
362+
func (s *S) TestArrayOpsMarshalItems(c *C) {
363+
for i, item := range arrayOpsMarshalItems {
364+
data, err := bson.Marshal(item.obj)
365+
c.Assert(err, IsNil)
366+
c.Assert(string(data), Equals, wrapInDoc(item.data),
367+
Commentf("Failed on item %d", i))
368+
}
369+
}
370+
346371
// --------------------------------------------------------------------------
347372
// Two-way tests for user-defined structures using the samples
348373
// from bsonspec.org.

bson/encode.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ var (
6060
typeTimeDuration = reflect.TypeOf(time.Duration(0))
6161
)
6262

63+
var (
64+
// spec for []uint8 or []byte encoding
65+
arrayOps = map[string]bool{
66+
"$in": true,
67+
"$nin": true,
68+
"$all": true,
69+
}
70+
)
71+
6372
const itoaCacheSize = 32
6473

6574
const (
@@ -423,8 +432,13 @@ func (e *encoder) addElem(name string, v reflect.Value, minSize bool) {
423432
vt := v.Type()
424433
et := vt.Elem()
425434
if et.Kind() == reflect.Uint8 {
426-
e.addElemName(0x05, name)
427-
e.addBinary(0x00, v.Bytes())
435+
if arrayOps[name] {
436+
e.addElemName(0x04, name)
437+
e.addDoc(v)
438+
} else {
439+
e.addElemName(0x05, name)
440+
e.addBinary(0x00, v.Bytes())
441+
}
428442
} else if et == typeDocElem || et == typeRawDocElem {
429443
e.addElemName(0x03, name)
430444
e.addDoc(v)
@@ -436,16 +450,21 @@ func (e *encoder) addElem(name string, v reflect.Value, minSize bool) {
436450
case reflect.Array:
437451
et := v.Type().Elem()
438452
if et.Kind() == reflect.Uint8 {
439-
e.addElemName(0x05, name)
440-
if v.CanAddr() {
441-
e.addBinary(0x00, v.Slice(0, v.Len()).Interface().([]byte))
453+
if arrayOps[name] {
454+
e.addElemName(0x04, name)
455+
e.addDoc(v)
442456
} else {
443-
n := v.Len()
444-
e.addInt32(int32(n))
445-
e.addBytes(0x00)
446-
for i := 0; i < n; i++ {
447-
el := v.Index(i)
448-
e.addBytes(byte(el.Uint()))
457+
e.addElemName(0x05, name)
458+
if v.CanAddr() {
459+
e.addBinary(0x00, v.Slice(0, v.Len()).Interface().([]byte))
460+
} else {
461+
n := v.Len()
462+
e.addInt32(int32(n))
463+
e.addBytes(0x00)
464+
for i := 0; i < n; i++ {
465+
el := v.Index(i)
466+
e.addBytes(byte(el.Uint()))
467+
}
449468
}
450469
}
451470
} else {

0 commit comments

Comments
 (0)