github.com/Big-big-orange/protoreflect@v0.0.0-20240408141420-285cedfdf6a4/dynamic/message_factory.go (about) 1 package dynamic 2 3 import ( 4 "reflect" 5 "sync" 6 7 "github.com/golang/protobuf/proto" 8 9 "github.com/Big-big-orange/protoreflect/desc" 10 ) 11 12 // MessageFactory can be used to create new empty message objects. A default instance 13 // (without extension registry or known-type registry specified) will always return 14 // dynamic messages (e.g. type will be *dynamic.Message) except for "well-known" types. 15 // The well-known types include primitive wrapper types and a handful of other special 16 // types defined in standard protobuf definitions, like Any, Duration, and Timestamp. 17 type MessageFactory struct { 18 er *ExtensionRegistry 19 ktr *KnownTypeRegistry 20 } 21 22 // NewMessageFactoryWithExtensionRegistry creates a new message factory where any 23 // dynamic messages produced will use the given extension registry to recognize and 24 // parse extension fields. 25 func NewMessageFactoryWithExtensionRegistry(er *ExtensionRegistry) *MessageFactory { 26 return NewMessageFactoryWithRegistries(er, nil) 27 } 28 29 // NewMessageFactoryWithKnownTypeRegistry creates a new message factory where the 30 // known types, per the given registry, will be returned as normal protobuf messages 31 // (e.g. generated structs, instead of dynamic messages). 32 func NewMessageFactoryWithKnownTypeRegistry(ktr *KnownTypeRegistry) *MessageFactory { 33 return NewMessageFactoryWithRegistries(nil, ktr) 34 } 35 36 // NewMessageFactoryWithDefaults creates a new message factory where all "default" types 37 // (those for which protoc-generated code is statically linked into the Go program) are 38 // known types. If any dynamic messages are produced, they will recognize and parse all 39 // "default" extension fields. This is the equivalent of: 40 // 41 // NewMessageFactoryWithRegistries( 42 // NewExtensionRegistryWithDefaults(), 43 // NewKnownTypeRegistryWithDefaults()) 44 func NewMessageFactoryWithDefaults() *MessageFactory { 45 return NewMessageFactoryWithRegistries(NewExtensionRegistryWithDefaults(), NewKnownTypeRegistryWithDefaults()) 46 } 47 48 // NewMessageFactoryWithRegistries creates a new message factory with the given extension 49 // and known type registries. 50 func NewMessageFactoryWithRegistries(er *ExtensionRegistry, ktr *KnownTypeRegistry) *MessageFactory { 51 return &MessageFactory{ 52 er: er, 53 ktr: ktr, 54 } 55 } 56 57 // NewMessage creates a new empty message that corresponds to the given descriptor. 58 // If the given descriptor describes a "known type" then that type is instantiated. 59 // Otherwise, an empty dynamic message is returned. 60 func (f *MessageFactory) NewMessage(md *desc.MessageDescriptor) proto.Message { 61 var ktr *KnownTypeRegistry 62 if f != nil { 63 ktr = f.ktr 64 } 65 if m := ktr.CreateIfKnown(md.GetFullyQualifiedName()); m != nil { 66 return m 67 } 68 return NewMessageWithMessageFactory(md, f) 69 } 70 71 // NewDynamicMessage creates a new empty dynamic message that corresponds to the given 72 // descriptor. This is like f.NewMessage(md) except the known type registry is not 73 // consulted so the return value is always a dynamic message. 74 // 75 // This is also like dynamic.NewMessage(md) except that the returned message will use 76 // this factory when creating other messages, like during de-serialization of fields 77 // that are themselves message types. 78 func (f *MessageFactory) NewDynamicMessage(md *desc.MessageDescriptor) *Message { 79 return NewMessageWithMessageFactory(md, f) 80 } 81 82 // GetKnownTypeRegistry returns the known type registry that this factory uses to 83 // instantiate known (e.g. generated) message types. 84 func (f *MessageFactory) GetKnownTypeRegistry() *KnownTypeRegistry { 85 if f == nil { 86 return nil 87 } 88 return f.ktr 89 } 90 91 // GetExtensionRegistry returns the extension registry that this factory uses to 92 // create dynamic messages. The registry is used by dynamic messages to recognize 93 // and parse extension fields during de-serialization. 94 func (f *MessageFactory) GetExtensionRegistry() *ExtensionRegistry { 95 if f == nil { 96 return nil 97 } 98 return f.er 99 } 100 101 type wkt interface { 102 XXX_WellKnownType() string 103 } 104 105 var typeOfWkt = reflect.TypeOf((*wkt)(nil)).Elem() 106 107 // KnownTypeRegistry is a registry of known message types, as identified by their 108 // fully-qualified name. A known message type is one for which a protoc-generated 109 // struct exists, so a dynamic message is not necessary to represent it. A 110 // MessageFactory uses a KnownTypeRegistry to decide whether to create a generated 111 // struct or a dynamic message. The zero-value registry (including the behavior of 112 // a nil pointer) only knows about the "well-known types" in protobuf. These 113 // include only the wrapper types and a handful of other special types like Any, 114 // Duration, and Timestamp. 115 type KnownTypeRegistry struct { 116 excludeWkt bool 117 includeDefault bool 118 mu sync.RWMutex 119 types map[string]reflect.Type 120 } 121 122 // NewKnownTypeRegistryWithDefaults creates a new registry that knows about all 123 // "default" types (those for which protoc-generated code is statically linked 124 // into the Go program). 125 func NewKnownTypeRegistryWithDefaults() *KnownTypeRegistry { 126 return &KnownTypeRegistry{includeDefault: true} 127 } 128 129 // NewKnownTypeRegistryWithoutWellKnownTypes creates a new registry that does *not* 130 // include the "well-known types" in protobuf. So even well-known types would be 131 // represented by a dynamic message. 132 func NewKnownTypeRegistryWithoutWellKnownTypes() *KnownTypeRegistry { 133 return &KnownTypeRegistry{excludeWkt: true} 134 } 135 136 // AddKnownType adds the types of the given messages as known types. 137 func (r *KnownTypeRegistry) AddKnownType(kts ...proto.Message) { 138 r.mu.Lock() 139 defer r.mu.Unlock() 140 if r.types == nil { 141 r.types = map[string]reflect.Type{} 142 } 143 for _, kt := range kts { 144 r.types[proto.MessageName(kt)] = reflect.TypeOf(kt) 145 } 146 } 147 148 // CreateIfKnown will construct an instance of the given message if it is a known type. 149 // If the given name is unknown, nil is returned. 150 func (r *KnownTypeRegistry) CreateIfKnown(messageName string) proto.Message { 151 msgType := r.GetKnownType(messageName) 152 if msgType == nil { 153 return nil 154 } 155 156 if msgType.Kind() == reflect.Ptr { 157 return reflect.New(msgType.Elem()).Interface().(proto.Message) 158 } else { 159 return reflect.New(msgType).Elem().Interface().(proto.Message) 160 } 161 } 162 163 func isWellKnownType(t reflect.Type) bool { 164 if t.Implements(typeOfWkt) { 165 return true 166 } 167 if msg, ok := reflect.Zero(t).Interface().(proto.Message); ok { 168 name := proto.MessageName(msg) 169 _, ok := wellKnownTypeNames[name] 170 return ok 171 } 172 return false 173 } 174 175 // GetKnownType will return the reflect.Type for the given message name if it is 176 // known. If it is not known, nil is returned. 177 func (r *KnownTypeRegistry) GetKnownType(messageName string) reflect.Type { 178 if r == nil { 179 // a nil registry behaves the same as zero value instance: only know of well-known types 180 t := proto.MessageType(messageName) 181 if t != nil && isWellKnownType(t) { 182 return t 183 } 184 return nil 185 } 186 187 if r.includeDefault { 188 t := proto.MessageType(messageName) 189 if t != nil && isMessage(t) { 190 return t 191 } 192 } else if !r.excludeWkt { 193 t := proto.MessageType(messageName) 194 if t != nil && isWellKnownType(t) { 195 return t 196 } 197 } 198 199 r.mu.RLock() 200 defer r.mu.RUnlock() 201 return r.types[messageName] 202 } 203 204 func isMessage(t reflect.Type) bool { 205 _, ok := reflect.Zero(t).Interface().(proto.Message) 206 return ok 207 }