Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: third_party/protobuf/php/src/Google/Protobuf/Internal/Message.php

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 /**
34 * Defines Message, the parent class extended by all protocol message classes.
35 */
36
37 namespace Google\Protobuf\Internal;
38
39 use Google\Protobuf\Internal\InputStream;
40 use Google\Protobuf\Internal\OutputStream;
41 use Google\Protobuf\Internal\DescriptorPool;
42 use Google\Protobuf\Internal\GPBLabel;
43 use Google\Protobuf\Internal\GPBType;
44 use Google\Protobuf\Internal\GPBWire;
45 use Google\Protobuf\Internal\MapEntry;
46 use Google\Protobuf\Internal\RepeatedField;
47
48 /**
49 * Parent class of all proto messages. Users should not instantiate this class
50 * or extend this class or its child classes by their own. See the comment of
51 * specific functions for more details.
52 */
53 class Message
54 {
55
56 /**
57 * @ignore
58 */
59 private $desc;
60
61 /**
62 * @ignore
63 */
64 public function __construct($desc = NULL)
65 {
66 // MapEntry message is shared by all types of map fields, whose
67 // descriptors are different from each other. Thus, we cannot find a
68 // specific descriptor from the descriptor pool.
69 if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') {
70 $this->desc = $desc;
71 return;
72 }
73 $pool = DescriptorPool::getGeneratedPool();
74 $this->desc = $pool->getDescriptorByClassName(get_class($this));
75 foreach ($this->desc->getField() as $field) {
76 $setter = $field->getSetter();
77 if ($field->isMap()) {
78 $message_type = $field->getMessageType();
79 $key_field = $message_type->getFieldByNumber(1);
80 $value_field = $message_type->getFieldByNumber(2);
81 switch ($value_field->getType()) {
82 case GPBType::MESSAGE:
83 case GPBType::GROUP:
84 $map_field = new MapField(
85 $key_field->getType(),
86 $value_field->getType(),
87 $value_field->getMessageType()->getClass());
88 $this->$setter($map_field);
89 break;
90 case GPBType::ENUM:
91 $map_field = new MapField(
92 $key_field->getType(),
93 $value_field->getType(),
94 $value_field->getEnumType()->getClass());
95 $this->$setter($map_field);
96 break;
97 default:
98 $map_field = new MapField(
99 $key_field->getType(),
100 $value_field->getType());
101 $this->$setter($map_field);
102 break;
103 }
104 } else if ($field->getLabel() === GPBLabel::REPEATED) {
105 switch ($field->getType()) {
106 case GPBType::MESSAGE:
107 case GPBType::GROUP:
108 $repeated_field = new RepeatedField(
109 $field->getType(),
110 $field->getMessageType()->getClass());
111 $this->$setter($repeated_field);
112 break;
113 case GPBType::ENUM:
114 $repeated_field = new RepeatedField(
115 $field->getType(),
116 $field->getEnumType()->getClass());
117 $this->$setter($repeated_field);
118 break;
119 default:
120 $repeated_field = new RepeatedField($field->getType());
121 $this->$setter($repeated_field);
122 break;
123 }
124 } else if ($field->getOneofIndex() !== -1) {
125 $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
126 $oneof_name = $oneof->getName();
127 $this->$oneof_name = new OneofField($oneof);
128 }
129 }
130 }
131
132 protected function readOneof($number)
133 {
134 $field = $this->desc->getFieldByNumber($number);
135 $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
136 $oneof_name = $oneof->getName();
137 $oneof_field = $this->$oneof_name;
138 if ($number === $oneof_field->getNumber()) {
139 return $oneof_field->getValue();
140 } else {
141 return $this->defaultValue($field);
142 }
143 }
144
145 protected function writeOneof($number, $value)
146 {
147 $field = $this->desc->getFieldByNumber($number);
148 $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
149 $oneof_name = $oneof->getName();
150 $oneof_field = $this->$oneof_name;
151 $oneof_field->setValue($value);
152 $oneof_field->setFieldName($field->getName());
153 $oneof_field->setNumber($number);
154 }
155
156 /**
157 * @ignore
158 */
159 private function defaultValue($field)
160 {
161 $value = null;
162
163 switch ($field->getType()) {
164 case GPBType::DOUBLE:
165 case GPBType::FLOAT:
166 return 0.0;
167 case GPBType::UINT32:
168 case GPBType::UINT64:
169 case GPBType::INT32:
170 case GPBType::INT64:
171 case GPBType::FIXED32:
172 case GPBType::FIXED64:
173 case GPBType::SFIXED32:
174 case GPBType::SFIXED64:
175 case GPBType::SINT32:
176 case GPBType::SINT64:
177 case GPBType::ENUM:
178 return 0;
179 case GPBType::BOOL:
180 return false;
181 case GPBType::STRING:
182 case GPBType::BYTES:
183 return "";
184 case GPBType::GROUP:
185 case GPBType::MESSAGE:
186 return null;
187 default:
188 user_error("Unsupported type.");
189 return false;
190 }
191 }
192
193 /**
194 * @ignore
195 */
196 private static function parseFieldFromStreamNoTag($input, $field, &$value)
197 {
198 switch ($field->getType()) {
199 case GPBType::DOUBLE:
200 if (!GPBWire::readDouble($input, $value)) {
201 return false;
202 }
203 break;
204 case GPBType::FLOAT:
205 if (!GPBWire::readFloat($input, $value)) {
206 return false;
207 }
208 break;
209 case GPBType::INT64:
210 if (!GPBWire::readInt64($input, $value)) {
211 return false;
212 }
213 break;
214 case GPBType::UINT64:
215 if (!GPBWire::readUint64($input, $value)) {
216 return false;
217 }
218 break;
219 case GPBType::INT32:
220 if (!GPBWire::readInt32($input, $value)) {
221 return false;
222 }
223 break;
224 case GPBType::FIXED64:
225 if (!GPBWire::readFixed64($input, $value)) {
226 return false;
227 }
228 break;
229 case GPBType::FIXED32:
230 if (!GPBWire::readFixed32($input, $value)) {
231 return false;
232 }
233 break;
234 case GPBType::BOOL:
235 if (!GPBWire::readBool($input, $value)) {
236 return false;
237 }
238 break;
239 case GPBType::STRING:
240 // TODO(teboring): Add utf-8 check.
241 if (!GPBWire::readString($input, $value)) {
242 return false;
243 }
244 break;
245 case GPBType::GROUP:
246 echo "GROUP\xA";
247 trigger_error("Not implemented.", E_ERROR);
248 break;
249 case GPBType::MESSAGE:
250 if ($field->isMap()) {
251 $value = new MapEntry($field->getMessageType());
252 } else {
253 $klass = $field->getMessageType()->getClass();
254 $value = new $klass;
255 }
256 if (!GPBWire::readMessage($input, $value)) {
257 return false;
258 }
259 break;
260 case GPBType::BYTES:
261 if (!GPBWire::readString($input, $value)) {
262 return false;
263 }
264 break;
265 case GPBType::UINT32:
266 if (!GPBWire::readUint32($input, $value)) {
267 return false;
268 }
269 break;
270 case GPBType::ENUM:
271 // TODO(teboring): Check unknown enum value.
272 if (!GPBWire::readInt32($input, $value)) {
273 return false;
274 }
275 break;
276 case GPBType::SFIXED32:
277 if (!GPBWire::readSfixed32($input, $value)) {
278 return false;
279 }
280 break;
281 case GPBType::SFIXED64:
282 if (!GPBWire::readSfixed64($input, $value)) {
283 return false;
284 }
285 break;
286 case GPBType::SINT32:
287 if (!GPBWire::readSint32($input, $value)) {
288 return false;
289 }
290 break;
291 case GPBType::SINT64:
292 if (!GPBWire::readSint64($input, $value)) {
293 return false;
294 }
295 break;
296 default:
297 user_error("Unsupported type.");
298 return false;
299 }
300 return true;
301 }
302
303 /**
304 * @ignore
305 */
306 private function parseFieldFromStream($tag, $input, $field)
307 {
308 $value = null;
309 $field_type = $field->getType();
310
311 $value_format = GPBWire::UNKNOWN;
312 if (GPBWire::getTagWireType($tag) ===
313 GPBWire::getWireType($field_type)) {
314 $value_format = GPBWire::NORMAL_FORMAT;
315 } elseif ($field->isPackable() &&
316 GPBWire::getTagWireType($tag) ===
317 GPBWire::WIRETYPE_LENGTH_DELIMITED) {
318 $value_format = GPBWire::PACKED_FORMAT;
319 }
320
321 if ($value_format === GPBWire::NORMAL_FORMAT) {
322 if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
323 return false;
324 }
325 } elseif ($value_format === GPBWire::PACKED_FORMAT) {
326 $length = 0;
327 if (!GPBWire::readInt32($input, $length)) {
328 return false;
329 }
330 $limit = $input->pushLimit($length);
331 $getter = $field->getGetter();
332 while ($input->bytesUntilLimit() > 0) {
333 if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
334 return false;
335 }
336 $this->$getter()[] = $value;
337 }
338 $input->popLimit($limit);
339 return true;
340 } else {
341 return false;
342 }
343
344 if ($field->isMap()) {
345 $getter = $field->getGetter();
346 $this->$getter()[$value->getKey()] = $value->getValue();
347 } else if ($field->isRepeated()) {
348 $getter = $field->getGetter();
349 $this->$getter()[] = $value;
350 } else {
351 $setter = $field->getSetter();
352 $this->$setter($value);
353 }
354
355 return true;
356 }
357
358 /**
359 * Parses a protocol buffer contained in a string.
360 *
361 * This function takes a string in the (non-human-readable) binary wire
362 * format, matching the encoding output by encode().
363 *
364 * @param string $data Binary protobuf data.
365 * @return bool Return true on success.
366 */
367 public function decode($data)
368 {
369 $input = new InputStream($data);
370 $this->parseFromStream($input);
371 }
372
373 /**
374 * @ignore
375 */
376 public function parseFromStream($input)
377 {
378 while (true) {
379 $tag = $input->readTag();
380 // End of input. This is a valid place to end, so return true.
381 if ($tag === 0) {
382 return true;
383 }
384
385 $number = GPBWire::getTagFieldNumber($tag);
386 $field = $this->desc->getFieldByNumber($number);
387
388 if (!$this->parseFieldFromStream($tag, $input, $field)) {
389 return false;
390 }
391 }
392 }
393
394 /**
395 * @ignore
396 */
397 private function serializeSingularFieldToStream($field, &$output)
398 {
399 if (!$this->existField($field)) {
400 return true;
401 }
402 $getter = $field->getGetter();
403 $value = $this->$getter();
404 if (!GPBWire::serializeFieldToStream($value, $field, true, $output)) {
405 return false;
406 }
407 return true;
408 }
409
410 /**
411 * @ignore
412 */
413 private function serializeRepeatedFieldToStream($field, &$output)
414 {
415 $getter = $field->getGetter();
416 $values = $this->$getter();
417 $count = count($values);
418 if ($count === 0) {
419 return true;
420 }
421
422 $packed = $field->getPacked();
423 if ($packed) {
424 if (!GPBWire::writeTag(
425 $output,
426 GPBWire::makeTag($field->getNumber(), GPBType::STRING))) {
427 return false;
428 }
429 $size = 0;
430 foreach ($values as $value) {
431 $size += $this->fieldDataOnlyByteSize($field, $value);
432 }
433 if (!$output->writeVarint32($size)) {
434 return false;
435 }
436 }
437
438 foreach ($values as $value) {
439 if (!GPBWire::serializeFieldToStream(
440 $value,
441 $field,
442 !$packed,
443 $output)) {
444 return false;
445 }
446 }
447 return true;
448 }
449
450 /**
451 * @ignore
452 */
453 private function serializeMapFieldToStream($field, $output)
454 {
455 $getter = $field->getGetter();
456 $values = $this->$getter();
457 $count = count($values);
458 if ($count === 0) {
459 return true;
460 }
461
462 foreach ($values as $key => $value) {
463 $map_entry = new MapEntry($field->getMessageType());
464 $map_entry->setKey($key);
465 $map_entry->setValue($value);
466 if (!GPBWire::serializeFieldToStream(
467 $map_entry,
468 $field,
469 true,
470 $output)) {
471 return false;
472 }
473 }
474 return true;
475 }
476
477 /**
478 * @ignore
479 */
480 private function serializeFieldToStream(&$output, $field)
481 {
482 if ($field->isMap()) {
483 return $this->serializeMapFieldToStream($field, $output);
484 } elseif ($field->isRepeated()) {
485 return $this->serializeRepeatedFieldToStream($field, $output);
486 } else {
487 return $this->serializeSingularFieldToStream($field, $output);
488 }
489 }
490
491 /**
492 * @ignore
493 */
494 public function serializeToStream(&$output)
495 {
496 $fields = $this->desc->getField();
497 foreach ($fields as $field) {
498 if (!$this->serializeFieldToStream($output, $field)) {
499 return false;
500 }
501 }
502 return true;
503 }
504
505 /**
506 * Serialize the message to string.
507 * @return string Serialized binary protobuf data.
508 */
509 public function encode()
510 {
511 $output = new OutputStream($this->byteSize());
512 $this->serializeToStream($output);
513 return $output->getData();
514 }
515
516 /**
517 * @ignore
518 */
519 private function existField($field)
520 {
521 $getter = $field->getGetter();
522 $value = $this->$getter();
523 return $value !== $this->defaultValue($field);
524 }
525
526 /**
527 * @ignore
528 */
529 private function repeatedFieldDataOnlyByteSize($field)
530 {
531 $size = 0;
532
533 $getter = $field->getGetter();
534 $values = $this->$getter();
535 $count = count($values);
536 if ($count !== 0) {
537 $size += $count * GPBWire::tagSize($field);
538 foreach ($values as $value) {
539 $size += $this->singularFieldDataOnlyByteSize($field);
540 }
541 }
542 }
543
544 /**
545 * @ignore
546 */
547 private function fieldDataOnlyByteSize($field, $value)
548 {
549 $size = 0;
550
551 switch ($field->getType()) {
552 case GPBType::BOOL:
553 $size += 1;
554 break;
555 case GPBType::FLOAT:
556 case GPBType::FIXED32:
557 case GPBType::SFIXED32:
558 $size += 4;
559 break;
560 case GPBType::DOUBLE:
561 case GPBType::FIXED64:
562 case GPBType::SFIXED64:
563 $size += 8;
564 break;
565 case GPBType::UINT32:
566 case GPBType::INT32:
567 case GPBType::ENUM:
568 $size += GPBWire::varint32Size($value);
569 break;
570 case GPBType::UINT64:
571 case GPBType::INT64:
572 $size += GPBWire::varint64Size($value);
573 break;
574 case GPBType::SINT32:
575 $size += GPBWire::sint32Size($value);
576 break;
577 case GPBType::SINT64:
578 $size += GPBWire::sint64Size($value);
579 break;
580 case GPBType::STRING:
581 case GPBType::BYTES:
582 $size += strlen($value);
583 $size += GPBWire::varint32Size($size);
584 break;
585 case GPBType::MESSAGE:
586 $size += $value->byteSize();
587 $size += GPBWire::varint32Size($size);
588 break;
589 case GPBType::GROUP:
590 // TODO(teboring): Add support.
591 user_error("Unsupported type.");
592 break;
593 default:
594 user_error("Unsupported type.");
595 return 0;
596 }
597
598 return $size;
599 }
600
601 /**
602 * @ignore
603 */
604 private function fieldByteSize($field)
605 {
606 $size = 0;
607 if ($field->isMap()) {
608 $getter = $field->getGetter();
609 $values = $this->$getter();
610 $count = count($values);
611 if ($count !== 0) {
612 $size += $count * GPBWire::tagSize($field);
613 $message_type = $field->getMessageType();
614 $key_field = $message_type->getFieldByNumber(1);
615 $value_field = $message_type->getFieldByNumber(2);
616 foreach ($values as $key => $value) {
617 $data_size = 0;
618 $data_size += $this->fieldDataOnlyByteSize($key_field, $key) ;
619 $data_size += $this->fieldDataOnlyByteSize(
620 $value_field,
621 $value);
622 $data_size += GPBWire::tagSize($key_field);
623 $data_size += GPBWire::tagSize($value_field);
624 $size += GPBWire::varint32Size($data_size) + $data_size;
625 }
626 }
627 } elseif ($field->isRepeated()) {
628 $getter = $field->getGetter();
629 $values = $this->$getter();
630 $count = count($values);
631 if ($count !== 0) {
632 if ($field->getPacked()) {
633 $data_size = 0;
634 foreach ($values as $value) {
635 $data_size += $this->fieldDataOnlyByteSize($field, $valu e);
636 }
637 $size += GPBWire::tagSize($field);
638 $size += GPBWire::varint32Size($data_size);
639 $size += $data_size;
640 } else {
641 $size += $count * GPBWire::tagSize($field);
642 foreach ($values as $value) {
643 $size += $this->fieldDataOnlyByteSize($field, $value);
644 }
645 }
646 }
647 } elseif ($this->existField($field)) {
648 $size += GPBWire::tagSize($field);
649 $getter = $field->getGetter();
650 $value = $this->$getter();
651 $size += $this->fieldDataOnlyByteSize($field, $value);
652 }
653 return $size;
654 }
655
656 /**
657 * @ignore
658 */
659 public function byteSize()
660 {
661 $size = 0;
662
663 $fields = $this->desc->getField();
664 foreach ($fields as $field) {
665 $size += $this->fieldByteSize($field);
666 }
667 return $size;
668 }
669 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698