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  }