• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "def.h"
9 
10 #include <php.h>
11 
12 // This is not self-contained: it must be after other Zend includes.
13 #include <Zend/zend_exceptions.h>
14 
15 #include "names.h"
16 #include "php-upb.h"
17 #include "protobuf.h"
18 
CheckUpbStatus(const upb_Status * status,const char * msg)19 static void CheckUpbStatus(const upb_Status* status, const char* msg) {
20   if (!upb_Status_IsOk(status)) {
21     zend_error(E_ERROR, "%s: %s\n", msg, upb_Status_ErrorMessage(status));
22   }
23 }
24 
25 static void FieldDescriptor_FromFieldDef(zval* val, const upb_FieldDef* f);
26 
27 // We use this for objects that should not be created directly from PHP.
CreateHandler_ReturnNull(zend_class_entry * class_type)28 static zend_object* CreateHandler_ReturnNull(zend_class_entry* class_type) {
29   return NULL;  // Nobody should call this.
30 }
31 
32 // clang-format off
33 ZEND_BEGIN_ARG_INFO_EX(arginfo_getByIndex, 0, 0, 1)
34   ZEND_ARG_INFO(0, index)
35 ZEND_END_ARG_INFO()
36 // clang-format on
37 
38 // -----------------------------------------------------------------------------
39 // EnumValueDescriptor
40 // -----------------------------------------------------------------------------
41 
42 typedef struct {
43   zend_object std;
44   const char* name;
45   int32_t number;
46 } EnumValueDescriptor;
47 
48 zend_class_entry* EnumValueDescriptor_class_entry;
49 static zend_object_handlers EnumValueDescriptor_object_handlers;
50 
51 /*
52  * EnumValueDescriptor_Make()
53  *
54  * Function to create an EnumValueDescriptor object from C.
55  */
EnumValueDescriptor_Make(zval * val,const char * name,int32_t number)56 static void EnumValueDescriptor_Make(zval* val, const char* name,
57                                      int32_t number) {
58   EnumValueDescriptor* intern = emalloc(sizeof(EnumValueDescriptor));
59   zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry);
60   intern->std.handlers = &EnumValueDescriptor_object_handlers;
61   intern->name = name;
62   intern->number = number;
63   // Skip object_properties_init(), we don't allow derived classes.
64   ZVAL_OBJ(val, &intern->std);
65 }
66 
67 /*
68  * EnumValueDescriptor::getName()
69  *
70  * Returns the name for this enum value.
71  */
PHP_METHOD(EnumValueDescriptor,getName)72 PHP_METHOD(EnumValueDescriptor, getName) {
73   EnumValueDescriptor* intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
74   RETURN_STRING(intern->name);
75 }
76 
77 /*
78  * EnumValueDescriptor::getNumber()
79  *
80  * Returns the number for this enum value.
81  */
PHP_METHOD(EnumValueDescriptor,getNumber)82 PHP_METHOD(EnumValueDescriptor, getNumber) {
83   EnumValueDescriptor* intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
84   RETURN_LONG(intern->number);
85 }
86 
87 // clang-format off
88 static zend_function_entry EnumValueDescriptor_methods[] = {
89   PHP_ME(EnumValueDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC)
90   PHP_ME(EnumValueDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
91   ZEND_FE_END
92 };
93 // clang-format on
94 
95 // -----------------------------------------------------------------------------
96 // EnumDescriptor
97 // -----------------------------------------------------------------------------
98 
99 typedef struct {
100   zend_object std;
101   const upb_EnumDef* enumdef;
102   void* cache_key;
103 } EnumDescriptor;
104 
105 zend_class_entry* EnumDescriptor_class_entry;
106 static zend_object_handlers EnumDescriptor_object_handlers;
107 
EnumDescriptor_destructor(zend_object * obj)108 static void EnumDescriptor_destructor(zend_object* obj) {
109   EnumDescriptor* intern = (EnumDescriptor*)obj;
110   ObjCache_Delete(intern->cache_key);
111 }
112 
113 // Caller owns a ref on the returned zval.
EnumDescriptor_FromClassEntry(zval * val,zend_class_entry * ce)114 static void EnumDescriptor_FromClassEntry(zval* val, zend_class_entry* ce) {
115   // To differentiate enums from classes, we pointer-tag the class entry.
116   void* key = (void*)((uintptr_t)ce | 1);
117   PBPHP_ASSERT(key != ce);
118 
119   if (ce == NULL) {
120     ZVAL_NULL(val);
121     return;
122   }
123 
124   if (!ObjCache_Get(key, val)) {
125     const upb_EnumDef* e = NameMap_GetEnum(ce);
126     if (!e) {
127       ZVAL_NULL(val);
128       return;
129     }
130     EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor));
131     zend_object_std_init(&ret->std, EnumDescriptor_class_entry);
132     ret->std.handlers = &EnumDescriptor_object_handlers;
133     ret->enumdef = e;
134     ret->cache_key = key;
135     ObjCache_Add(key, &ret->std);
136     ZVAL_OBJ(val, &ret->std);
137   }
138 }
139 
140 // Caller owns a ref on the returned zval.
EnumDescriptor_FromEnumDef(zval * val,const upb_EnumDef * m)141 static void EnumDescriptor_FromEnumDef(zval* val, const upb_EnumDef* m) {
142   if (!m) {
143     ZVAL_NULL(val);
144   } else {
145     char* classname =
146         GetPhpClassname(upb_EnumDef_File(m), upb_EnumDef_FullName(m), false);
147     zend_string* str = zend_string_init(classname, strlen(classname), 0);
148     zend_class_entry* ce = zend_lookup_class(str);  // May autoload the class.
149 
150     zend_string_release(str);
151 
152     if (!ce) {
153       zend_error(E_ERROR, "Couldn't load generated class %s", classname);
154     }
155 
156     free(classname);
157     EnumDescriptor_FromClassEntry(val, ce);
158   }
159 }
160 
161 /*
162  * EnumDescriptor::getValue()
163  *
164  * Returns an EnumValueDescriptor for this index. Note: we are not looking
165  * up by numeric enum value, but by the index in the list of enum values.
166  */
PHP_METHOD(EnumDescriptor,getValue)167 PHP_METHOD(EnumDescriptor, getValue) {
168   EnumDescriptor* intern = (EnumDescriptor*)Z_OBJ_P(getThis());
169   zend_long index;
170   zval ret;
171 
172   if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
173     zend_error(E_USER_ERROR, "Expect integer for index.\n");
174     return;
175   }
176 
177   if (index < 0 || index >= upb_EnumDef_ValueCount(intern->enumdef)) {
178     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
179     return;
180   }
181 
182   const upb_EnumValueDef* ev = upb_EnumDef_Value(intern->enumdef, index);
183   EnumValueDescriptor_Make(&ret, upb_EnumValueDef_Name(ev),
184                            upb_EnumValueDef_Number(ev));
185   RETURN_COPY_VALUE(&ret);
186 }
187 
188 /*
189  * EnumDescriptor::getValueCount()
190  *
191  * Returns the number of values in this enum.
192  */
PHP_METHOD(EnumDescriptor,getValueCount)193 PHP_METHOD(EnumDescriptor, getValueCount) {
194   EnumDescriptor* intern = (EnumDescriptor*)Z_OBJ_P(getThis());
195   RETURN_LONG(upb_EnumDef_ValueCount(intern->enumdef));
196 }
197 
198 /*
199  * EnumDescriptor::getPublicDescriptor()
200  *
201  * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
202  * have two separate EnumDescriptor classes. We use a single class for both
203  * the public and private descriptor.
204  */
PHP_METHOD(EnumDescriptor,getPublicDescriptor)205 PHP_METHOD(EnumDescriptor, getPublicDescriptor) { RETURN_COPY(getThis()); }
206 
207 // clang-format off
208 static zend_function_entry EnumDescriptor_methods[] = {
209   PHP_ME(EnumDescriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
210   PHP_ME(EnumDescriptor, getValueCount, arginfo_void, ZEND_ACC_PUBLIC)
211   PHP_ME(EnumDescriptor, getValue, arginfo_getByIndex, ZEND_ACC_PUBLIC)
212   ZEND_FE_END
213 };
214 // clang-format on
215 
216 // -----------------------------------------------------------------------------
217 // Oneof
218 // -----------------------------------------------------------------------------
219 
220 typedef struct {
221   zend_object std;
222   const upb_OneofDef* oneofdef;
223 } OneofDescriptor;
224 
225 zend_class_entry* OneofDescriptor_class_entry;
226 static zend_object_handlers OneofDescriptor_object_handlers;
227 
OneofDescriptor_destructor(zend_object * obj)228 static void OneofDescriptor_destructor(zend_object* obj) {
229   OneofDescriptor* intern = (OneofDescriptor*)obj;
230   ObjCache_Delete(intern->oneofdef);
231 }
232 
OneofDescriptor_FromOneofDef(zval * val,const upb_OneofDef * o)233 static void OneofDescriptor_FromOneofDef(zval* val, const upb_OneofDef* o) {
234   if (o == NULL) {
235     ZVAL_NULL(val);
236     return;
237   }
238 
239   if (!ObjCache_Get(o, val)) {
240     OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor));
241     zend_object_std_init(&ret->std, OneofDescriptor_class_entry);
242     ret->std.handlers = &OneofDescriptor_object_handlers;
243     ret->oneofdef = o;
244     ObjCache_Add(o, &ret->std);
245     ZVAL_OBJ(val, &ret->std);
246   }
247 }
248 
249 /*
250  * OneofDescriptor::getName()
251  *
252  * Returns the name of this oneof.
253  */
PHP_METHOD(OneofDescriptor,getName)254 PHP_METHOD(OneofDescriptor, getName) {
255   OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis());
256   RETURN_STRING(upb_OneofDef_Name(intern->oneofdef));
257 }
258 
259 /*
260  * OneofDescriptor::getField()
261  *
262  * Returns a field from this oneof. The given index must be in the range
263  *   [0, getFieldCount() - 1].
264  */
PHP_METHOD(OneofDescriptor,getField)265 PHP_METHOD(OneofDescriptor, getField) {
266   OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis());
267   zend_long index;
268   zval ret;
269 
270   if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
271     zend_error(E_USER_ERROR, "Expect integer for index.\n");
272     return;
273   }
274 
275   if (index < 0 || index >= upb_OneofDef_FieldCount(intern->oneofdef)) {
276     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
277     return;
278   }
279 
280   const upb_FieldDef* field = upb_OneofDef_Field(intern->oneofdef, index);
281   FieldDescriptor_FromFieldDef(&ret, field);
282   RETURN_COPY_VALUE(&ret);
283 }
284 
285 /*
286  * OneofDescriptor::getFieldCount()
287  *
288  * Returns the number of fields in this oneof.
289  */
PHP_METHOD(OneofDescriptor,getFieldCount)290 PHP_METHOD(OneofDescriptor, getFieldCount) {
291   OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis());
292   RETURN_LONG(upb_OneofDef_FieldCount(intern->oneofdef));
293 }
294 
295 // clang-format off
296 static zend_function_entry OneofDescriptor_methods[] = {
297   PHP_ME(OneofDescriptor, getName,  arginfo_void, ZEND_ACC_PUBLIC)
298   PHP_ME(OneofDescriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
299   PHP_ME(OneofDescriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
300   ZEND_FE_END
301 };
302 // clang-format on
303 
304 // -----------------------------------------------------------------------------
305 // FieldDescriptor
306 // -----------------------------------------------------------------------------
307 
308 typedef struct {
309   zend_object std;
310   const upb_FieldDef* fielddef;
311 } FieldDescriptor;
312 
313 zend_class_entry* FieldDescriptor_class_entry;
314 static zend_object_handlers FieldDescriptor_object_handlers;
315 
FieldDescriptor_destructor(zend_object * obj)316 static void FieldDescriptor_destructor(zend_object* obj) {
317   FieldDescriptor* intern = (FieldDescriptor*)obj;
318   ObjCache_Delete(intern->fielddef);
319 }
320 
321 // Caller owns a ref on the returned zval.
FieldDescriptor_FromFieldDef(zval * val,const upb_FieldDef * f)322 static void FieldDescriptor_FromFieldDef(zval* val, const upb_FieldDef* f) {
323   if (f == NULL) {
324     ZVAL_NULL(val);
325     return;
326   }
327 
328   if (!ObjCache_Get(f, val)) {
329     FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor));
330     zend_object_std_init(&ret->std, FieldDescriptor_class_entry);
331     ret->std.handlers = &FieldDescriptor_object_handlers;
332     ret->fielddef = f;
333     ObjCache_Add(f, &ret->std);
334     ZVAL_OBJ(val, &ret->std);
335   }
336 }
337 
to_fieldtype(upb_FieldType type)338 upb_CType to_fieldtype(upb_FieldType type) {
339   switch (type) {
340 #define CASE(descriptor_type, type)      \
341   case kUpb_FieldType_##descriptor_type: \
342     return kUpb_CType_##type;
343 
344     CASE(Float, Float);
345     CASE(Double, Double);
346     CASE(Bool, Bool);
347     CASE(String, String);
348     CASE(Bytes, Bytes);
349     CASE(Message, Message);
350     CASE(Group, Message);
351     CASE(Enum, Enum);
352     CASE(Int32, Int32);
353     CASE(Int64, Int64);
354     CASE(UInt32, UInt32);
355     CASE(UInt64, UInt64);
356     CASE(SInt32, Int32);
357     CASE(SInt64, Int64);
358     CASE(Fixed32, UInt32);
359     CASE(Fixed64, UInt64);
360     CASE(SFixed32, Int32);
361     CASE(SFixed64, Int64);
362 
363 #undef CONVERT
364   }
365 
366   zend_error(E_ERROR, "Unknown field type.");
367   return 0;
368 }
369 
370 /*
371  * FieldDescriptor::getName()
372  *
373  * Returns the name of this field.
374  */
PHP_METHOD(FieldDescriptor,getName)375 PHP_METHOD(FieldDescriptor, getName) {
376   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
377   RETURN_STRING(upb_FieldDef_Name(intern->fielddef));
378 }
379 
380 /*
381  * FieldDescriptor::getNumber()
382  *
383  * Returns the number of this field.
384  */
PHP_METHOD(FieldDescriptor,getNumber)385 PHP_METHOD(FieldDescriptor, getNumber) {
386   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
387   RETURN_LONG(upb_FieldDef_Number(intern->fielddef));
388 }
389 
390 /*
391  * FieldDescriptor::getLabel()
392  *
393  * Returns the label of this field as an integer.
394  */
PHP_METHOD(FieldDescriptor,getLabel)395 PHP_METHOD(FieldDescriptor, getLabel) {
396   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
397   RETURN_LONG(upb_FieldDef_Label(intern->fielddef));
398 }
399 
400 /*
401  * FieldDescriptor::getType()
402  *
403  * Returns the type of this field as an integer.
404  */
PHP_METHOD(FieldDescriptor,getType)405 PHP_METHOD(FieldDescriptor, getType) {
406   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
407   RETURN_LONG(upb_FieldDef_Type(intern->fielddef));
408 }
409 
410 /*
411  * FieldDescriptor::isMap()
412  *
413  * Returns true if this field is a map.
414  */
PHP_METHOD(FieldDescriptor,isMap)415 PHP_METHOD(FieldDescriptor, isMap) {
416   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
417   RETURN_BOOL(upb_FieldDef_IsMap(intern->fielddef));
418 }
419 
420 /*
421  * FieldDescriptor::getEnumType()
422  *
423  * Returns the EnumDescriptor for this field, which must be an enum.
424  */
PHP_METHOD(FieldDescriptor,getEnumType)425 PHP_METHOD(FieldDescriptor, getEnumType) {
426   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
427   const upb_EnumDef* e = upb_FieldDef_EnumSubDef(intern->fielddef);
428   zval ret;
429 
430   if (!e) {
431     zend_throw_exception_ex(NULL, 0,
432                             "Cannot get enum type for non-enum field '%s'",
433                             upb_FieldDef_Name(intern->fielddef));
434     return;
435   }
436 
437   EnumDescriptor_FromEnumDef(&ret, e);
438   RETURN_COPY_VALUE(&ret);
439 }
440 
441 /*
442  * FieldDescriptor::getContainingOneof()
443  *
444  * Returns the OneofDescriptor for this field, or null if it is not inside
445  * a oneof.
446  */
PHP_METHOD(FieldDescriptor,getContainingOneof)447 PHP_METHOD(FieldDescriptor, getContainingOneof) {
448   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
449   const upb_OneofDef* o = upb_FieldDef_ContainingOneof(intern->fielddef);
450   zval ret;
451 
452   if (!o) {
453     RETURN_NULL();
454   }
455 
456   OneofDescriptor_FromOneofDef(&ret, o);
457   RETURN_COPY_VALUE(&ret);
458 }
459 
460 /*
461  * FieldDescriptor::getRealContainingOneof()
462  *
463  * Returns the non-synthetic OneofDescriptor for this field, or null if it is
464  * not inside a oneof.
465  */
PHP_METHOD(FieldDescriptor,getRealContainingOneof)466 PHP_METHOD(FieldDescriptor, getRealContainingOneof) {
467   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
468   const upb_OneofDef* o = upb_FieldDef_RealContainingOneof(intern->fielddef);
469   zval ret;
470 
471   if (!o) {
472     RETURN_NULL();
473   }
474 
475   OneofDescriptor_FromOneofDef(&ret, o);
476   RETURN_COPY_VALUE(&ret);
477 }
478 
479 /*
480  * FieldDescriptor::getMessageType()
481  *
482  * Returns the Descriptor for this field, which must be a message.
483  */
PHP_METHOD(FieldDescriptor,getMessageType)484 PHP_METHOD(FieldDescriptor, getMessageType) {
485   FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis());
486   Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef);
487 
488   if (!desc) {
489     zend_throw_exception_ex(
490         NULL, 0, "Cannot get message type for non-message field '%s'",
491         upb_FieldDef_Name(intern->fielddef));
492     return;
493   }
494 
495   RETURN_OBJ_COPY(&desc->std);
496 }
497 
498 // clang-format off
499 static zend_function_entry FieldDescriptor_methods[] = {
500   PHP_ME(FieldDescriptor, getName,   arginfo_void, ZEND_ACC_PUBLIC)
501   PHP_ME(FieldDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
502   PHP_ME(FieldDescriptor, getLabel,  arginfo_void, ZEND_ACC_PUBLIC)
503   PHP_ME(FieldDescriptor, getType,   arginfo_void, ZEND_ACC_PUBLIC)
504   PHP_ME(FieldDescriptor, isMap,     arginfo_void, ZEND_ACC_PUBLIC)
505   PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC)
506   PHP_ME(FieldDescriptor, getContainingOneof, arginfo_void, ZEND_ACC_PUBLIC)
507   PHP_ME(FieldDescriptor, getRealContainingOneof, arginfo_void, ZEND_ACC_PUBLIC)
508   PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC)
509   ZEND_FE_END
510 };
511 // clang-format on
512 
513 // -----------------------------------------------------------------------------
514 // Descriptor
515 // -----------------------------------------------------------------------------
516 
517 zend_class_entry* Descriptor_class_entry;
518 static zend_object_handlers Descriptor_object_handlers;
519 
Descriptor_destructor(zend_object * obj)520 static void Descriptor_destructor(zend_object* obj) {
521   // We don't really need to do anything here, we don't allow this to be
522   // collected before the end of the request.
523 }
524 
Descriptor_GetGeneratedClass(const upb_MessageDef * m)525 static zend_class_entry* Descriptor_GetGeneratedClass(const upb_MessageDef* m) {
526   for (int i = 0; i < 2; ++i) {
527     char* classname = GetPhpClassname(upb_MessageDef_File(m),
528                                       upb_MessageDef_FullName(m), (bool)i);
529     zend_string* str = zend_string_init(classname, strlen(classname), 0);
530     zend_class_entry* ce = zend_lookup_class(str);  // May autoload the class.
531 
532     zend_string_release(str);
533     free(classname);
534 
535     if (ce) {
536       return ce;
537     }
538   }
539 
540   char* classname = GetPhpClassname(upb_MessageDef_File(m),
541                                     upb_MessageDef_FullName(m), false);
542   zend_error(E_ERROR, "Couldn't load generated class %s", classname);
543   return NULL;
544 }
545 
Descriptor_FromMessageDef(zval * val,const upb_MessageDef * m)546 void Descriptor_FromMessageDef(zval* val, const upb_MessageDef* m) {
547   if (m == NULL) {
548     ZVAL_NULL(val);
549     return;
550   }
551 
552   if (!ObjCache_Get(m, val)) {
553     zend_class_entry* ce = NULL;
554     if (!upb_MessageDef_IsMapEntry(m)) {  // Map entries don't have a class.
555       ce = Descriptor_GetGeneratedClass(m);
556       if (!ce) {
557         ZVAL_NULL(val);
558         return;
559       }
560     }
561     Descriptor* ret = emalloc(sizeof(Descriptor));
562     zend_object_std_init(&ret->std, Descriptor_class_entry);
563     ret->std.handlers = &Descriptor_object_handlers;
564     ret->class_entry = ce;
565     ret->msgdef = m;
566     ObjCache_Add(m, &ret->std);
567     Descriptors_Add(&ret->std);
568     ZVAL_OBJ(val, &ret->std);
569   }
570 }
571 
Descriptor_FromClassEntry(zval * val,zend_class_entry * ce)572 static void Descriptor_FromClassEntry(zval* val, zend_class_entry* ce) {
573   if (ce) {
574     Descriptor_FromMessageDef(val, NameMap_GetMessage(ce));
575   } else {
576     ZVAL_NULL(val);
577   }
578 }
579 
Descriptor_GetFromZval(zval * val)580 static Descriptor* Descriptor_GetFromZval(zval* val) {
581   if (Z_TYPE_P(val) == IS_NULL) {
582     return NULL;
583   } else {
584     zend_object* ret = Z_OBJ_P(val);
585     zval_ptr_dtor(val);
586     return (Descriptor*)ret;
587   }
588 }
589 
590 // C Functions from def.h //////////////////////////////////////////////////////
591 
592 // These are documented in the header file.
593 
Descriptor_GetFromClassEntry(zend_class_entry * ce)594 Descriptor* Descriptor_GetFromClassEntry(zend_class_entry* ce) {
595   zval desc;
596   Descriptor_FromClassEntry(&desc, ce);
597   return Descriptor_GetFromZval(&desc);
598 }
599 
Descriptor_GetFromMessageDef(const upb_MessageDef * m)600 Descriptor* Descriptor_GetFromMessageDef(const upb_MessageDef* m) {
601   zval desc;
602   Descriptor_FromMessageDef(&desc, m);
603   return Descriptor_GetFromZval(&desc);
604 }
605 
Descriptor_GetFromFieldDef(const upb_FieldDef * f)606 Descriptor* Descriptor_GetFromFieldDef(const upb_FieldDef* f) {
607   return Descriptor_GetFromMessageDef(upb_FieldDef_MessageSubDef(f));
608 }
609 
610 /*
611  * Descriptor::getPublicDescriptor()
612  *
613  * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
614  * have two separate EnumDescriptor classes. We use a single class for both
615  * the public and private descriptor.
616  */
PHP_METHOD(Descriptor,getPublicDescriptor)617 PHP_METHOD(Descriptor, getPublicDescriptor) { RETURN_COPY(getThis()); }
618 
619 /*
620  * Descriptor::getFullName()
621  *
622  * Returns the full name for this message type.
623  */
PHP_METHOD(Descriptor,getFullName)624 PHP_METHOD(Descriptor, getFullName) {
625   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
626   RETURN_STRING(upb_MessageDef_FullName(intern->msgdef));
627 }
628 
629 /*
630  * Descriptor::getField()
631  *
632  * Returns a FieldDescriptor for the given index, which must be in the range
633  * [0, getFieldCount()-1].
634  */
PHP_METHOD(Descriptor,getField)635 PHP_METHOD(Descriptor, getField) {
636   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
637   int count = upb_MessageDef_FieldCount(intern->msgdef);
638   zval ret;
639   zend_long index;
640 
641   if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
642     zend_error(E_USER_ERROR, "Expect integer for index.\n");
643     return;
644   }
645 
646   if (index < 0 || index >= count) {
647     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
648     return;
649   }
650 
651   FieldDescriptor_FromFieldDef(&ret,
652                                upb_MessageDef_Field(intern->msgdef, index));
653   RETURN_COPY_VALUE(&ret);
654 }
655 
656 /*
657  * Descriptor::getFieldCount()
658  *
659  * Returns the number of fields in this message.
660  */
PHP_METHOD(Descriptor,getFieldCount)661 PHP_METHOD(Descriptor, getFieldCount) {
662   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
663   RETURN_LONG(upb_MessageDef_FieldCount(intern->msgdef));
664 }
665 
666 /*
667  * Descriptor::getOneofDecl()
668  *
669  * Returns a OneofDescriptor for the given index, which must be in the range
670  * [0, getOneofDeclCount()].
671  */
PHP_METHOD(Descriptor,getOneofDecl)672 PHP_METHOD(Descriptor, getOneofDecl) {
673   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
674   zend_long index;
675   zval ret;
676 
677   if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
678     zend_error(E_USER_ERROR, "Expect integer for index.\n");
679     return;
680   }
681 
682   if (index < 0 || index >= upb_MessageDef_OneofCount(intern->msgdef)) {
683     zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
684     return;
685   }
686 
687   OneofDescriptor_FromOneofDef(&ret,
688                                upb_MessageDef_Oneof(intern->msgdef, index));
689   RETURN_COPY_VALUE(&ret);
690 }
691 
692 /*
693  * Descriptor::getOneofDeclCount()
694  *
695  * Returns the number of oneofs in this message.
696  */
PHP_METHOD(Descriptor,getOneofDeclCount)697 PHP_METHOD(Descriptor, getOneofDeclCount) {
698   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
699   RETURN_LONG(upb_MessageDef_OneofCount(intern->msgdef));
700 }
701 
702 /*
703  * Descriptor::getClass()
704  *
705  * Returns the name of the PHP class for this message.
706  */
PHP_METHOD(Descriptor,getClass)707 PHP_METHOD(Descriptor, getClass) {
708   Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis());
709   const char* classname = ZSTR_VAL(intern->class_entry->name);
710   RETURN_STRING(classname);
711 }
712 
713 // clang-format off
714 static zend_function_entry Descriptor_methods[] = {
715   PHP_ME(Descriptor, getClass, arginfo_void, ZEND_ACC_PUBLIC)
716   PHP_ME(Descriptor, getFullName, arginfo_void, ZEND_ACC_PUBLIC)
717   PHP_ME(Descriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
718   PHP_ME(Descriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
719   PHP_ME(Descriptor, getOneofDecl, arginfo_getByIndex, ZEND_ACC_PUBLIC)
720   PHP_ME(Descriptor, getOneofDeclCount, arginfo_void, ZEND_ACC_PUBLIC)
721   PHP_ME(Descriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
722   ZEND_FE_END
723 };
724 // clang-format on
725 
726 // -----------------------------------------------------------------------------
727 // DescriptorPool
728 // -----------------------------------------------------------------------------
729 
730 typedef struct DescriptorPool {
731   zend_object std;
732   upb_DefPool* symtab;
733 } DescriptorPool;
734 
735 zend_class_entry* DescriptorPool_class_entry;
736 static zend_object_handlers DescriptorPool_object_handlers;
737 
GetPool(const zval * this_ptr)738 static DescriptorPool* GetPool(const zval* this_ptr) {
739   return (DescriptorPool*)Z_OBJ_P(this_ptr);
740 }
741 
742 /**
743  * Object handler to free an DescriptorPool.
744  */
DescriptorPool_destructor(zend_object * obj)745 static void DescriptorPool_destructor(zend_object* obj) {
746   DescriptorPool* intern = (DescriptorPool*)obj;
747 
748   // We can't free our underlying symtab here, because user code may create
749   // messages from destructors that will refer to it. The symtab will be freed
750   // by our RSHUTDOWN() handler in protobuf.c
751 
752   zend_object_std_dtor(&intern->std);
753 }
754 
DescriptorPool_CreateWithSymbolTable(zval * zv,upb_DefPool * symtab)755 void DescriptorPool_CreateWithSymbolTable(zval* zv, upb_DefPool* symtab) {
756   DescriptorPool* intern = emalloc(sizeof(DescriptorPool));
757   zend_object_std_init(&intern->std, DescriptorPool_class_entry);
758   intern->std.handlers = &DescriptorPool_object_handlers;
759   intern->symtab = symtab;
760 
761   ZVAL_OBJ(zv, &intern->std);
762 }
763 
DescriptorPool_GetSymbolTable()764 upb_DefPool* DescriptorPool_GetSymbolTable() { return get_global_symtab(); }
765 
766 /*
767  * DescriptorPool::getGeneratedPool()
768  *
769  * Returns the generated DescriptorPool.
770  */
PHP_METHOD(DescriptorPool,getGeneratedPool)771 PHP_METHOD(DescriptorPool, getGeneratedPool) {
772   DescriptorPool_CreateWithSymbolTable(return_value, get_global_symtab());
773 }
774 
775 /*
776  * DescriptorPool::getDescriptorByClassName()
777  *
778  * Returns a Descriptor object for the given PHP class name.
779  */
PHP_METHOD(DescriptorPool,getDescriptorByClassName)780 PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
781   char* classname = NULL;
782   zend_long classname_len;
783   zend_class_entry* ce;
784   zend_string* str;
785   zval ret;
786 
787   if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
788       FAILURE) {
789     return;
790   }
791 
792   str = zend_string_init(classname, strlen(classname), 0);
793   ce = zend_lookup_class(str);  // May autoload the class.
794   zend_string_release(str);
795 
796   if (!ce) {
797     RETURN_NULL();
798   }
799 
800   Descriptor_FromClassEntry(&ret, ce);
801   RETURN_COPY_VALUE(&ret);
802 }
803 
804 /*
805  * DescriptorPool::getEnumDescriptorByClassName()
806  *
807  * Returns a EnumDescriptor object for the given PHP class name.
808  */
PHP_METHOD(DescriptorPool,getEnumDescriptorByClassName)809 PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
810   char* classname = NULL;
811   zend_long classname_len;
812   zend_class_entry* ce;
813   zend_string* str;
814   zval ret;
815 
816   if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
817       FAILURE) {
818     return;
819   }
820 
821   str = zend_string_init(classname, strlen(classname), 0);
822   ce = zend_lookup_class(str);  // May autoload the class.
823   zend_string_release(str);
824 
825   if (!ce) {
826     RETURN_NULL();
827   }
828 
829   EnumDescriptor_FromClassEntry(&ret, ce);
830   RETURN_COPY_VALUE(&ret);
831 }
832 
833 /*
834  * DescriptorPool::getEnumDescriptorByProtoName()
835  *
836  * Returns a Descriptor object for the given protobuf message name.
837  */
PHP_METHOD(DescriptorPool,getDescriptorByProtoName)838 PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {
839   DescriptorPool* intern = GetPool(getThis());
840   char* protoname = NULL;
841   zend_long protoname_len;
842   const upb_MessageDef* m;
843 
844   if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) ==
845       FAILURE) {
846     return;
847   }
848 
849   if (*protoname == '.') protoname++;
850 
851   m = upb_DefPool_FindMessageByName(intern->symtab, protoname);
852 
853   if (m) {
854     RETURN_OBJ_COPY(&Descriptor_GetFromMessageDef(m)->std);
855   } else {
856     RETURN_NULL();
857   }
858 }
859 
860 /*
861  * depends_on_descriptor()
862  *
863  * Returns true if this FileDescriptorProto depends on descriptor.proto.
864  */
depends_on_descriptor(const google_protobuf_FileDescriptorProto * file)865 bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
866   const upb_StringView* deps;
867   upb_StringView name =
868       upb_StringView_FromString("google/protobuf/descriptor.proto");
869   size_t i, n;
870 
871   deps = google_protobuf_FileDescriptorProto_dependency(file, &n);
872   for (i = 0; i < n; i++) {
873     if (upb_StringView_IsEqual(deps[i], name)) {
874       return true;
875     }
876   }
877 
878   return false;
879 }
880 
add_message_name_mappings(const upb_MessageDef * message)881 static void add_message_name_mappings(const upb_MessageDef* message) {
882   NameMap_AddMessage(message);
883   int msg_n = upb_MessageDef_NestedMessageCount(message);
884   for (int i = 0; i < msg_n; i++) {
885     add_message_name_mappings(upb_MessageDef_NestedMessage(message, i));
886   }
887   int enum_n = upb_MessageDef_NestedEnumCount(message);
888   for (int i = 0; i < enum_n; i++) {
889     NameMap_AddEnum(upb_MessageDef_NestedEnum(message, i));
890   }
891 }
892 
893 /*
894  * add_name_mappings()
895  *
896  * Adds the messages and enums in this file to the NameMap.
897  */
add_name_mappings(const upb_FileDef * file)898 static void add_name_mappings(const upb_FileDef* file) {
899   for (int i = 0; i < upb_FileDef_TopLevelMessageCount(file); i++) {
900     add_message_name_mappings(upb_FileDef_TopLevelMessage(file, i));
901   }
902 
903   for (int i = 0; i < upb_FileDef_TopLevelEnumCount(file); i++) {
904     NameMap_AddEnum(upb_FileDef_TopLevelEnum(file, i));
905   }
906 }
907 
add_descriptor(upb_DefPool * symtab,const google_protobuf_FileDescriptorProto * file)908 static void add_descriptor(upb_DefPool* symtab,
909                            const google_protobuf_FileDescriptorProto* file) {
910   upb_StringView name = google_protobuf_FileDescriptorProto_name(file);
911   upb_Status status;
912   const upb_FileDef* file_def;
913   upb_Status_Clear(&status);
914 
915   if (upb_DefPool_FindFileByNameWithSize(symtab, name.data, name.size)) {
916     // Already added.
917     // TODO: Re-enable this warning when aggregate metadata is
918     // deprecated.
919     // zend_error(E_USER_WARNING,
920     //            "proto descriptor was previously loaded (included in multiple
921     //            " "metadata bundles?): " UPB_STRINGVIEW_FORMAT,
922     //            UPB_STRINGVIEW_ARGS(name));
923     return;
924   }
925 
926   // The PHP code generator currently special-cases descriptor.proto.  It
927   // doesn't add it as a dependency even if the proto file actually does
928   // depend on it.
929   if (depends_on_descriptor(file)) {
930     google_protobuf_FileDescriptorProto_getmsgdef(symtab);
931   }
932 
933   file_def = upb_DefPool_AddFile(symtab, file, &status);
934   CheckUpbStatus(&status, "Unable to load descriptor");
935   add_name_mappings(file_def);
936 }
937 
938 /*
939  * add_descriptor()
940  *
941  * Adds the given descriptor data to this DescriptorPool.
942  */
add_descriptor_set(upb_DefPool * symtab,const char * data,int data_len,upb_Arena * arena)943 static void add_descriptor_set(upb_DefPool* symtab, const char* data,
944                                int data_len, upb_Arena* arena) {
945   size_t i, n;
946   google_protobuf_FileDescriptorSet* set;
947   const google_protobuf_FileDescriptorProto* const* files;
948 
949   set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);
950 
951   if (!set) {
952     zend_error(E_ERROR, "Failed to parse binary descriptor\n");
953     return;
954   }
955 
956   files = google_protobuf_FileDescriptorSet_file(set, &n);
957 
958   for (i = 0; i < n; i++) {
959     const google_protobuf_FileDescriptorProto* file = files[i];
960     add_descriptor(symtab, file);
961   }
962 }
963 
DescriptorPool_HasFile(const char * filename)964 bool DescriptorPool_HasFile(const char* filename) {
965   return upb_DefPool_FindFileByName(get_global_symtab(), filename) != NULL;
966 }
967 
DescriptorPool_AddDescriptor(const char * filename,const char * data,int size)968 void DescriptorPool_AddDescriptor(const char* filename, const char* data,
969                                   int size) {
970   upb_Arena* arena = upb_Arena_New();
971   const google_protobuf_FileDescriptorProto* file =
972       google_protobuf_FileDescriptorProto_parse(data, size, arena);
973 
974   if (!file) {
975     zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename);
976     return;
977   }
978 
979   add_descriptor(get_global_symtab(), file);
980   upb_Arena_Free(arena);
981 }
982 
983 /*
984  * DescriptorPool::internalAddGeneratedFile()
985  *
986  * Adds the given descriptor data to this DescriptorPool.
987  */
PHP_METHOD(DescriptorPool,internalAddGeneratedFile)988 PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
989   DescriptorPool* intern = GetPool(getThis());
990   char* data = NULL;
991   zend_long data_len;
992   zend_bool use_nested_submsg = false;
993   upb_Arena* arena;
994 
995   if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
996                             &use_nested_submsg) != SUCCESS) {
997     return;
998   }
999 
1000   arena = upb_Arena_New();
1001   add_descriptor_set(intern->symtab, data, data_len, arena);
1002   upb_Arena_Free(arena);
1003 }
1004 
1005 // clang-format off
1006 ZEND_BEGIN_ARG_INFO_EX(arginfo_lookupByName, 0, 0, 1)
1007   ZEND_ARG_INFO(0, name)
1008 ZEND_END_ARG_INFO()
1009 
1010 ZEND_BEGIN_ARG_INFO_EX(arginfo_addgeneratedfile, 0, 0, 2)
1011   ZEND_ARG_INFO(0, data)
1012   ZEND_ARG_INFO(0, data_len)
1013 ZEND_END_ARG_INFO()
1014 
1015 static zend_function_entry DescriptorPool_methods[] = {
1016   PHP_ME(DescriptorPool, getGeneratedPool, arginfo_void,
1017          ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1018   PHP_ME(DescriptorPool, getDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1019   PHP_ME(DescriptorPool, getDescriptorByProtoName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1020   PHP_ME(DescriptorPool, getEnumDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1021   PHP_ME(DescriptorPool, internalAddGeneratedFile, arginfo_addgeneratedfile, ZEND_ACC_PUBLIC)
1022   ZEND_FE_END
1023 };
1024 // clang-format on
1025 
1026 // -----------------------------------------------------------------------------
1027 // InternalDescriptorPool
1028 // -----------------------------------------------------------------------------
1029 
1030 // For the C extension, Google\Protobuf\Internal\DescriptorPool is not a
1031 // separate instantiable object, it just returns a
1032 // Google\Protobuf\DescriptorPool.
1033 
1034 zend_class_entry* InternalDescriptorPool_class_entry;
1035 
1036 /*
1037  * InternalDescriptorPool::getGeneratedPool()
1038  *
1039  * Returns the generated DescriptorPool. Note that this is identical to
1040  * DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool
1041  * instance.
1042  */
PHP_METHOD(InternalDescriptorPool,getGeneratedPool)1043 PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
1044   DescriptorPool_CreateWithSymbolTable(return_value, get_global_symtab());
1045 }
1046 
1047 // clang-format off
1048 static zend_function_entry InternalDescriptorPool_methods[] = {
1049   PHP_ME(InternalDescriptorPool, getGeneratedPool, arginfo_void,
1050          ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1051   ZEND_FE_END
1052 };
1053 // clang-format on
1054 
1055 // -----------------------------------------------------------------------------
1056 // GPBType
1057 // -----------------------------------------------------------------------------
1058 
1059 zend_class_entry* gpb_type_type;
1060 
1061 static zend_function_entry gpb_type_methods[] = {ZEND_FE_END};
1062 
1063 // -----------------------------------------------------------------------------
1064 // Module Init
1065 // -----------------------------------------------------------------------------
1066 
Def_ModuleInit()1067 void Def_ModuleInit() {
1068   zend_class_entry tmp_ce;
1069   zend_object_handlers* h;
1070 
1071   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",
1072                    OneofDescriptor_methods);
1073   OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1074   OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1075   OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1076   h = &OneofDescriptor_object_handlers;
1077   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1078   h->dtor_obj = &OneofDescriptor_destructor;
1079 
1080   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",
1081                    EnumValueDescriptor_methods);
1082   EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1083   EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1084   EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1085   h = &EnumValueDescriptor_object_handlers;
1086   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1087 
1088   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",
1089                    EnumDescriptor_methods);
1090   EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1091   EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1092   EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1093   h = &EnumDescriptor_object_handlers;
1094   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1095   h->dtor_obj = &EnumDescriptor_destructor;
1096 
1097   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor", Descriptor_methods);
1098 
1099   Descriptor_class_entry = zend_register_internal_class(&tmp_ce);
1100   Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1101   Descriptor_class_entry->create_object = CreateHandler_ReturnNull;
1102   h = &Descriptor_object_handlers;
1103   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1104   h->dtor_obj = Descriptor_destructor;
1105 
1106   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",
1107                    FieldDescriptor_methods);
1108   FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1109   FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1110   FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1111   h = &FieldDescriptor_object_handlers;
1112   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1113   h->dtor_obj = &FieldDescriptor_destructor;
1114 
1115   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool",
1116                    DescriptorPool_methods);
1117   DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
1118   DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
1119   DescriptorPool_class_entry->create_object = CreateHandler_ReturnNull;
1120   h = &DescriptorPool_object_handlers;
1121   memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1122   h->dtor_obj = DescriptorPool_destructor;
1123 
1124   INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
1125                    InternalDescriptorPool_methods);
1126   InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
1127 
1128   // GPBType.
1129 #define STR(str) (str), strlen(str)
1130   zend_class_entry class_type;
1131   INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
1132                    gpb_type_methods);
1133   gpb_type_type = zend_register_internal_class(&class_type);
1134   zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);
1135   zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);
1136   zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);
1137   zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);
1138   zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);
1139   zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);
1140   zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);
1141   zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);
1142   zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);
1143   zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);
1144   zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);
1145   zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);
1146   zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);
1147   zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);
1148   zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);
1149   zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);
1150   zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);
1151   zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);
1152 #undef STR
1153 }
1154