| 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 /** |
| 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 } |
| OLD | NEW |