podman
248 строк · 9.6 Кб
1// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package bson8
9import (10"bytes"11"encoding/json"12
13"go.mongodb.org/mongo-driver/bson/bsoncodec"14"go.mongodb.org/mongo-driver/bson/bsonrw"15"go.mongodb.org/mongo-driver/bson/bsontype"16)
17
18const defaultDstCap = 25619
20var bvwPool = bsonrw.NewBSONValueWriterPool()21var extjPool = bsonrw.NewExtJSONValueWriterPool()22
23// Marshaler is an interface implemented by types that can marshal themselves
24// into a BSON document represented as bytes. The bytes returned must be a valid
25// BSON document if the error is nil.
26type Marshaler interface {27MarshalBSON() ([]byte, error)28}
29
30// ValueMarshaler is an interface implemented by types that can marshal
31// themselves into a BSON value as bytes. The type must be the valid type for
32// the bytes returned. The bytes and byte type together must be valid if the
33// error is nil.
34type ValueMarshaler interface {35MarshalBSONValue() (bsontype.Type, []byte, error)36}
37
38// Marshal returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed into a
39// document, MarshalValue should be used instead.
40//
41// Marshal will use the default registry created by NewRegistry to recursively
42// marshal val into a []byte. Marshal will inspect struct tags and alter the
43// marshaling process accordingly.
44func Marshal(val interface{}) ([]byte, error) {45return MarshalWithRegistry(DefaultRegistry, val)46}
47
48// MarshalAppend will encode val as a BSON document and append the bytes to dst. If dst is not large enough to hold the
49// bytes, it will be grown. If val is not a type that can be transformed into a document, MarshalValueAppend should be
50// used instead.
51func MarshalAppend(dst []byte, val interface{}) ([]byte, error) {52return MarshalAppendWithRegistry(DefaultRegistry, dst, val)53}
54
55// MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed
56// into a document, MarshalValueWithRegistry should be used instead.
57func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) {58dst := make([]byte, 0)59return MarshalAppendWithRegistry(r, dst, val)60}
61
62// MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type
63// that can be transformed into a document, MarshalValueWithContext should be used instead.
64func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) {65dst := make([]byte, 0)66return MarshalAppendWithContext(ec, dst, val)67}
68
69// MarshalAppendWithRegistry will encode val as a BSON document using Registry r and append the bytes to dst. If dst is
70// not large enough to hold the bytes, it will be grown. If val is not a type that can be transformed into a document,
71// MarshalValueAppendWithRegistry should be used instead.
72func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) {73return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)74}
75
76// MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the
77// bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be
78// transformed into a document, MarshalValueAppendWithContext should be used instead.
79func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) {80sw := new(bsonrw.SliceWriter)81*sw = dst82vw := bvwPool.Get(sw)83defer bvwPool.Put(vw)84
85enc := encPool.Get().(*Encoder)86defer encPool.Put(enc)87
88err := enc.Reset(vw)89if err != nil {90return nil, err91}92err = enc.SetContext(ec)93if err != nil {94return nil, err95}96
97err = enc.Encode(val)98if err != nil {99return nil, err100}101
102return *sw, nil103}
104
105// MarshalValue returns the BSON encoding of val.
106//
107// MarshalValue will use bson.DefaultRegistry to transform val into a BSON value. If val is a struct, this function will
108// inspect struct tags and alter the marshalling process accordingly.
109func MarshalValue(val interface{}) (bsontype.Type, []byte, error) {110return MarshalValueWithRegistry(DefaultRegistry, val)111}
112
113// MarshalValueAppend will append the BSON encoding of val to dst. If dst is not large enough to hold the BSON encoding
114// of val, dst will be grown.
115func MarshalValueAppend(dst []byte, val interface{}) (bsontype.Type, []byte, error) {116return MarshalValueAppendWithRegistry(DefaultRegistry, dst, val)117}
118
119// MarshalValueWithRegistry returns the BSON encoding of val using Registry r.
120func MarshalValueWithRegistry(r *bsoncodec.Registry, val interface{}) (bsontype.Type, []byte, error) {121dst := make([]byte, 0)122return MarshalValueAppendWithRegistry(r, dst, val)123}
124
125// MarshalValueWithContext returns the BSON encoding of val using EncodeContext ec.
126func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsontype.Type, []byte, error) {127dst := make([]byte, 0)128return MarshalValueAppendWithContext(ec, dst, val)129}
130
131// MarshalValueAppendWithRegistry will append the BSON encoding of val to dst using Registry r. If dst is not large
132// enough to hold the BSON encoding of val, dst will be grown.
133func MarshalValueAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) (bsontype.Type, []byte, error) {134return MarshalValueAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)135}
136
137// MarshalValueAppendWithContext will append the BSON encoding of val to dst using EncodeContext ec. If dst is not large
138// enough to hold the BSON encoding of val, dst will be grown.
139func MarshalValueAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) (bsontype.Type, []byte, error) {140// get a ValueWriter configured to write to dst141sw := new(bsonrw.SliceWriter)142*sw = dst143vwFlusher := bvwPool.GetAtModeElement(sw)144
145// get an Encoder and encode the value146enc := encPool.Get().(*Encoder)147defer encPool.Put(enc)148if err := enc.Reset(vwFlusher); err != nil {149return 0, nil, err150}151if err := enc.SetContext(ec); err != nil {152return 0, nil, err153}154if err := enc.Encode(val); err != nil {155return 0, nil, err156}157
158// flush the bytes written because we cannot guarantee that a full document has been written159// after the flush, *sw will be in the format160// [value type, 0 (null byte to indicate end of empty element name), value bytes..]161if err := vwFlusher.Flush(); err != nil {162return 0, nil, err163}164buffer := *sw165return bsontype.Type(buffer[0]), buffer[2:], nil166}
167
168// MarshalExtJSON returns the extended JSON encoding of val.
169func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) {170return MarshalExtJSONWithRegistry(DefaultRegistry, val, canonical, escapeHTML)171}
172
173// MarshalExtJSONAppend will append the extended JSON encoding of val to dst.
174// If dst is not large enough to hold the extended JSON encoding of val, dst
175// will be grown.
176func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {177return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML)178}
179
180// MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r.
181func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) {182dst := make([]byte, 0, defaultDstCap)183return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)184}
185
186// MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r.
187func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) {188dst := make([]byte, 0, defaultDstCap)189return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML)190}
191
192// MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of
193// val to dst using Registry r. If dst is not large enough to hold the BSON
194// encoding of val, dst will be grown.
195func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {196return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)197}
198
199// MarshalExtJSONAppendWithContext will append the extended JSON encoding of
200// val to dst using Registry r. If dst is not large enough to hold the BSON
201// encoding of val, dst will be grown.
202func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {203sw := new(bsonrw.SliceWriter)204*sw = dst205ejvw := extjPool.Get(sw, canonical, escapeHTML)206defer extjPool.Put(ejvw)207
208enc := encPool.Get().(*Encoder)209defer encPool.Put(enc)210
211err := enc.Reset(ejvw)212if err != nil {213return nil, err214}215err = enc.SetContext(ec)216if err != nil {217return nil, err218}219
220err = enc.Encode(val)221if err != nil {222return nil, err223}224
225return *sw, nil226}
227
228// IndentExtJSON will prefix and indent the provided extended JSON src and append it to dst.
229func IndentExtJSON(dst *bytes.Buffer, src []byte, prefix, indent string) error {230return json.Indent(dst, src, prefix, indent)231}
232
233// MarshalExtJSONIndent returns the extended JSON encoding of val with each line with prefixed
234// and indented.
235func MarshalExtJSONIndent(val interface{}, canonical, escapeHTML bool, prefix, indent string) ([]byte, error) {236marshaled, err := MarshalExtJSON(val, canonical, escapeHTML)237if err != nil {238return nil, err239}240
241var buf bytes.Buffer242err = IndentExtJSON(&buf, marshaled, prefix, indent)243if err != nil {244return nil, err245}246
247return buf.Bytes(), nil248}
249