OLD | NEW |
| (Empty) |
1 <?php | |
2 | |
3 // Protocol Buffers - Google's data interchange format | |
4 // Copyright 2008 Google Inc. All rights reserved. | |
5 // https://developers.google.com/protocol-buffers/ | |
6 // | |
7 // Redistribution and use in source and binary forms, with or without | |
8 // modification, are permitted provided that the following conditions are | |
9 // met: | |
10 // | |
11 // * Redistributions of source code must retain the above copyright | |
12 // notice, this list of conditions and the following disclaimer. | |
13 // * Redistributions in binary form must reproduce the above | |
14 // copyright notice, this list of conditions and the following disclaimer | |
15 // in the documentation and/or other materials provided with the | |
16 // distribution. | |
17 // * Neither the name of Google Inc. nor the names of its | |
18 // contributors may be used to endorse or promote products derived from | |
19 // this software without specific prior written permission. | |
20 // | |
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | |
33 namespace Google\Protobuf\Internal; | |
34 | |
35 use Google\Protobuf\Internal\GPBType; | |
36 use Google\Protobuf\Internal\MessageOptions; | |
37 | |
38 class FileDescriptor | |
39 { | |
40 | |
41 private $package; | |
42 private $message_type = []; | |
43 private $enum_type = []; | |
44 | |
45 public function setPackage($package) | |
46 { | |
47 $this->package = $package; | |
48 } | |
49 | |
50 public function getPackage() | |
51 { | |
52 return $this->package; | |
53 } | |
54 | |
55 public function getMessageType() | |
56 { | |
57 return $this->message_type; | |
58 } | |
59 | |
60 public function addMessageType($desc) | |
61 { | |
62 $this->message_type[] = $desc; | |
63 } | |
64 | |
65 public function getEnumType() | |
66 { | |
67 return $this->enum_type; | |
68 } | |
69 | |
70 public function addEnumType($desc) | |
71 { | |
72 $this->enum_type[]= $desc; | |
73 } | |
74 | |
75 public static function buildFromProto($proto) | |
76 { | |
77 $file = new FileDescriptor(); | |
78 $file->setPackage($proto->getPackage()); | |
79 foreach ($proto->getMessageType() as $message_proto) { | |
80 $file->addMessageType(Descriptor::buildFromProto( | |
81 $message_proto, $file->getPackage(), "")); | |
82 } | |
83 foreach ($proto->getEnumType() as $enum_proto) { | |
84 $file->getEnumType()[] = | |
85 $file->addEnumType( | |
86 EnumDescriptor::buildFromProto( | |
87 $enum_proto, | |
88 $file->getPackage(), | |
89 "")); | |
90 } | |
91 return $file; | |
92 } | |
93 } | |
94 | |
95 class Descriptor | |
96 { | |
97 | |
98 private $full_name; | |
99 private $field = []; | |
100 private $nested_type = []; | |
101 private $enum_type = []; | |
102 private $klass; | |
103 private $options; | |
104 private $oneof_decl = []; | |
105 | |
106 public function addOneofDecl($oneof) | |
107 { | |
108 $this->oneof_decl[] = $oneof; | |
109 } | |
110 | |
111 public function getOneofDecl() | |
112 { | |
113 return $this->oneof_decl; | |
114 } | |
115 | |
116 public function setFullName($full_name) | |
117 { | |
118 $this->full_name = $full_name; | |
119 } | |
120 | |
121 public function getFullName() | |
122 { | |
123 return $this->full_name; | |
124 } | |
125 | |
126 public function addField($field) | |
127 { | |
128 $this->field[$field->getNumber()] = $field; | |
129 } | |
130 | |
131 public function getField() | |
132 { | |
133 return $this->field; | |
134 } | |
135 | |
136 public function addNestedType($desc) | |
137 { | |
138 $this->nested_type[] = $desc; | |
139 } | |
140 | |
141 public function getNestedType() | |
142 { | |
143 return $this->nested_type; | |
144 } | |
145 | |
146 public function addEnumType($desc) | |
147 { | |
148 $this->enum_type[] = $desc; | |
149 } | |
150 | |
151 public function getEnumType() | |
152 { | |
153 return $this->enum_type; | |
154 } | |
155 | |
156 public function getFieldByNumber($number) | |
157 { | |
158 return $this->field[$number]; | |
159 } | |
160 | |
161 public function setClass($klass) | |
162 { | |
163 $this->klass = $klass; | |
164 } | |
165 | |
166 public function getClass() | |
167 { | |
168 return $this->klass; | |
169 } | |
170 | |
171 public function setOptions($options) | |
172 { | |
173 $this->options = $options; | |
174 } | |
175 | |
176 public function getOptions() | |
177 { | |
178 return $this->options; | |
179 } | |
180 | |
181 public static function buildFromProto($proto, $package, $containing) | |
182 { | |
183 $desc = new Descriptor(); | |
184 | |
185 $message_name_without_package = ""; | |
186 $classname = ""; | |
187 $fullname = ""; | |
188 getFullClassName( | |
189 $proto, | |
190 $containing, | |
191 $package, | |
192 $message_name_without_package, | |
193 $classname, | |
194 $fullname); | |
195 $desc->setFullName($fullname); | |
196 $desc->setClass($classname); | |
197 $desc->setOptions($proto->getOptions()); | |
198 | |
199 foreach ($proto->getField() as $field_proto) { | |
200 $desc->addField(FieldDescriptor::buildFromProto($field_proto)); | |
201 } | |
202 | |
203 // Handle nested types. | |
204 foreach ($proto->getNestedType() as $nested_proto) { | |
205 $desc->addNestedType(Descriptor::buildFromProto( | |
206 $nested_proto, $package, $message_name_without_package)); | |
207 } | |
208 | |
209 // Handle oneof fields. | |
210 foreach ($proto->getOneofDecl() as $oneof_proto) { | |
211 $desc->addOneofDecl( | |
212 OneofDescriptor::buildFromProto($oneof_proto, $desc)); | |
213 } | |
214 | |
215 return $desc; | |
216 } | |
217 } | |
218 | |
219 function addPrefixIfSpecial( | |
220 $name, | |
221 $package) | |
222 { | |
223 if ($name === "Empty" && $package === "google.protobuf") { | |
224 return "GPBEmpty"; | |
225 } else { | |
226 return $name; | |
227 } | |
228 } | |
229 | |
230 function getFullClassName( | |
231 $proto, | |
232 $containing, | |
233 $package, | |
234 &$message_name_without_package, | |
235 &$classname, | |
236 &$fullname) | |
237 { | |
238 // Full name needs to start with '.'. | |
239 $message_name_without_package = | |
240 addPrefixIfSpecial($proto->getName(), $package); | |
241 if ($containing !== "") { | |
242 $message_name_without_package = | |
243 $containing . "." . $message_name_without_package; | |
244 } | |
245 if ($package === "") { | |
246 $fullname = "." . $message_name_without_package; | |
247 } else { | |
248 $fullname = "." . $package . "." . $message_name_without_package; | |
249 } | |
250 | |
251 // Nested message class names are seperated by '_', and package names are | |
252 // seperated by '\'. | |
253 $class_name_without_package = | |
254 implode('_', array_map('ucwords', | |
255 explode('.', $message_name_without_package))); | |
256 if ($package === "") { | |
257 $classname = $class_name_without_package; | |
258 } else { | |
259 $classname = | |
260 implode('\\', array_map('ucwords', explode('.', $package))). | |
261 "\\".$class_name_without_package; | |
262 } | |
263 } | |
264 | |
265 class OneofDescriptor | |
266 { | |
267 | |
268 private $name; | |
269 private $fields; | |
270 | |
271 public function setName($name) | |
272 { | |
273 $this->name = $name; | |
274 } | |
275 | |
276 public function getName() | |
277 { | |
278 return $this->name; | |
279 } | |
280 | |
281 public function addField(&$field) | |
282 { | |
283 $this->fields[] = $field; | |
284 } | |
285 | |
286 public function getFields() | |
287 { | |
288 return $this->fields; | |
289 } | |
290 | |
291 public static function buildFromProto($oneof_proto) | |
292 { | |
293 $oneof = new OneofDescriptor(); | |
294 $oneof->setName($oneof_proto->getName()); | |
295 return $oneof; | |
296 } | |
297 } | |
298 | |
299 | |
300 class EnumDescriptor | |
301 { | |
302 | |
303 private $klass; | |
304 private $full_name; | |
305 private $value; | |
306 | |
307 public function setFullName($full_name) | |
308 { | |
309 $this->full_name = $full_name; | |
310 } | |
311 | |
312 public function getFullName() | |
313 { | |
314 return $this->full_name; | |
315 } | |
316 | |
317 public function addValue($number, $value) | |
318 { | |
319 $this->value[$number] = $value; | |
320 } | |
321 | |
322 public function setClass($klass) | |
323 { | |
324 $this->klass = $klass; | |
325 } | |
326 | |
327 public function getClass() | |
328 { | |
329 return $this->klass; | |
330 } | |
331 | |
332 public static function buildFromProto($proto, $package, $containing) | |
333 { | |
334 $desc = new EnumDescriptor(); | |
335 | |
336 $enum_name_without_package = ""; | |
337 $classname = ""; | |
338 $fullname = ""; | |
339 getFullClassName( | |
340 $proto, | |
341 $containing, | |
342 $package, | |
343 $enum_name_without_package, | |
344 $classname, | |
345 $fullname); | |
346 $desc->setFullName($fullname); | |
347 $desc->setClass($classname); | |
348 | |
349 return $desc; | |
350 } | |
351 } | |
352 | |
353 class EnumValueDescriptor | |
354 { | |
355 } | |
356 | |
357 class FieldDescriptor | |
358 { | |
359 | |
360 private $name; | |
361 private $setter; | |
362 private $getter; | |
363 private $number; | |
364 private $label; | |
365 private $type; | |
366 private $message_type; | |
367 private $enum_type; | |
368 private $packed; | |
369 private $is_map; | |
370 private $oneof_index = -1; | |
371 | |
372 public function setOneofIndex($index) | |
373 { | |
374 $this->oneof_index = $index; | |
375 } | |
376 | |
377 public function getOneofIndex() | |
378 { | |
379 return $this->oneof_index; | |
380 } | |
381 | |
382 public function setName($name) | |
383 { | |
384 $this->name = $name; | |
385 } | |
386 | |
387 public function getName() | |
388 { | |
389 return $this->name; | |
390 } | |
391 | |
392 public function setSetter($setter) | |
393 { | |
394 $this->setter = $setter; | |
395 } | |
396 | |
397 public function getSetter() | |
398 { | |
399 return $this->setter; | |
400 } | |
401 | |
402 public function setGetter($getter) | |
403 { | |
404 $this->getter = $getter; | |
405 } | |
406 | |
407 public function getGetter() | |
408 { | |
409 return $this->getter; | |
410 } | |
411 | |
412 public function setNumber($number) | |
413 { | |
414 $this->number = $number; | |
415 } | |
416 | |
417 public function getNumber() | |
418 { | |
419 return $this->number; | |
420 } | |
421 | |
422 public function setLabel($label) | |
423 { | |
424 $this->label = $label; | |
425 } | |
426 | |
427 public function getLabel() | |
428 { | |
429 return $this->label; | |
430 } | |
431 | |
432 public function isRepeated() | |
433 { | |
434 return $this->label === GPBLabel::REPEATED; | |
435 } | |
436 | |
437 public function setType($type) | |
438 { | |
439 $this->type = $type; | |
440 } | |
441 | |
442 public function getType() | |
443 { | |
444 return $this->type; | |
445 } | |
446 | |
447 public function setMessageType($message_type) | |
448 { | |
449 $this->message_type = $message_type; | |
450 } | |
451 | |
452 public function getMessageType() | |
453 { | |
454 return $this->message_type; | |
455 } | |
456 | |
457 public function setEnumType($enum_type) | |
458 { | |
459 $this->enum_type = $enum_type; | |
460 } | |
461 | |
462 public function getEnumType() | |
463 { | |
464 return $this->enum_type; | |
465 } | |
466 | |
467 public function setPacked($packed) | |
468 { | |
469 $this->packed = $packed; | |
470 } | |
471 | |
472 public function getPacked() | |
473 { | |
474 return $this->packed; | |
475 } | |
476 | |
477 public function isPackable() | |
478 { | |
479 return $this->isRepeated() && self::isTypePackable($this->type); | |
480 } | |
481 | |
482 public function isMap() | |
483 { | |
484 return $this->getType() == GPBType::MESSAGE && | |
485 !is_null($this->getMessageType()->getOptions()) && | |
486 $this->getMessageType()->getOptions()->getMapEntry(); | |
487 } | |
488 | |
489 private static function isTypePackable($field_type) | |
490 { | |
491 return ($field_type !== GPBType::STRING && | |
492 $field_type !== GPBType::GROUP && | |
493 $field_type !== GPBType::MESSAGE && | |
494 $field_type !== GPBType::BYTES); | |
495 } | |
496 | |
497 public static function getFieldDescriptor( | |
498 $name, | |
499 $label, | |
500 $type, | |
501 $number, | |
502 $oneof_index, | |
503 $packed, | |
504 $type_name = null) | |
505 { | |
506 $field = new FieldDescriptor(); | |
507 $field->setName($name); | |
508 $camel_name = implode('', array_map('ucwords', explode('_', $name))); | |
509 $field->setGetter('get' . $camel_name); | |
510 $field->setSetter('set' . $camel_name); | |
511 $field->setType($type); | |
512 $field->setNumber($number); | |
513 $field->setLabel($label); | |
514 $field->setPacked($packed); | |
515 $field->setOneofIndex($oneof_index); | |
516 | |
517 // At this time, the message/enum type may have not been added to pool. | |
518 // So we use the type name as place holder and will replace it with the | |
519 // actual descriptor in cross building. | |
520 switch ($type) { | |
521 case GPBType::MESSAGE: | |
522 $field->setMessageType($type_name); | |
523 break; | |
524 case GPBType::ENUM: | |
525 $field->setEnumType($type_name); | |
526 break; | |
527 default: | |
528 break; | |
529 } | |
530 | |
531 return $field; | |
532 } | |
533 | |
534 public static function buildFromProto($proto) | |
535 { | |
536 $type_name = null; | |
537 switch ($proto->getType()) { | |
538 case GPBType::MESSAGE: | |
539 case GPBType::GROUP: | |
540 case GPBType::ENUM: | |
541 $type_name = $proto->getTypeName(); | |
542 break; | |
543 default: | |
544 break; | |
545 } | |
546 | |
547 $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1; | |
548 $packed = false; | |
549 $options = $proto->getOptions(); | |
550 if ($options !== null) { | |
551 $packed = $options->getPacked(); | |
552 } | |
553 | |
554 return FieldDescriptor::getFieldDescriptor( | |
555 $proto->getName(), $proto->getLabel(), $proto->getType(), | |
556 $proto->getNumber(), $oneof_index, $packed, $type_name); | |
557 } | |
558 } | |
OLD | NEW |