forked from gitea/gitea
157 lines
5.6 KiB
Go
157 lines
5.6 KiB
Go
// Copyright (C) MongoDB, Inc. 2017-present.
|
|
//
|
|
// 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
|
|
|
|
package bson
|
|
|
|
import (
|
|
"go.mongodb.org/mongo-driver/bson/bsoncodec"
|
|
"go.mongodb.org/mongo-driver/bson/bsonrw"
|
|
"go.mongodb.org/mongo-driver/bson/bsontype"
|
|
)
|
|
|
|
const defaultDstCap = 256
|
|
|
|
var bvwPool = bsonrw.NewBSONValueWriterPool()
|
|
var extjPool = bsonrw.NewExtJSONValueWriterPool()
|
|
|
|
// Marshaler is an interface implemented by types that can marshal themselves
|
|
// into a BSON document represented as bytes. The bytes returned must be a valid
|
|
// BSON document if the error is nil.
|
|
type Marshaler interface {
|
|
MarshalBSON() ([]byte, error)
|
|
}
|
|
|
|
// ValueMarshaler is an interface implemented by types that can marshal
|
|
// themselves into a BSON value as bytes. The type must be the valid type for
|
|
// the bytes returned. The bytes and byte type together must be valid if the
|
|
// error is nil.
|
|
type ValueMarshaler interface {
|
|
MarshalBSONValue() (bsontype.Type, []byte, error)
|
|
}
|
|
|
|
// Marshal returns the BSON encoding of val.
|
|
//
|
|
// Marshal will use the default registry created by NewRegistry to recursively
|
|
// marshal val into a []byte. Marshal will inspect struct tags and alter the
|
|
// marshaling process accordingly.
|
|
func Marshal(val interface{}) ([]byte, error) {
|
|
return MarshalWithRegistry(DefaultRegistry, val)
|
|
}
|
|
|
|
// MarshalAppend will append the BSON encoding of val to dst. If dst is not
|
|
// large enough to hold the BSON encoding of val, dst will be grown.
|
|
func MarshalAppend(dst []byte, val interface{}) ([]byte, error) {
|
|
return MarshalAppendWithRegistry(DefaultRegistry, dst, val)
|
|
}
|
|
|
|
// MarshalWithRegistry returns the BSON encoding of val using Registry r.
|
|
func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) {
|
|
dst := make([]byte, 0, 256) // TODO: make the default cap a constant
|
|
return MarshalAppendWithRegistry(r, dst, val)
|
|
}
|
|
|
|
// MarshalWithContext returns the BSON encoding of val using EncodeContext ec.
|
|
func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) {
|
|
dst := make([]byte, 0, 256) // TODO: make the default cap a constant
|
|
return MarshalAppendWithContext(ec, dst, val)
|
|
}
|
|
|
|
// MarshalAppendWithRegistry will append the BSON encoding of val to dst using
|
|
// Registry r. If dst is not large enough to hold the BSON encoding of val, dst
|
|
// will be grown.
|
|
func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) {
|
|
return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
|
|
}
|
|
|
|
// MarshalAppendWithContext will append the BSON encoding of val to dst using
|
|
// EncodeContext ec. If dst is not large enough to hold the BSON encoding of val, dst
|
|
// will be grown.
|
|
func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) {
|
|
sw := new(bsonrw.SliceWriter)
|
|
*sw = dst
|
|
vw := bvwPool.Get(sw)
|
|
defer bvwPool.Put(vw)
|
|
|
|
enc := encPool.Get().(*Encoder)
|
|
defer encPool.Put(enc)
|
|
|
|
err := enc.Reset(vw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = enc.SetContext(ec)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = enc.Encode(val)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return *sw, nil
|
|
}
|
|
|
|
// MarshalExtJSON returns the extended JSON encoding of val.
|
|
func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
return MarshalExtJSONWithRegistry(DefaultRegistry, val, canonical, escapeHTML)
|
|
}
|
|
|
|
// MarshalExtJSONAppend will append the extended JSON encoding of val to dst.
|
|
// If dst is not large enough to hold the extended JSON encoding of val, dst
|
|
// will be grown.
|
|
func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML)
|
|
}
|
|
|
|
// MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r.
|
|
func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
dst := make([]byte, 0, defaultDstCap)
|
|
return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
|
|
}
|
|
|
|
// MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r.
|
|
func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
dst := make([]byte, 0, defaultDstCap)
|
|
return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML)
|
|
}
|
|
|
|
// MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of
|
|
// val to dst using Registry r. If dst is not large enough to hold the BSON
|
|
// encoding of val, dst will be grown.
|
|
func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
|
|
}
|
|
|
|
// MarshalExtJSONAppendWithContext will append the extended JSON encoding of
|
|
// val to dst using Registry r. If dst is not large enough to hold the BSON
|
|
// encoding of val, dst will be grown.
|
|
func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
|
|
sw := new(bsonrw.SliceWriter)
|
|
*sw = dst
|
|
ejvw := extjPool.Get(sw, canonical, escapeHTML)
|
|
defer extjPool.Put(ejvw)
|
|
|
|
enc := encPool.Get().(*Encoder)
|
|
defer encPool.Put(enc)
|
|
|
|
err := enc.Reset(ejvw)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = enc.SetContext(ec)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = enc.Encode(val)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return *sw, nil
|
|
}
|