1
2 #ifndef UPB_DEF_HPP_
3 #define UPB_DEF_HPP_
4
5 #include <cstring>
6 #include <memory>
7 #include <string>
8 #include <vector>
9
10 #include "upb/def.h"
11 #include "upb/upb.hpp"
12
13 namespace upb {
14
15 class EnumDefPtr;
16 class MessageDefPtr;
17 class OneofDefPtr;
18
19 // A upb::FieldDefPtr describes a single field in a message. It is most often
20 // found as a part of a upb_msgdef, but can also stand alone to represent
21 // an extension.
22 class FieldDefPtr {
23 public:
FieldDefPtr()24 FieldDefPtr() : ptr_(nullptr) {}
FieldDefPtr(const upb_fielddef * ptr)25 explicit FieldDefPtr(const upb_fielddef* ptr) : ptr_(ptr) {}
26
ptr() const27 const upb_fielddef* ptr() const { return ptr_; }
operator bool() const28 explicit operator bool() const { return ptr_ != nullptr; }
29
30 typedef upb_fieldtype_t Type;
31 typedef upb_label_t Label;
32 typedef upb_descriptortype_t DescriptorType;
33
full_name() const34 const char* full_name() const { return upb_fielddef_fullname(ptr_); }
35
type() const36 Type type() const { return upb_fielddef_type(ptr_); }
label() const37 Label label() const { return upb_fielddef_label(ptr_); }
name() const38 const char* name() const { return upb_fielddef_name(ptr_); }
json_name() const39 const char* json_name() const { return upb_fielddef_jsonname(ptr_); }
number() const40 uint32_t number() const { return upb_fielddef_number(ptr_); }
is_extension() const41 bool is_extension() const { return upb_fielddef_isextension(ptr_); }
42
43 // For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
44 // indicates whether this field should have lazy parsing handlers that yield
45 // the unparsed string for the submessage.
46 //
47 // TODO(haberman): I think we want to move this into a FieldOptions container
48 // when we add support for custom options (the FieldOptions struct will
49 // contain both regular FieldOptions like "lazy" *and* custom options).
lazy() const50 bool lazy() const { return upb_fielddef_lazy(ptr_); }
51
52 // For non-string, non-submessage fields, this indicates whether binary
53 // protobufs are encoded in packed or non-packed format.
54 //
55 // TODO(haberman): see note above about putting options like this into a
56 // FieldOptions container.
packed() const57 bool packed() const { return upb_fielddef_packed(ptr_); }
58
59 // An integer that can be used as an index into an array of fields for
60 // whatever message this field belongs to. Guaranteed to be less than
61 // f->containing_type()->field_count(). May only be accessed once the def has
62 // been finalized.
index() const63 uint32_t index() const { return upb_fielddef_index(ptr_); }
64
65 // The MessageDef to which this field belongs.
66 //
67 // If this field has been added to a MessageDef, that message can be retrieved
68 // directly (this is always the case for frozen FieldDefs).
69 //
70 // If the field has not yet been added to a MessageDef, you can set the name
71 // of the containing type symbolically instead. This is mostly useful for
72 // extensions, where the extension is declared separately from the message.
73 MessageDefPtr containing_type() const;
74
75 // The OneofDef to which this field belongs, or NULL if this field is not part
76 // of a oneof.
77 OneofDefPtr containing_oneof() const;
78
79 // The field's type according to the enum in descriptor.proto. This is not
80 // the same as UPB_TYPE_*, because it distinguishes between (for example)
81 // INT32 and SINT32, whereas our "type" enum does not. This return of
82 // descriptor_type() is a function of type(), integer_format(), and
83 // is_tag_delimited().
descriptor_type() const84 DescriptorType descriptor_type() const {
85 return upb_fielddef_descriptortype(ptr_);
86 }
87
88 // Convenient field type tests.
IsSubMessage() const89 bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); }
IsString() const90 bool IsString() const { return upb_fielddef_isstring(ptr_); }
IsSequence() const91 bool IsSequence() const { return upb_fielddef_isseq(ptr_); }
IsPrimitive() const92 bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); }
IsMap() const93 bool IsMap() const { return upb_fielddef_ismap(ptr_); }
94
95 // Returns the non-string default value for this fielddef, which may either
96 // be something the client set explicitly or the "default default" (0 for
97 // numbers, empty for strings). The field's type indicates the type of the
98 // returned value, except for enum fields that are still mutable.
99 //
100 // Requires that the given function matches the field's current type.
default_int64() const101 int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); }
default_int32() const102 int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); }
default_uint64() const103 uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); }
default_uint32() const104 uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); }
default_bool() const105 bool default_bool() const { return upb_fielddef_defaultbool(ptr_); }
default_float() const106 float default_float() const { return upb_fielddef_defaultfloat(ptr_); }
default_double() const107 double default_double() const { return upb_fielddef_defaultdouble(ptr_); }
108
109 // The resulting string is always NULL-terminated. If non-NULL, the length
110 // will be stored in *len.
default_string(size_t * len) const111 const char* default_string(size_t* len) const {
112 return upb_fielddef_defaultstr(ptr_, len);
113 }
114
115 // Returns the enum or submessage def for this field, if any. The field's
116 // type must match (ie. you may only call enum_subdef() for fields where
117 // type() == UPB_TYPE_ENUM).
118 EnumDefPtr enum_subdef() const;
119 MessageDefPtr message_subdef() const;
120
121 private:
122 const upb_fielddef* ptr_;
123 };
124
125 // Class that represents a oneof.
126 class OneofDefPtr {
127 public:
OneofDefPtr()128 OneofDefPtr() : ptr_(nullptr) {}
OneofDefPtr(const upb_oneofdef * ptr)129 explicit OneofDefPtr(const upb_oneofdef* ptr) : ptr_(ptr) {}
130
ptr() const131 const upb_oneofdef* ptr() const { return ptr_; }
operator bool() const132 explicit operator bool() const { return ptr_ != nullptr; }
133
134 // Returns the MessageDef that contains this OneofDef.
135 MessageDefPtr containing_type() const;
136
137 // Returns the name of this oneof.
name() const138 const char* name() const { return upb_oneofdef_name(ptr_); }
139
140 // Returns the number of fields in the oneof.
field_count() const141 int field_count() const { return upb_oneofdef_numfields(ptr_); }
field(int i) const142 FieldDefPtr field(int i) const { return FieldDefPtr(upb_oneofdef_field(ptr_, i)); }
143
144 // Looks up by name.
FindFieldByName(const char * name,size_t len) const145 FieldDefPtr FindFieldByName(const char* name, size_t len) const {
146 return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len));
147 }
FindFieldByName(const char * name) const148 FieldDefPtr FindFieldByName(const char* name) const {
149 return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name));
150 }
151
152 template <class T>
FindFieldByName(const T & str) const153 FieldDefPtr FindFieldByName(const T& str) const {
154 return FindFieldByName(str.c_str(), str.size());
155 }
156
157 // Looks up by tag number.
FindFieldByNumber(uint32_t num) const158 FieldDefPtr FindFieldByNumber(uint32_t num) const {
159 return FieldDefPtr(upb_oneofdef_itof(ptr_, num));
160 }
161
162 private:
163 const upb_oneofdef* ptr_;
164 };
165
166 // Structure that describes a single .proto message type.
167 class MessageDefPtr {
168 public:
MessageDefPtr()169 MessageDefPtr() : ptr_(nullptr) {}
MessageDefPtr(const upb_msgdef * ptr)170 explicit MessageDefPtr(const upb_msgdef* ptr) : ptr_(ptr) {}
171
ptr() const172 const upb_msgdef* ptr() const { return ptr_; }
operator bool() const173 explicit operator bool() const { return ptr_ != nullptr; }
174
full_name() const175 const char* full_name() const { return upb_msgdef_fullname(ptr_); }
name() const176 const char* name() const { return upb_msgdef_name(ptr_); }
177
178 // The number of fields that belong to the MessageDef.
field_count() const179 int field_count() const { return upb_msgdef_numfields(ptr_); }
field(int i) const180 FieldDefPtr field(int i) const { return FieldDefPtr(upb_msgdef_field(ptr_, i)); }
181
182 // The number of oneofs that belong to the MessageDef.
oneof_count() const183 int oneof_count() const { return upb_msgdef_numoneofs(ptr_); }
oneof(int i) const184 OneofDefPtr oneof(int i) const { return OneofDefPtr(upb_msgdef_oneof(ptr_, i)); }
185
syntax() const186 upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); }
187
188 // These return null pointers if the field is not found.
FindFieldByNumber(uint32_t number) const189 FieldDefPtr FindFieldByNumber(uint32_t number) const {
190 return FieldDefPtr(upb_msgdef_itof(ptr_, number));
191 }
FindFieldByName(const char * name,size_t len) const192 FieldDefPtr FindFieldByName(const char* name, size_t len) const {
193 return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len));
194 }
FindFieldByName(const char * name) const195 FieldDefPtr FindFieldByName(const char* name) const {
196 return FieldDefPtr(upb_msgdef_ntofz(ptr_, name));
197 }
198
199 template <class T>
FindFieldByName(const T & str) const200 FieldDefPtr FindFieldByName(const T& str) const {
201 return FindFieldByName(str.c_str(), str.size());
202 }
203
FindOneofByName(const char * name,size_t len) const204 OneofDefPtr FindOneofByName(const char* name, size_t len) const {
205 return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len));
206 }
207
FindOneofByName(const char * name) const208 OneofDefPtr FindOneofByName(const char* name) const {
209 return OneofDefPtr(upb_msgdef_ntooz(ptr_, name));
210 }
211
212 template <class T>
FindOneofByName(const T & str) const213 OneofDefPtr FindOneofByName(const T& str) const {
214 return FindOneofByName(str.c_str(), str.size());
215 }
216
217 // Is this message a map entry?
mapentry() const218 bool mapentry() const { return upb_msgdef_mapentry(ptr_); }
219
220 // Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for
221 // non-well-known message.
wellknowntype() const222 upb_wellknowntype_t wellknowntype() const {
223 return upb_msgdef_wellknowntype(ptr_);
224 }
225
226 // Whether is a number wrapper.
isnumberwrapper() const227 bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); }
228
229 private:
230 class FieldIter {
231 public:
FieldIter(const upb_msgdef * m,int i)232 explicit FieldIter(const upb_msgdef *m, int i) : m_(m), i_(i) {}
operator ++()233 void operator++() { i_++; }
234
operator *()235 FieldDefPtr operator*() { return FieldDefPtr(upb_msgdef_field(m_, i_)); }
operator !=(const FieldIter & other)236 bool operator!=(const FieldIter& other) { return i_ != other.i_; }
operator ==(const FieldIter & other)237 bool operator==(const FieldIter& other) { return i_ == other.i_; }
238
239 private:
240 const upb_msgdef *m_;
241 int i_;
242 };
243
244 class FieldAccessor {
245 public:
FieldAccessor(const upb_msgdef * md)246 explicit FieldAccessor(const upb_msgdef* md) : md_(md) {}
begin()247 FieldIter begin() { return FieldIter(md_, 0); }
end()248 FieldIter end() { return FieldIter(md_, upb_msgdef_fieldcount(md_)); }
249
250 private:
251 const upb_msgdef* md_;
252 };
253
254 class OneofIter {
255 public:
OneofIter(const upb_msgdef * m,int i)256 explicit OneofIter(const upb_msgdef *m, int i) : m_(m), i_(i) {}
operator ++()257 void operator++() { i_++; }
258
operator *()259 OneofDefPtr operator*() { return OneofDefPtr(upb_msgdef_oneof(m_, i_)); }
operator !=(const OneofIter & other)260 bool operator!=(const OneofIter& other) { return i_ != other.i_; }
operator ==(const OneofIter & other)261 bool operator==(const OneofIter& other) { return i_ == other.i_; }
262
263 private:
264 const upb_msgdef *m_;
265 int i_;
266 };
267
268 class OneofAccessor {
269 public:
OneofAccessor(const upb_msgdef * md)270 explicit OneofAccessor(const upb_msgdef* md) : md_(md) {}
begin()271 OneofIter begin() { return OneofIter(md_, 0); }
end()272 OneofIter end() { return OneofIter(md_, upb_msgdef_oneofcount(md_)); }
273
274 private:
275 const upb_msgdef* md_;
276 };
277
278 public:
fields() const279 FieldAccessor fields() const { return FieldAccessor(ptr()); }
oneofs() const280 OneofAccessor oneofs() const { return OneofAccessor(ptr()); }
281
282 private:
283 const upb_msgdef* ptr_;
284 };
285
286 class EnumDefPtr {
287 public:
EnumDefPtr()288 EnumDefPtr() : ptr_(nullptr) {}
EnumDefPtr(const upb_enumdef * ptr)289 explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {}
290
ptr() const291 const upb_enumdef* ptr() const { return ptr_; }
operator bool() const292 explicit operator bool() const { return ptr_ != nullptr; }
293
full_name() const294 const char* full_name() const { return upb_enumdef_fullname(ptr_); }
name() const295 const char* name() const { return upb_enumdef_name(ptr_); }
296
297 // The value that is used as the default when no field default is specified.
298 // If not set explicitly, the first value that was added will be used.
299 // The default value must be a member of the enum.
300 // Requires that value_count() > 0.
default_value() const301 int32_t default_value() const { return upb_enumdef_default(ptr_); }
302
303 // Returns the number of values currently defined in the enum. Note that
304 // multiple names can refer to the same number, so this may be greater than
305 // the total number of unique numbers.
value_count() const306 int value_count() const { return upb_enumdef_numvals(ptr_); }
307
308 // Lookups from name to integer, returning true if found.
FindValueByName(const char * name,int32_t * num) const309 bool FindValueByName(const char* name, int32_t* num) const {
310 return upb_enumdef_ntoiz(ptr_, name, num);
311 }
312
313 // Finds the name corresponding to the given number, or NULL if none was
314 // found. If more than one name corresponds to this number, returns the
315 // first one that was added.
FindValueByNumber(int32_t num) const316 const char* FindValueByNumber(int32_t num) const {
317 return upb_enumdef_iton(ptr_, num);
318 }
319
320 // Iteration over name/value pairs. The order is undefined.
321 // Adding an enum val invalidates any iterators.
322 //
323 // TODO: make compatible with range-for, with elements as pairs?
324 class Iterator {
325 public:
Iterator(EnumDefPtr e)326 explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); }
327
number()328 int32_t number() { return upb_enum_iter_number(&iter_); }
name()329 const char* name() { return upb_enum_iter_name(&iter_); }
Done()330 bool Done() { return upb_enum_done(&iter_); }
Next()331 void Next() { return upb_enum_next(&iter_); }
332
333 private:
334 upb_enum_iter iter_;
335 };
336
337 private:
338 const upb_enumdef* ptr_;
339 };
340
341 // Class that represents a .proto file with some things defined in it.
342 //
343 // Many users won't care about FileDefs, but they are necessary if you want to
344 // read the values of file-level options.
345 class FileDefPtr {
346 public:
FileDefPtr(const upb_filedef * ptr)347 explicit FileDefPtr(const upb_filedef* ptr) : ptr_(ptr) {}
348
ptr() const349 const upb_filedef* ptr() const { return ptr_; }
operator bool() const350 explicit operator bool() const { return ptr_ != nullptr; }
351
352 // Get/set name of the file (eg. "foo/bar.proto").
name() const353 const char* name() const { return upb_filedef_name(ptr_); }
354
355 // Package name for definitions inside the file (eg. "foo.bar").
package() const356 const char* package() const { return upb_filedef_package(ptr_); }
357
358 // Sets the php class prefix which is prepended to all php generated classes
359 // from this .proto. Default is empty.
phpprefix() const360 const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); }
361
362 // Use this option to change the namespace of php generated classes. Default
363 // is empty. When this option is empty, the package name will be used for
364 // determining the namespace.
phpnamespace() const365 const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); }
366
367 // Syntax for the file. Defaults to proto2.
syntax() const368 upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); }
369
370 // Get the list of dependencies from the file. These are returned in the
371 // order that they were added to the FileDefPtr.
dependency_count() const372 int dependency_count() const { return upb_filedef_depcount(ptr_); }
dependency(int index) const373 const FileDefPtr dependency(int index) const {
374 return FileDefPtr(upb_filedef_dep(ptr_, index));
375 }
376
377 private:
378 const upb_filedef* ptr_;
379 };
380
381 // Non-const methods in upb::SymbolTable are NOT thread-safe.
382 class SymbolTable {
383 public:
SymbolTable()384 SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {}
SymbolTable(upb_symtab * s)385 explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {}
386
ptr() const387 const upb_symtab* ptr() const { return ptr_.get(); }
ptr()388 upb_symtab* ptr() { return ptr_.get(); }
389
390 // Finds an entry in the symbol table with this exact name. If not found,
391 // returns NULL.
LookupMessage(const char * sym) const392 MessageDefPtr LookupMessage(const char* sym) const {
393 return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym));
394 }
395
LookupEnum(const char * sym) const396 EnumDefPtr LookupEnum(const char* sym) const {
397 return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym));
398 }
399
LookupFile(const char * name) const400 FileDefPtr LookupFile(const char* name) const {
401 return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name));
402 }
403
404 // TODO: iteration?
405
406 // Adds the given serialized FileDescriptorProto to the pool.
AddFile(const google_protobuf_FileDescriptorProto * file_proto,Status * status)407 FileDefPtr AddFile(const google_protobuf_FileDescriptorProto* file_proto,
408 Status* status) {
409 return FileDefPtr(
410 upb_symtab_addfile(ptr_.get(), file_proto, status->ptr()));
411 }
412
413 private:
414 std::unique_ptr<upb_symtab, decltype(&upb_symtab_free)> ptr_;
415 };
416
message_subdef() const417 inline MessageDefPtr FieldDefPtr::message_subdef() const {
418 return MessageDefPtr(upb_fielddef_msgsubdef(ptr_));
419 }
420
containing_type() const421 inline MessageDefPtr FieldDefPtr::containing_type() const {
422 return MessageDefPtr(upb_fielddef_containingtype(ptr_));
423 }
424
containing_type() const425 inline MessageDefPtr OneofDefPtr::containing_type() const {
426 return MessageDefPtr(upb_oneofdef_containingtype(ptr_));
427 }
428
containing_oneof() const429 inline OneofDefPtr FieldDefPtr::containing_oneof() const {
430 return OneofDefPtr(upb_fielddef_containingoneof(ptr_));
431 }
432
enum_subdef() const433 inline EnumDefPtr FieldDefPtr::enum_subdef() const {
434 return EnumDefPtr(upb_fielddef_enumsubdef(ptr_));
435 }
436
437 } // namespace upb
438
439 #endif // UPB_DEF_HPP_
440