github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go (about) 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 7 package bsoncodec 8 9 import ( 10 "fmt" 11 "reflect" 12 13 "go.mongodb.org/mongo-driver/bson/bsonoptions" 14 "go.mongodb.org/mongo-driver/bson/bsonrw" 15 "go.mongodb.org/mongo-driver/bson/bsontype" 16 "go.mongodb.org/mongo-driver/bson/primitive" 17 ) 18 19 var defaultSliceCodec = NewSliceCodec() 20 21 // SliceCodec is the Codec used for slice values. 22 // 23 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the 24 // SliceCodec registered. 25 type SliceCodec struct { 26 // EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of 27 // BSON null. 28 // 29 // Deprecated: Use bson.Encoder.NilSliceAsEmpty instead. 30 EncodeNilAsEmpty bool 31 } 32 33 // NewSliceCodec returns a MapCodec with options opts. 34 // 35 // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the 36 // SliceCodec registered. 37 func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { 38 sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) 39 40 codec := SliceCodec{} 41 if sliceOpt.EncodeNilAsEmpty != nil { 42 codec.EncodeNilAsEmpty = *sliceOpt.EncodeNilAsEmpty 43 } 44 return &codec 45 } 46 47 // EncodeValue is the ValueEncoder for slice types. 48 func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { 49 if !val.IsValid() || val.Kind() != reflect.Slice { 50 return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} 51 } 52 53 if val.IsNil() && !sc.EncodeNilAsEmpty && !ec.nilSliceAsEmpty { 54 return vw.WriteNull() 55 } 56 57 // If we have a []byte we want to treat it as a binary instead of as an array. 58 if val.Type().Elem() == tByte { 59 byteSlice := make([]byte, val.Len()) 60 reflect.Copy(reflect.ValueOf(byteSlice), val) 61 return vw.WriteBinary(byteSlice) 62 } 63 64 // If we have a []primitive.E we want to treat it as a document instead of as an array. 65 if val.Type().ConvertibleTo(tD) { 66 d := val.Convert(tD).Interface().(primitive.D) 67 68 dw, err := vw.WriteDocument() 69 if err != nil { 70 return err 71 } 72 73 for _, e := range d { 74 err = encodeElement(ec, dw, e) 75 if err != nil { 76 return err 77 } 78 } 79 80 return dw.WriteDocumentEnd() 81 } 82 83 aw, err := vw.WriteArray() 84 if err != nil { 85 return err 86 } 87 88 elemType := val.Type().Elem() 89 encoder, err := ec.LookupEncoder(elemType) 90 if err != nil && elemType.Kind() != reflect.Interface { 91 return err 92 } 93 94 for idx := 0; idx < val.Len(); idx++ { 95 currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) 96 if lookupErr != nil && lookupErr != errInvalidValue { 97 return lookupErr 98 } 99 100 vw, err := aw.WriteArrayElement() 101 if err != nil { 102 return err 103 } 104 105 if lookupErr == errInvalidValue { 106 err = vw.WriteNull() 107 if err != nil { 108 return err 109 } 110 continue 111 } 112 113 err = currEncoder.EncodeValue(ec, vw, currVal) 114 if err != nil { 115 return err 116 } 117 } 118 return aw.WriteArrayEnd() 119 } 120 121 // DecodeValue is the ValueDecoder for slice types. 122 func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { 123 if !val.CanSet() || val.Kind() != reflect.Slice { 124 return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} 125 } 126 127 switch vrType := vr.Type(); vrType { 128 case bsontype.Array: 129 case bsontype.Null: 130 val.Set(reflect.Zero(val.Type())) 131 return vr.ReadNull() 132 case bsontype.Undefined: 133 val.Set(reflect.Zero(val.Type())) 134 return vr.ReadUndefined() 135 case bsontype.Type(0), bsontype.EmbeddedDocument: 136 if val.Type().Elem() != tE { 137 return fmt.Errorf("cannot decode document into %s", val.Type()) 138 } 139 case bsontype.Binary: 140 if val.Type().Elem() != tByte { 141 return fmt.Errorf("SliceDecodeValue can only decode a binary into a byte array, got %v", vrType) 142 } 143 data, subtype, err := vr.ReadBinary() 144 if err != nil { 145 return err 146 } 147 if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { 148 return fmt.Errorf("SliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype) 149 } 150 151 if val.IsNil() { 152 val.Set(reflect.MakeSlice(val.Type(), 0, len(data))) 153 } 154 val.SetLen(0) 155 val.Set(reflect.AppendSlice(val, reflect.ValueOf(data))) 156 return nil 157 case bsontype.String: 158 if sliceType := val.Type().Elem(); sliceType != tByte { 159 return fmt.Errorf("SliceDecodeValue can only decode a string into a byte array, got %v", sliceType) 160 } 161 str, err := vr.ReadString() 162 if err != nil { 163 return err 164 } 165 byteStr := []byte(str) 166 167 if val.IsNil() { 168 val.Set(reflect.MakeSlice(val.Type(), 0, len(byteStr))) 169 } 170 val.SetLen(0) 171 val.Set(reflect.AppendSlice(val, reflect.ValueOf(byteStr))) 172 return nil 173 default: 174 return fmt.Errorf("cannot decode %v into a slice", vrType) 175 } 176 177 var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) 178 switch val.Type().Elem() { 179 case tE: 180 dc.Ancestor = val.Type() 181 elemsFunc = defaultValueDecoders.decodeD 182 default: 183 elemsFunc = defaultValueDecoders.decodeDefault 184 } 185 186 elems, err := elemsFunc(dc, vr, val) 187 if err != nil { 188 return err 189 } 190 191 if val.IsNil() { 192 val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) 193 } 194 195 val.SetLen(0) 196 val.Set(reflect.Append(val, elems...)) 197 198 return nil 199 }