Skip to content

Commit

Permalink
bson: support all non-deprecated types and fix int/uint bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewdale committed Apr 30, 2023
1 parent b2cb5c3 commit 2017ff8
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 108 deletions.
4 changes: 4 additions & 0 deletions doc/formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,10 @@ bplist> from_ns_keyed_archiver(1)

## bson

Limitations:

- The decimal128 type is not supported for decoding, will just be treated as binary

### Convert represented value to JSON

```
Expand Down
87 changes: 52 additions & 35 deletions format/bson/bson.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package bson

// https://bsonspec.org/spec.html
// TODO: more types

import (
"embed"
Expand All @@ -27,42 +26,50 @@ func init() {
}

const (
elementTypeDouble = 0x01
elementTypeString = 0x02
elementTypeDocument = 0x03
elementTypeArray = 0x04
elementTypeBinary = 0x05
elementTypeUndefined = 0x06
elementTypeObjectID = 0x07
elementTypeBoolean = 0x08
elementTypeDatatime = 0x09
elementTypeNull = 0x0a
elementTypeRegexp = 0x0b
elementTypeInt32 = 0x10
elementTypeTimestamp = 0x11
elementTypeInt64 = 0x12
elementTypeDouble = 0x01
elementTypeString = 0x02
elementTypeDocument = 0x03
elementTypeArray = 0x04
elementTypeBinary = 0x05
elementTypeUndefined = 0x06
elementTypeObjectID = 0x07
elementTypeBoolean = 0x08
elementTypeDatetime = 0x09
elementTypeNull = 0x0a
elementTypeRegexp = 0x0b
elementTypeJavaScript = 0x0d
elementTypeInt32 = 0x10
elementTypeTimestamp = 0x11
elementTypeInt64 = 0x12
elementTypeDecimal128 = 0x13
elementTypeMinKey = 0xFF
elementTypeMaxKey = 0x7f
)

var elementTypeMap = scalar.UintMap{
elementTypeDouble: {Sym: "double", Description: "64-bit binary floating point"},
elementTypeString: {Sym: "string", Description: "UTF-8 string"},
elementTypeDocument: {Sym: "document", Description: "Embedded document"},
elementTypeArray: {Sym: "array", Description: "Array"},
elementTypeBinary: {Sym: "binary", Description: "Binary data"},
elementTypeUndefined: {Sym: "undefined", Description: "Undefined (deprecated)"},
elementTypeObjectID: {Sym: "object_id", Description: "ObjectId"},
elementTypeBoolean: {Sym: "boolean", Description: "Boolean"},
elementTypeDatatime: {Sym: "datatime", Description: "UTC datetime"},
elementTypeNull: {Sym: "null", Description: "Null value"},
elementTypeRegexp: {Sym: "regexp", Description: "Regular expression"},
elementTypeInt32: {Sym: "int32", Description: "32-bit integer"},
elementTypeTimestamp: {Sym: "timestamp", Description: "Timestamp"},
elementTypeInt64: {Sym: "int64", Description: "64-bit integer"},
elementTypeDouble: {Sym: "double", Description: "64-bit binary floating point"},
elementTypeString: {Sym: "string", Description: "UTF-8 string"},
elementTypeDocument: {Sym: "document", Description: "Embedded document"},
elementTypeArray: {Sym: "array", Description: "Array"},
elementTypeBinary: {Sym: "binary", Description: "Binary data"},
elementTypeUndefined: {Sym: "undefined", Description: "Undefined (deprecated)"},
elementTypeObjectID: {Sym: "object_id", Description: "ObjectId"},
elementTypeBoolean: {Sym: "boolean", Description: "Boolean"},
elementTypeDatetime: {Sym: "datetime", Description: "UTC datetime"},
elementTypeNull: {Sym: "null", Description: "Null value"},
elementTypeRegexp: {Sym: "regexp", Description: "Regular expression"},
elementTypeJavaScript: {Sym: "javascript", Description: "JavaScript code"},
elementTypeInt32: {Sym: "int32", Description: "32-bit integer"},
elementTypeTimestamp: {Sym: "timestamp", Description: "Timestamp"},
elementTypeInt64: {Sym: "int64", Description: "64-bit integer"},
elementTypeDecimal128: {Sym: "decimal128", Description: "128-bit decimal floating point"},
elementTypeMinKey: {Sym: "minkey", Description: "Min key"},
elementTypeMaxKey: {Sym: "maxkey", Description: "Max key"},
}

func decodeBSONDocument(d *decode.D) {
size := d.FieldU32("size")
d.FramedFn(int64(size-4)*8, func(d *decode.D) {
size := d.FieldS32("size")
d.FramedFn((size-4)*8, func(d *decode.D) {
d.FieldArray("elements", func(d *decode.D) {
for d.BitsLeft() > 8 {
d.FieldStruct("element", func(d *decode.D) {
Expand All @@ -79,28 +86,38 @@ func decodeBSONDocument(d *decode.D) {
case elementTypeArray:
d.FieldStruct("value", decodeBSONDocument)
case elementTypeBinary:
length := d.FieldU32("length")
length := d.FieldS32("length")
d.FieldU8("subtype")
d.FieldRawLen("value", int64(length)*8)
d.FieldRawLen("value", length*8)
case elementTypeUndefined:
//deprecated
case elementTypeObjectID:
d.FieldRawLen("value", 12*8)
case elementTypeBoolean:
d.FieldU8("value")
case elementTypeDatatime:
d.FieldS32("value")
case elementTypeDatetime:
d.FieldS64("value")
case elementTypeNull:
d.FieldValueAny("value", nil)
case elementTypeRegexp:
d.FieldUTF8Null("value")
d.FieldUTF8Null("options")
case elementTypeJavaScript:
length := d.FieldS32("length")
d.FieldUTF8NullFixedLen("value", int(length))
case elementTypeInt32:
d.FieldS32("value")
case elementTypeTimestamp:
d.FieldU64("value")
case elementTypeInt64:
d.FieldS64("value")
case elementTypeDecimal128:
// TODO: Parse the IEEE 754 decimal128 value.
d.FieldRawLen("value", 128)
case elementTypeMinKey:
d.FieldValueAny("value", nil)
case elementTypeMaxKey:
d.FieldValueAny("value", nil)
default:
d.FieldRawLen("value", d.BitsLeft())
}
Expand Down
Binary file modified format/bson/testdata/test.bson
Binary file not shown.

0 comments on commit 2017ff8

Please sign in to comment.