| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package proto |
| |
| import ( |
| "fmt" |
| "log" |
| "reflect" |
| "strconv" |
| ) |
| |
| var enumValueMaps = make(map[string]map[string]int32) |
| |
| // RegisterEnum is called from the generated code to install the enum descriptor |
| // maps into the global table to aid parsing text format protocol buffers. |
| func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { |
| if registerEnumAlt != nil { |
| registerEnumAlt(typeName, unusedNameMap, valueMap) // populated by hooks_enabled.go |
| return |
| } |
| if _, ok := enumValueMaps[typeName]; ok { |
| panic("proto: duplicate enum registered: " + typeName) |
| } |
| enumValueMaps[typeName] = valueMap |
| } |
| |
| // EnumValueMap returns the mapping from names to integers of the |
| // enum type enumType, or a nil if not found. |
| func EnumValueMap(enumType string) map[string]int32 { |
| if enumValueMapAlt != nil { |
| return enumValueMapAlt(enumType) // populated by hooks_enabled.go |
| } |
| return enumValueMaps[enumType] |
| } |
| |
| // A registry of all linked message types. |
| // The string is a fully-qualified proto name ("pkg.Message"). |
| var ( |
| protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers |
| protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types |
| revProtoTypes = make(map[reflect.Type]string) |
| ) |
| |
| // RegisterType is called from generated code and maps from the fully qualified |
| // proto name to the type (pointer to struct) of the protocol buffer. |
| func RegisterType(x Message, name string) { |
| if registerTypeAlt != nil { |
| registerTypeAlt(x, name) // populated by hooks_enabled.go |
| return |
| } |
| if _, ok := protoTypedNils[name]; ok { |
| // TODO: Some day, make this a panic. |
| log.Printf("proto: duplicate proto type registered: %s", name) |
| return |
| } |
| t := reflect.TypeOf(x) |
| if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 { |
| // Generated code always calls RegisterType with nil x. |
| // This check is just for extra safety. |
| protoTypedNils[name] = x |
| } else { |
| protoTypedNils[name] = reflect.Zero(t).Interface().(Message) |
| } |
| revProtoTypes[t] = name |
| } |
| |
| // RegisterMapType is called from generated code and maps from the fully qualified |
| // proto name to the native map type of the proto map definition. |
| func RegisterMapType(x interface{}, name string) { |
| if registerMapTypeAlt != nil { |
| registerMapTypeAlt(x, name) // populated by hooks_enabled.go |
| return |
| } |
| if reflect.TypeOf(x).Kind() != reflect.Map { |
| panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name)) |
| } |
| if _, ok := protoMapTypes[name]; ok { |
| log.Printf("proto: duplicate proto type registered: %s", name) |
| return |
| } |
| t := reflect.TypeOf(x) |
| protoMapTypes[name] = t |
| |
| // Avoid registering into revProtoTypes since map types are not unique. |
| // revProtoTypes[t] = name |
| } |
| |
| // MessageName returns the fully-qualified proto name for the given message type. |
| func MessageName(x Message) string { |
| if messageNameAlt != nil { |
| return messageNameAlt(x) // populated by hooks_enabled.go |
| } |
| type xname interface { |
| XXX_MessageName() string |
| } |
| if m, ok := x.(xname); ok { |
| return m.XXX_MessageName() |
| } |
| return revProtoTypes[reflect.TypeOf(x)] |
| } |
| |
| // MessageType returns the message type (pointer to struct) for a named message. |
| // The type is not guaranteed to implement proto.Message if the name refers to a |
| // map entry. |
| func MessageType(name string) reflect.Type { |
| if messageTypeAlt != nil { |
| return messageTypeAlt(name) // populated by hooks_enabled.go |
| } |
| if t, ok := protoTypedNils[name]; ok { |
| return reflect.TypeOf(t) |
| } |
| return protoMapTypes[name] |
| } |
| |
| // A registry of all linked proto files. |
| var protoFiles = make(map[string][]byte) // file name => fileDescriptor |
| |
| // RegisterFile is called from generated code and maps from the |
| // full file name of a .proto file to its compressed FileDescriptorProto. |
| func RegisterFile(filename string, fileDescriptor []byte) { |
| if registerFileAlt != nil { |
| registerFileAlt(filename, fileDescriptor) // populated by hooks_enabled.go |
| return |
| } |
| protoFiles[filename] = fileDescriptor |
| } |
| |
| // FileDescriptor returns the compressed FileDescriptorProto for a .proto file. |
| func FileDescriptor(filename string) []byte { |
| if fileDescriptorAlt != nil { |
| return fileDescriptorAlt(filename) // populated by hooks_enabled.go |
| } |
| return protoFiles[filename] |
| } |
| |
| var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) |
| |
| // RegisterExtension is called from the generated code. |
| func RegisterExtension(desc *ExtensionDesc) { |
| if registerExtensionAlt != nil { |
| registerExtensionAlt(desc) // populated by hooks_enabled.go |
| return |
| } |
| st := reflect.TypeOf(desc.ExtendedType).Elem() |
| m := extensionMaps[st] |
| if m == nil { |
| m = make(map[int32]*ExtensionDesc) |
| extensionMaps[st] = m |
| } |
| if _, ok := m[desc.Field]; ok { |
| panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) |
| } |
| m[desc.Field] = desc |
| } |
| |
| // RegisteredExtensions returns a map of the registered extensions of a |
| // protocol buffer struct, indexed by the extension number. |
| // The argument pb should be a nil pointer to the struct type. |
| func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { |
| if registeredExtensionsAlt != nil { |
| return registeredExtensionsAlt(pb) // populated by hooks_enabled.go |
| } |
| return extensionMaps[reflect.TypeOf(pb).Elem()] |
| } |