blob: 59b77ebce5abff4ff62544eb2393f50927cb5d5a [file] [log] [blame]
khenaidooa46458b2021-12-15 16:50:44 -05001// Package dynamic provides an implementation for a dynamic protobuf message.
2//
3// The dynamic message is essentially a message descriptor along with a map of
4// tag numbers to values. It has a broad API for interacting with the message,
5// including inspection and modification. Generally, most operations have two
6// forms: a regular method that panics on bad input or error and a "Try" form
7// of the method that will instead return an error.
8//
9// A dynamic message can optionally be constructed with a MessageFactory. The
10// MessageFactory has various registries that may be used by the dynamic message,
11// such as during de-serialization. The message factory is "inherited" by any
12// other dynamic messages created, such as nested messages that are created
13// during de-serialization. Similarly, any dynamic message created using
14// MessageFactory.NewMessage will be associated with that factory, which in turn
15// will be used to create other messages or parse extension fields during
16// de-serialization.
17//
Abhay Kumara2ae5992025-11-10 14:02:24 +000018// # Field Types
khenaidooa46458b2021-12-15 16:50:44 -050019//
20// The types of values expected by setters and returned by getters are the
21// same as protoc generates for scalar fields. For repeated fields, there are
22// methods for getting and setting values at a particular index or for adding
23// an element. Similarly, for map fields, there are methods for getting and
24// setting values for a particular key.
25//
26// If you use GetField for a repeated field, it will return a copy of all
27// elements as a slice []interface{}. Similarly, using GetField for a map field
28// will return a copy of all mappings as a map[interface{}]interface{}. You can
29// also use SetField to supply an entire slice or map for repeated or map fields.
30// The slice need not be []interface{} but can actually be typed according to
31// the field's expected type. For example, a repeated uint64 field can be set
32// using a slice of type []uint64.
33//
34// Descriptors for map fields describe them as repeated fields with a nested
35// message type. The nested message type is a special generated type that
36// represents a single mapping: key and value pair. The dynamic message has some
37// special affordances for this representation. For example, you can use
38// SetField to set a map field using a slice of these entry messages. Internally,
39// the slice of entries will be converted to an actual map. Similarly, you can
40// use AddRepeatedField with an entry message to add (or overwrite) a mapping.
41// However, you cannot use GetRepeatedField or SetRepeatedField to modify maps,
42// since those take numeric index arguments which are not relevant to maps
43// (since maps in Go have no defined ordering).
44//
45// When setting field values in dynamic messages, the type-checking is lenient
46// in that it accepts any named type with the right kind. So a string field can
47// be assigned to any type that is defined as a string. Enum fields require
48// int32 values (or any type that is defined as an int32).
49//
50// Unlike normal use of numeric values in Go, values will be automatically
51// widened when assigned. So, for example, an int64 field can be set using an
52// int32 value since it can be safely widened without truncation or loss of
53// precision. Similar goes for uint32 values being converted to uint64 and
54// float32 being converted to float64. Narrowing conversions are not done,
55// however. Also, unsigned values will never be automatically converted to
56// signed (and vice versa), and floating point values will never be
57// automatically converted to integral values (and vice versa). Since the bit
58// width of int and uint fields is allowed to be platform dependent, but will
59// always be less than or equal to 64, they can only be used as values for
60// int64 and uint64 fields, respectively. They cannot be used to set int32 or
61// uint32 fields, which includes enums fields.
62//
63// Fields whose type is a nested message can have values set to either other
64// dynamic messages or generated messages (e.g. pointers to structs generated by
65// protoc). Getting a value for such a field will return the actual type it is
66// set to (e.g. either a dynamic message or a generated message). If the value
67// is not set and the message uses proto2 syntax, the default message returned
68// will be whatever is returned by the dynamic message's MessageFactory (if the
69// dynamic message was not created with a factory, it will use the logic of the
70// zero value factory). In most typical cases, it will return a dynamic message,
71// but if the factory is configured with a KnownTypeRegistry, or if the field's
72// type is a well-known type, it will return a zero value generated message.
73//
Abhay Kumara2ae5992025-11-10 14:02:24 +000074// # Unrecognized Fields
khenaidooa46458b2021-12-15 16:50:44 -050075//
76// Unrecognized fields are preserved by the dynamic message when unmarshaling
77// from the standard binary format. If the message's MessageFactory was
78// configured with an ExtensionRegistry, it will be used to identify and parse
79// extension fields for the message.
80//
81// Unrecognized fields can dynamically become recognized fields if the
82// application attempts to retrieve an unrecognized field's value using a
83// FieldDescriptor. In this case, the given FieldDescriptor is used to parse the
84// unknown field and move the parsed value into the message's set of known
85// fields. This behavior is most suited to the use of extensions, where an
86// ExtensionRegistry is not setup with all known extensions ahead of time. But
87// it can even happen for non-extension fields! Here's an example scenario where
88// a non-extension field can initially be unknown and become known:
89//
Abhay Kumara2ae5992025-11-10 14:02:24 +000090// 1. A dynamic message is created with a descriptor, A, and then
91// de-serialized from a stream of bytes. The stream includes an
92// unrecognized tag T. The message will include tag T in its unrecognized
93// field set.
94// 2. Another call site retrieves a newer descriptor, A', which includes a
95// newly added field with tag T.
96// 3. That other call site then uses a FieldDescriptor to access the value of
97// the new field. This will cause the dynamic message to parse the bytes
98// for the unknown tag T and store them as a known field.
99// 4. Subsequent operations for tag T, including setting the field using only
100// tag number or de-serializing a stream that includes tag T, will operate
101// as if that tag were part of the original descriptor, A.
khenaidooa46458b2021-12-15 16:50:44 -0500102//
Abhay Kumara2ae5992025-11-10 14:02:24 +0000103// # Compatibility
khenaidooa46458b2021-12-15 16:50:44 -0500104//
105// In addition to implementing the proto.Message interface, the included
106// Message type also provides an XXX_MessageName() method, so it can work with
107// proto.MessageName. And it provides a Descriptor() method that behaves just
108// like the method of the same signature in messages generated by protoc.
109// Because of this, it is actually compatible with proto.Message in many (though
110// not all) contexts. In particular, it is compatible with proto.Marshal and
111// proto.Unmarshal for serializing and de-serializing messages.
112//
113// The dynamic message supports binary and text marshaling, using protobuf's
114// well-defined binary format and the same text format that protoc-generated
115// types use. It also supports JSON serialization/de-serialization by
116// implementing the json.Marshaler and json.Unmarshaler interfaces. And dynamic
117// messages can safely be used with the jsonpb package for JSON serialization
118// and de-serialization.
119//
120// In addition to implementing the proto.Message interface and numerous related
121// methods, it also provides inter-op with generated messages via conversion.
122// The ConvertTo, ConvertFrom, MergeInto, and MergeFrom methods copy message
123// contents from a dynamic message to a generated message and vice versa.
124//
125// When copying from a generated message into a dynamic message, if the
126// generated message contains fields unknown to the dynamic message (e.g. not
127// present in the descriptor used to create the dynamic message), these fields
128// become known to the dynamic message (as per behavior described above in
129// "Unrecognized Fields"). If the generated message has unrecognized fields of
130// its own, including unrecognized extensions, they are preserved in the dynamic
131// message. It is possible that the dynamic message knows about fields that the
132// generated message did not, like if it has a different version of the
133// descriptor or its MessageFactory has an ExtensionRegistry that knows about
134// different extensions than were linked into the program. In this case, these
135// unrecognized fields in the generated message will be known fields in the
136// dynamic message.
137//
138// Similarly, when copying from a dynamic message into a generated message, if
139// the dynamic message has unrecognized fields they can be preserved in the
140// generated message (currently only for syntax proto2 since proto3 generated
141// messages do not preserve unrecognized fields). If the generated message knows
142// about fields that the dynamic message does not, these unrecognized fields may
143// become known fields in the generated message.
144//
Abhay Kumara2ae5992025-11-10 14:02:24 +0000145// # Registries
khenaidooa46458b2021-12-15 16:50:44 -0500146//
147// This package also contains a couple of registries, for managing known types
148// and descriptors.
149//
150// The KnownTypeRegistry allows de-serialization of a dynamic message to use
151// generated message types, instead of dynamic messages, for some kinds of
152// nested message fields. This is particularly useful for working with proto
153// messages that have special encodings as JSON (e.g. the well-known types),
154// since the dynamic message does not try to handle these special cases in its
155// JSON marshaling facilities.
156//
157// The ExtensionRegistry allows for recognizing and parsing extensions fields
158// (for proto2 messages).
Abhay Kumara2ae5992025-11-10 14:02:24 +0000159//
160// Deprecated: This module was created for use with the older "v1" Protobuf API
161// in github.com/golang/protobuf. However, much of this module is no longer
162// necessary as the newer "v2" API in google.golang.org/protobuf provides similar
163// capabilities. Instead of using this github.com/jhump/protoreflect/dynamic package,
164// see [google.golang.org/protobuf/types/dynamicpb].
165//
166// [google.golang.org/protobuf/types/dynamicpb]: https://pkg.go.dev/google.golang.org/protobuf/types/dynamicpb
khenaidooa46458b2021-12-15 16:50:44 -0500167package dynamic