| // 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 bsoncodec |
| |
| import ( |
| "fmt" |
| "reflect" |
| "strings" |
| |
| "github.com/mongodb/mongo-go-driver/bson/bsonrw" |
| "github.com/mongodb/mongo-go-driver/bson/bsontype" |
| ) |
| |
| // 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) |
| } |
| |
| // Unmarshaler is an interface implemented by types that can unmarshal a BSON |
| // document representation of themselves. The BSON bytes can be assumed to be |
| // valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data |
| // after returning. |
| type Unmarshaler interface { |
| UnmarshalBSON([]byte) error |
| } |
| |
| // ValueUnmarshaler is an interface implemented by types that can unmarshal a |
| // BSON value representaiton of themselves. The BSON bytes and type can be |
| // assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it |
| // wishes to retain the data after returning. |
| type ValueUnmarshaler interface { |
| UnmarshalBSONValue(bsontype.Type, []byte) error |
| } |
| |
| // ValueEncoderError is an error returned from a ValueEncoder when the provided value can't be |
| // encoded by the ValueEncoder. |
| type ValueEncoderError struct { |
| Name string |
| Types []reflect.Type |
| Kinds []reflect.Kind |
| Received reflect.Value |
| } |
| |
| func (vee ValueEncoderError) Error() string { |
| typeKinds := make([]string, 0, len(vee.Types)+len(vee.Kinds)) |
| for _, t := range vee.Types { |
| typeKinds = append(typeKinds, t.String()) |
| } |
| for _, k := range vee.Kinds { |
| if k == reflect.Map { |
| typeKinds = append(typeKinds, "map[string]*") |
| continue |
| } |
| typeKinds = append(typeKinds, k.String()) |
| } |
| received := vee.Received.Kind().String() |
| if vee.Received.IsValid() { |
| received = vee.Received.Type().String() |
| } |
| return fmt.Sprintf("%s can only encode valid %s, but got %s", vee.Name, strings.Join(typeKinds, ", "), received) |
| } |
| |
| // ValueDecoderError is an error returned from a ValueDecoder when the provided value can't be |
| // decoded by the ValueDecoder. |
| type ValueDecoderError struct { |
| Name string |
| Types []reflect.Type |
| Kinds []reflect.Kind |
| Received reflect.Value |
| } |
| |
| func (vde ValueDecoderError) Error() string { |
| typeKinds := make([]string, 0, len(vde.Types)+len(vde.Kinds)) |
| for _, t := range vde.Types { |
| typeKinds = append(typeKinds, t.String()) |
| } |
| for _, k := range vde.Kinds { |
| if k == reflect.Map { |
| typeKinds = append(typeKinds, "map[string]*") |
| continue |
| } |
| typeKinds = append(typeKinds, k.String()) |
| } |
| received := vde.Received.Kind().String() |
| if vde.Received.IsValid() { |
| received = vde.Received.Type().String() |
| } |
| return fmt.Sprintf("%s can only decode valid and settable %s, but got %s", vde.Name, strings.Join(typeKinds, ", "), received) |
| } |
| |
| // EncodeContext is the contextual information required for a Codec to encode a |
| // value. |
| type EncodeContext struct { |
| *Registry |
| MinSize bool |
| } |
| |
| // DecodeContext is the contextual information required for a Codec to decode a |
| // value. |
| type DecodeContext struct { |
| *Registry |
| Truncate bool |
| // Ancestor is the type of a containing document. This is mainly used to determine what type |
| // should be used when decoding an embedded document into an empty interface. For example, if |
| // Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface |
| // will be decoded into a bson.M. |
| Ancestor reflect.Type |
| } |
| |
| // ValueCodec is the interface that groups the methods to encode and decode |
| // values. |
| type ValueCodec interface { |
| ValueEncoder |
| ValueDecoder |
| } |
| |
| // ValueEncoder is the interface implemented by types that can handle the encoding of a value. |
| type ValueEncoder interface { |
| EncodeValue(EncodeContext, bsonrw.ValueWriter, reflect.Value) error |
| } |
| |
| // ValueEncoderFunc is an adapter function that allows a function with the correct signature to be |
| // used as a ValueEncoder. |
| type ValueEncoderFunc func(EncodeContext, bsonrw.ValueWriter, reflect.Value) error |
| |
| // EncodeValue implements the ValueEncoder interface. |
| func (fn ValueEncoderFunc) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { |
| return fn(ec, vw, val) |
| } |
| |
| // ValueDecoder is the interface implemented by types that can handle the decoding of a value. |
| type ValueDecoder interface { |
| DecodeValue(DecodeContext, bsonrw.ValueReader, reflect.Value) error |
| } |
| |
| // ValueDecoderFunc is an adapter function that allows a function with the correct signature to be |
| // used as a ValueDecoder. |
| type ValueDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) error |
| |
| // DecodeValue implements the ValueDecoder interface. |
| func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { |
| return fn(dc, vr, val) |
| } |
| |
| // CodecZeroer is the interface implemented by Codecs that can also determine if |
| // a value of the type that would be encoded is zero. |
| type CodecZeroer interface { |
| IsTypeZero(interface{}) bool |
| } |