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