Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bson: support all non-deprecated types and fix int/uint bugs #650

Merged
merged 3 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

wader marked this conversation as resolved.
Show resolved Hide resolved
### 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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳


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) {
wader marked this conversation as resolved.
Show resolved Hide resolved
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)
wader marked this conversation as resolved.
Show resolved Hide resolved
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.
Loading