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