...
1
2
3
4
5 package impl
6
7 import (
8 "sync"
9
10 "google.golang.org/protobuf/internal/errors"
11 "google.golang.org/protobuf/reflect/protoreflect"
12 "google.golang.org/protobuf/runtime/protoiface"
13 )
14
15 func (mi *MessageInfo) checkInitialized(in protoiface.CheckInitializedInput) (protoiface.CheckInitializedOutput, error) {
16 var p pointer
17 if ms, ok := in.Message.(*messageState); ok {
18 p = ms.pointer()
19 } else {
20 p = in.Message.(*messageReflectWrapper).pointer()
21 }
22 return protoiface.CheckInitializedOutput{}, mi.checkInitializedPointer(p)
23 }
24
25 func (mi *MessageInfo) checkInitializedPointer(p pointer) error {
26 mi.init()
27 if !mi.needsInitCheck {
28 return nil
29 }
30 if p.IsNil() {
31 for _, f := range mi.orderedCoderFields {
32 if f.isRequired {
33 return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName()))
34 }
35 }
36 return nil
37 }
38 if mi.extensionOffset.IsValid() {
39 e := p.Apply(mi.extensionOffset).Extensions()
40 if err := mi.isInitExtensions(e); err != nil {
41 return err
42 }
43 }
44 for _, f := range mi.orderedCoderFields {
45 if !f.isRequired && f.funcs.isInit == nil {
46 continue
47 }
48 fptr := p.Apply(f.offset)
49 if f.isPointer && fptr.Elem().IsNil() {
50 if f.isRequired {
51 return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName()))
52 }
53 continue
54 }
55 if f.funcs.isInit == nil {
56 continue
57 }
58 if err := f.funcs.isInit(fptr, f); err != nil {
59 return err
60 }
61 }
62 return nil
63 }
64
65 func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error {
66 if ext == nil {
67 return nil
68 }
69 for _, x := range *ext {
70 ei := getExtensionFieldInfo(x.Type())
71 if ei.funcs.isInit == nil {
72 continue
73 }
74 v := x.Value()
75 if !v.IsValid() {
76 continue
77 }
78 if err := ei.funcs.isInit(v); err != nil {
79 return err
80 }
81 }
82 return nil
83 }
84
85 var (
86 needsInitCheckMu sync.Mutex
87 needsInitCheckMap sync.Map
88 )
89
90
91
92
93 func needsInitCheck(md protoreflect.MessageDescriptor) bool {
94 if v, ok := needsInitCheckMap.Load(md); ok {
95 if has, ok := v.(bool); ok {
96 return has
97 }
98 }
99 needsInitCheckMu.Lock()
100 defer needsInitCheckMu.Unlock()
101 return needsInitCheckLocked(md)
102 }
103
104 func needsInitCheckLocked(md protoreflect.MessageDescriptor) (has bool) {
105 if v, ok := needsInitCheckMap.Load(md); ok {
106
107
108
109
110
111
112
113
114
115
116 has, ok := v.(bool)
117 return ok && has
118 }
119 needsInitCheckMap.Store(md, struct{}{})
120 defer func() {
121 needsInitCheckMap.Store(md, has)
122 }()
123 if md.RequiredNumbers().Len() > 0 {
124 return true
125 }
126 if md.ExtensionRanges().Len() > 0 {
127 return true
128 }
129 for i := 0; i < md.Fields().Len(); i++ {
130 fd := md.Fields().Get(i)
131
132 if fd.IsMap() {
133 fd = fd.MapValue()
134 }
135 fmd := fd.Message()
136 if fmd != nil && needsInitCheckLocked(fmd) {
137 return true
138 }
139 }
140 return false
141 }
142
View as plain text