...
1
2
3
4
5
6
7 package bsoncodec
8
9 import (
10 "reflect"
11
12 "go.mongodb.org/mongo-driver/bson/bsonrw"
13 "go.mongodb.org/mongo-driver/bson/bsontype"
14 )
15
16 var _ ValueEncoder = &PointerCodec{}
17 var _ ValueDecoder = &PointerCodec{}
18
19
20
21
22
23
24
25
26
27
28
29
30
31 type PointerCodec struct {
32 ecache typeEncoderCache
33 dcache typeDecoderCache
34 }
35
36
37
38
39
40 func NewPointerCodec() *PointerCodec {
41 return &PointerCodec{}
42 }
43
44
45
46 func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
47 if val.Kind() != reflect.Ptr {
48 if !val.IsValid() {
49 return vw.WriteNull()
50 }
51 return ValueEncoderError{Name: "PointerCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val}
52 }
53
54 if val.IsNil() {
55 return vw.WriteNull()
56 }
57
58 typ := val.Type()
59 if v, ok := pc.ecache.Load(typ); ok {
60 if v == nil {
61 return ErrNoEncoder{Type: typ}
62 }
63 return v.EncodeValue(ec, vw, val.Elem())
64 }
65
66 enc, err := ec.LookupEncoder(typ.Elem())
67 enc = pc.ecache.LoadOrStore(typ, enc)
68 if err != nil {
69 return err
70 }
71 return enc.EncodeValue(ec, vw, val.Elem())
72 }
73
74
75
76 func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
77 if !val.CanSet() || val.Kind() != reflect.Ptr {
78 return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val}
79 }
80
81 typ := val.Type()
82 if vr.Type() == bsontype.Null {
83 val.Set(reflect.Zero(typ))
84 return vr.ReadNull()
85 }
86 if vr.Type() == bsontype.Undefined {
87 val.Set(reflect.Zero(typ))
88 return vr.ReadUndefined()
89 }
90
91 if val.IsNil() {
92 val.Set(reflect.New(typ.Elem()))
93 }
94
95 if v, ok := pc.dcache.Load(typ); ok {
96 if v == nil {
97 return ErrNoDecoder{Type: typ}
98 }
99 return v.DecodeValue(dc, vr, val.Elem())
100 }
101
102 dec, err := dc.LookupDecoder(typ.Elem())
103 dec = pc.dcache.LoadOrStore(typ, dec)
104 if err != nil {
105 return err
106 }
107 return dec.DecodeValue(dc, vr, val.Elem())
108 }
109
View as plain text