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 mgocompat 8 9import ( 10 "errors" 11 "reflect" 12 "time" 13 14 "go.mongodb.org/mongo-driver/bson" 15 "go.mongodb.org/mongo-driver/bson/bsoncodec" 16 "go.mongodb.org/mongo-driver/bson/bsonoptions" 17 "go.mongodb.org/mongo-driver/bson/bsontype" 18) 19 20var ( 21 // ErrSetZero may be returned from a SetBSON method to have the value set to its respective zero value. 22 ErrSetZero = errors.New("set to zero") 23 24 tInt = reflect.TypeOf(int(0)) 25 tTime = reflect.TypeOf(time.Time{}) 26 tM = reflect.TypeOf(bson.M{}) 27 tInterfaceSlice = reflect.TypeOf([]interface{}{}) 28 tByteSlice = reflect.TypeOf([]byte{}) 29 tEmpty = reflect.TypeOf((*interface{})(nil)).Elem() 30 tGetter = reflect.TypeOf((*Getter)(nil)).Elem() 31 tSetter = reflect.TypeOf((*Setter)(nil)).Elem() 32) 33 34// Registry is the mgo compatible bsoncodec.Registry. It contains the default and 35// primitive codecs with mgo compatible options. 36var Registry = NewRegistryBuilder().Build() 37 38// RegistryRespectNilValues is the bsoncodec.Registry compatible with mgo withSetRespectNilValues set to true. 39var RegistryRespectNilValues = NewRespectNilValuesRegistryBuilder().Build() 40 41// NewRegistryBuilder creates a new bsoncodec.RegistryBuilder configured with the default encoders and 42// deocders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the 43// PrimitiveCodecs type in this package. 44func NewRegistryBuilder() *bsoncodec.RegistryBuilder { 45 rb := bsoncodec.NewRegistryBuilder() 46 bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) 47 bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb) 48 bson.PrimitiveCodecs{}.RegisterPrimitiveCodecs(rb) 49 50 structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.DefaultStructTagParser, 51 bsonoptions.StructCodec(). 52 SetDecodeZeroStruct(true). 53 SetEncodeOmitDefaultStruct(true). 54 SetOverwriteDuplicatedInlinedFields(false). 55 SetAllowUnexportedFields(true)) 56 emptyInterCodec := bsoncodec.NewEmptyInterfaceCodec( 57 bsonoptions.EmptyInterfaceCodec(). 58 SetDecodeBinaryAsSlice(true)) 59 mapCodec := bsoncodec.NewMapCodec( 60 bsonoptions.MapCodec(). 61 SetDecodeZerosMap(true). 62 SetEncodeNilAsEmpty(true). 63 SetEncodeKeysWithStringer(true)) 64 uintcodec := bsoncodec.NewUIntCodec(bsonoptions.UIntCodec().SetEncodeToMinSize(true)) 65 66 rb.RegisterTypeDecoder(tEmpty, emptyInterCodec). 67 RegisterDefaultDecoder(reflect.String, bsoncodec.NewStringCodec(bsonoptions.StringCodec().SetDecodeObjectIDAsHex(false))). 68 RegisterDefaultDecoder(reflect.Struct, structcodec). 69 RegisterDefaultDecoder(reflect.Map, mapCodec). 70 RegisterTypeEncoder(tByteSlice, bsoncodec.NewByteSliceCodec(bsonoptions.ByteSliceCodec().SetEncodeNilAsEmpty(true))). 71 RegisterDefaultEncoder(reflect.Struct, structcodec). 72 RegisterDefaultEncoder(reflect.Slice, bsoncodec.NewSliceCodec(bsonoptions.SliceCodec().SetEncodeNilAsEmpty(true))). 73 RegisterDefaultEncoder(reflect.Map, mapCodec). 74 RegisterDefaultEncoder(reflect.Uint, uintcodec). 75 RegisterDefaultEncoder(reflect.Uint8, uintcodec). 76 RegisterDefaultEncoder(reflect.Uint16, uintcodec). 77 RegisterDefaultEncoder(reflect.Uint32, uintcodec). 78 RegisterDefaultEncoder(reflect.Uint64, uintcodec). 79 RegisterTypeMapEntry(bsontype.Int32, tInt). 80 RegisterTypeMapEntry(bsontype.DateTime, tTime). 81 RegisterTypeMapEntry(bsontype.Array, tInterfaceSlice). 82 RegisterTypeMapEntry(bsontype.Type(0), tM). 83 RegisterTypeMapEntry(bsontype.EmbeddedDocument, tM). 84 RegisterHookEncoder(tGetter, bsoncodec.ValueEncoderFunc(GetterEncodeValue)). 85 RegisterHookDecoder(tSetter, bsoncodec.ValueDecoderFunc(SetterDecodeValue)) 86 87 return rb 88} 89 90// NewRespectNilValuesRegistryBuilder creates a new bsoncodec.RegistryBuilder configured to behave like mgo/bson 91// with RespectNilValues set to true. 92func NewRespectNilValuesRegistryBuilder() *bsoncodec.RegistryBuilder { 93 rb := NewRegistryBuilder() 94 95 structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.DefaultStructTagParser, 96 bsonoptions.StructCodec(). 97 SetDecodeZeroStruct(true). 98 SetEncodeOmitDefaultStruct(true). 99 SetOverwriteDuplicatedInlinedFields(false). 100 SetAllowUnexportedFields(true)) 101 mapCodec := bsoncodec.NewMapCodec( 102 bsonoptions.MapCodec(). 103 SetDecodeZerosMap(true). 104 SetEncodeNilAsEmpty(false)) 105 106 rb.RegisterDefaultDecoder(reflect.Struct, structcodec). 107 RegisterDefaultDecoder(reflect.Map, mapCodec). 108 RegisterTypeEncoder(tByteSlice, bsoncodec.NewByteSliceCodec(bsonoptions.ByteSliceCodec().SetEncodeNilAsEmpty(false))). 109 RegisterDefaultEncoder(reflect.Struct, structcodec). 110 RegisterDefaultEncoder(reflect.Slice, bsoncodec.NewSliceCodec(bsonoptions.SliceCodec().SetEncodeNilAsEmpty(false))). 111 RegisterDefaultEncoder(reflect.Map, mapCodec) 112 113 return rb 114} 115