message.go (8571B)
1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package impl 6 7 import ( 8 "fmt" 9 "reflect" 10 "strconv" 11 "strings" 12 "sync" 13 "sync/atomic" 14 15 "google.golang.org/protobuf/internal/genid" 16 "google.golang.org/protobuf/reflect/protoreflect" 17 "google.golang.org/protobuf/reflect/protoregistry" 18 ) 19 20 // MessageInfo provides protobuf related functionality for a given Go type 21 // that represents a message. A given instance of MessageInfo is tied to 22 // exactly one Go type, which must be a pointer to a struct type. 23 // 24 // The exported fields must be populated before any methods are called 25 // and cannot be mutated after set. 26 type MessageInfo struct { 27 // GoReflectType is the underlying message Go type and must be populated. 28 GoReflectType reflect.Type // pointer to struct 29 30 // Desc is the underlying message descriptor type and must be populated. 31 Desc protoreflect.MessageDescriptor 32 33 // Exporter must be provided in a purego environment in order to provide 34 // access to unexported fields. 35 Exporter exporter 36 37 // OneofWrappers is list of pointers to oneof wrapper struct types. 38 OneofWrappers []interface{} 39 40 initMu sync.Mutex // protects all unexported fields 41 initDone uint32 42 43 reflectMessageInfo // for reflection implementation 44 coderMessageInfo // for fast-path method implementations 45 } 46 47 // exporter is a function that returns a reference to the ith field of v, 48 // where v is a pointer to a struct. It returns nil if it does not support 49 // exporting the requested field (e.g., already exported). 50 type exporter func(v interface{}, i int) interface{} 51 52 // getMessageInfo returns the MessageInfo for any message type that 53 // is generated by our implementation of protoc-gen-go (for v2 and on). 54 // If it is unable to obtain a MessageInfo, it returns nil. 55 func getMessageInfo(mt reflect.Type) *MessageInfo { 56 m, ok := reflect.Zero(mt).Interface().(protoreflect.ProtoMessage) 57 if !ok { 58 return nil 59 } 60 mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo }) 61 if !ok { 62 return nil 63 } 64 return mr.ProtoMessageInfo() 65 } 66 67 func (mi *MessageInfo) init() { 68 // This function is called in the hot path. Inline the sync.Once logic, 69 // since allocating a closure for Once.Do is expensive. 70 // Keep init small to ensure that it can be inlined. 71 if atomic.LoadUint32(&mi.initDone) == 0 { 72 mi.initOnce() 73 } 74 } 75 76 func (mi *MessageInfo) initOnce() { 77 mi.initMu.Lock() 78 defer mi.initMu.Unlock() 79 if mi.initDone == 1 { 80 return 81 } 82 83 t := mi.GoReflectType 84 if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct { 85 panic(fmt.Sprintf("got %v, want *struct kind", t)) 86 } 87 t = t.Elem() 88 89 si := mi.makeStructInfo(t) 90 mi.makeReflectFuncs(t, si) 91 mi.makeCoderMethods(t, si) 92 93 atomic.StoreUint32(&mi.initDone, 1) 94 } 95 96 // getPointer returns the pointer for a message, which should be of 97 // the type of the MessageInfo. If the message is of a different type, 98 // it returns ok==false. 99 func (mi *MessageInfo) getPointer(m protoreflect.Message) (p pointer, ok bool) { 100 switch m := m.(type) { 101 case *messageState: 102 return m.pointer(), m.messageInfo() == mi 103 case *messageReflectWrapper: 104 return m.pointer(), m.messageInfo() == mi 105 } 106 return pointer{}, false 107 } 108 109 type ( 110 SizeCache = int32 111 WeakFields = map[int32]protoreflect.ProtoMessage 112 UnknownFields = unknownFieldsA // TODO: switch to unknownFieldsB 113 unknownFieldsA = []byte 114 unknownFieldsB = *[]byte 115 ExtensionFields = map[int32]ExtensionField 116 ) 117 118 var ( 119 sizecacheType = reflect.TypeOf(SizeCache(0)) 120 weakFieldsType = reflect.TypeOf(WeakFields(nil)) 121 unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil)) 122 unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil)) 123 extensionFieldsType = reflect.TypeOf(ExtensionFields(nil)) 124 ) 125 126 type structInfo struct { 127 sizecacheOffset offset 128 sizecacheType reflect.Type 129 weakOffset offset 130 weakType reflect.Type 131 unknownOffset offset 132 unknownType reflect.Type 133 extensionOffset offset 134 extensionType reflect.Type 135 136 fieldsByNumber map[protoreflect.FieldNumber]reflect.StructField 137 oneofsByName map[protoreflect.Name]reflect.StructField 138 oneofWrappersByType map[reflect.Type]protoreflect.FieldNumber 139 oneofWrappersByNumber map[protoreflect.FieldNumber]reflect.Type 140 } 141 142 func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo { 143 si := structInfo{ 144 sizecacheOffset: invalidOffset, 145 weakOffset: invalidOffset, 146 unknownOffset: invalidOffset, 147 extensionOffset: invalidOffset, 148 149 fieldsByNumber: map[protoreflect.FieldNumber]reflect.StructField{}, 150 oneofsByName: map[protoreflect.Name]reflect.StructField{}, 151 oneofWrappersByType: map[reflect.Type]protoreflect.FieldNumber{}, 152 oneofWrappersByNumber: map[protoreflect.FieldNumber]reflect.Type{}, 153 } 154 155 fieldLoop: 156 for i := 0; i < t.NumField(); i++ { 157 switch f := t.Field(i); f.Name { 158 case genid.SizeCache_goname, genid.SizeCacheA_goname: 159 if f.Type == sizecacheType { 160 si.sizecacheOffset = offsetOf(f, mi.Exporter) 161 si.sizecacheType = f.Type 162 } 163 case genid.WeakFields_goname, genid.WeakFieldsA_goname: 164 if f.Type == weakFieldsType { 165 si.weakOffset = offsetOf(f, mi.Exporter) 166 si.weakType = f.Type 167 } 168 case genid.UnknownFields_goname, genid.UnknownFieldsA_goname: 169 if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType { 170 si.unknownOffset = offsetOf(f, mi.Exporter) 171 si.unknownType = f.Type 172 } 173 case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname: 174 if f.Type == extensionFieldsType { 175 si.extensionOffset = offsetOf(f, mi.Exporter) 176 si.extensionType = f.Type 177 } 178 default: 179 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { 180 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { 181 n, _ := strconv.ParseUint(s, 10, 64) 182 si.fieldsByNumber[protoreflect.FieldNumber(n)] = f 183 continue fieldLoop 184 } 185 } 186 if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 { 187 si.oneofsByName[protoreflect.Name(s)] = f 188 continue fieldLoop 189 } 190 } 191 } 192 193 // Derive a mapping of oneof wrappers to fields. 194 oneofWrappers := mi.OneofWrappers 195 for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { 196 if fn, ok := reflect.PtrTo(t).MethodByName(method); ok { 197 for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { 198 if vs, ok := v.Interface().([]interface{}); ok { 199 oneofWrappers = vs 200 } 201 } 202 } 203 } 204 for _, v := range oneofWrappers { 205 tf := reflect.TypeOf(v).Elem() 206 f := tf.Field(0) 207 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { 208 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { 209 n, _ := strconv.ParseUint(s, 10, 64) 210 si.oneofWrappersByType[tf] = protoreflect.FieldNumber(n) 211 si.oneofWrappersByNumber[protoreflect.FieldNumber(n)] = tf 212 break 213 } 214 } 215 } 216 217 return si 218 } 219 220 func (mi *MessageInfo) New() protoreflect.Message { 221 m := reflect.New(mi.GoReflectType.Elem()).Interface() 222 if r, ok := m.(protoreflect.ProtoMessage); ok { 223 return r.ProtoReflect() 224 } 225 return mi.MessageOf(m) 226 } 227 func (mi *MessageInfo) Zero() protoreflect.Message { 228 return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) 229 } 230 func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { 231 return mi.Desc 232 } 233 func (mi *MessageInfo) Enum(i int) protoreflect.EnumType { 234 mi.init() 235 fd := mi.Desc.Fields().Get(i) 236 return Export{}.EnumTypeOf(mi.fieldTypes[fd.Number()]) 237 } 238 func (mi *MessageInfo) Message(i int) protoreflect.MessageType { 239 mi.init() 240 fd := mi.Desc.Fields().Get(i) 241 switch { 242 case fd.IsWeak(): 243 mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()) 244 return mt 245 case fd.IsMap(): 246 return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]} 247 default: 248 return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()]) 249 } 250 } 251 252 type mapEntryType struct { 253 desc protoreflect.MessageDescriptor 254 valType interface{} // zero value of enum or message type 255 } 256 257 func (mt mapEntryType) New() protoreflect.Message { 258 return nil 259 } 260 func (mt mapEntryType) Zero() protoreflect.Message { 261 return nil 262 } 263 func (mt mapEntryType) Descriptor() protoreflect.MessageDescriptor { 264 return mt.desc 265 } 266 func (mt mapEntryType) Enum(i int) protoreflect.EnumType { 267 fd := mt.desc.Fields().Get(i) 268 if fd.Enum() == nil { 269 return nil 270 } 271 return Export{}.EnumTypeOf(mt.valType) 272 } 273 func (mt mapEntryType) Message(i int) protoreflect.MessageType { 274 fd := mt.desc.Fields().Get(i) 275 if fd.Message() == nil { 276 return nil 277 } 278 return Export{}.MessageTypeOf(mt.valType) 279 }