Skip to content

Commit

Permalink
Add new BSON decoding package (FerretDB#3905)
Browse files Browse the repository at this point in the history
Closes #3759.
  • Loading branch information
AlekSi authored Jan 17, 2024
1 parent 21ebe3a commit 562d767
Show file tree
Hide file tree
Showing 19 changed files with 1,739 additions and 8 deletions.
13 changes: 13 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,21 @@ linters-settings:
files:
- $all
- "!**/internal/wire/*.go"
- "!**/internal/bson2/*_test.go"
deny:
- pkg: github.com/FerretDB/FerretDB/internal/bson
bson2:
files:
- $all
deny:
- pkg: github.com/FerretDB/FerretDB/internal/bson2
bsonproto:
files:
- $all
- "!**/internal/bson2/*.go"
deny:
- pkg: github.com/cristalhq/bson
- pkg: github.com/cristalhq/bson/bsonproto
sjson:
files:
- $all
Expand Down
10 changes: 2 additions & 8 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -338,16 +338,10 @@ tasks:
- go test -count=0 ./...

fuzz:
desc: "Fuzz for about 3 minutes (with default FUZZ_TIME)"
desc: "Fuzz for about 1 minute (with default FUZZ_TIME)"
cmds:
- go test -list='Fuzz.*' ./...
# TODO https://github.com/FerretDB/FerretDB/issues/1273
# - go test -run=XXX -fuzz=FuzzArrayWithFixedSchemas -fuzztime={{.FUZZ_TIME}} ./internal/handler/sjson/
# - go test -run=XXX -fuzz=FuzzArrayWithFixedDocuments -fuzztime={{.FUZZ_TIME}} ./internal/handler/sjson/
# - go test -run=XXX -fuzz=FuzzDocumentWithFixedSchemas -fuzztime={{.FUZZ_TIME}} ./internal/handler/sjson/
# - go test -run=XXX -fuzz=FuzzDocumentWithFixedDocuments -fuzztime={{.FUZZ_TIME}} ./internal/handler/sjson/
- go test -run=XXX -fuzz=FuzzArray -fuzztime={{.FUZZ_TIME}} ./internal/bson/
- go test -run=XXX -fuzz=FuzzDocument -fuzztime={{.FUZZ_TIME}} ./internal/bson/
- go test -run=XXX -fuzz=FuzzDocument -fuzztime={{.FUZZ_TIME}} ./internal/bson2/
- go test -run=XXX -fuzz=FuzzMsg -fuzztime={{.FUZZ_TIME}} ./internal/wire/
- go test -run=XXX -fuzz=FuzzQuery -fuzztime={{.FUZZ_TIME}} ./internal/wire/
- go test -run=XXX -fuzz=FuzzReply -fuzztime={{.FUZZ_TIME}} ./internal/wire/
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/SAP/go-hdb v1.7.1
github.com/alecthomas/kong v0.8.1
github.com/arl/statsviz v0.6.0
github.com/cristalhq/bson v0.0.8-0.20240102124511-ad00c9874d78
github.com/go-sql-driver/mysql v1.7.1
github.com/google/uuid v1.5.0
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqy
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cristalhq/bson v0.0.8-0.20240102124511-ad00c9874d78 h1:UC6ggM/RJ0ibp1PwpOpFQnlaRVtoPJ6ZNsePNenlSC8=
github.com/cristalhq/bson v0.0.8-0.20240102124511-ad00c9874d78/go.mod h1:oMahOeK6u+O0cAC7ZAuxYvFatYqEcl6XRp3FZ51j5dA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
98 changes: 98 additions & 0 deletions internal/bson2/array.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2021 FerretDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bson2

import (
"errors"
"log/slog"

"github.com/FerretDB/FerretDB/internal/types"
"github.com/FerretDB/FerretDB/internal/util/iterator"
"github.com/FerretDB/FerretDB/internal/util/lazyerrors"
)

// RawArray represents a BSON array in the binary encoded form.
//
// It generally references a part of a larger slice, not a copy.
type RawArray []byte

// LogValue implements slog.LogValuer interface.
func (arr *RawArray) LogValue() slog.Value {
return slogValue(arr)
}

// Array represents a BSON array in the (partially) decoded form.
type Array struct {
elements []any
}

// ConvertArray converts [*types.Array] to Array.
func ConvertArray(arr *types.Array) (*Array, error) {
iter := arr.Iterator()
defer iter.Close()

elements := make([]any, arr.Len())

for {
i, v, err := iter.Next()
if err != nil {
if errors.Is(err, iterator.ErrIteratorDone) {
return &Array{
elements: elements,
}, nil
}

return nil, lazyerrors.Error(err)
}

v, err = convertFromTypes(v)
if err != nil {
return nil, lazyerrors.Error(err)
}

elements[i] = v
}
}

// Convert converts Array to [*types.Array], decoding raw documents and arrays on the fly.
func (arr *Array) Convert() (*types.Array, error) {
values := make([]any, len(arr.elements))

for i, f := range arr.elements {
v, err := convertToTypes(f)
if err != nil {
return nil, lazyerrors.Error(err)
}

values[i] = v
}

res, err := types.NewArray(values...)
if err != nil {
return nil, lazyerrors.Error(err)
}

return res, nil
}

// LogValue implements slog.LogValuer interface.
func (arr *Array) LogValue() slog.Value {
return slogValue(arr)
}

// check interfaces
var (
_ slog.LogValuer = (*Array)(nil)
)
Loading

0 comments on commit 562d767

Please sign in to comment.