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 33namespace Google\Protobuf\Internal; 34 35class FieldDescriptor 36{ 37 use HasPublicDescriptorTrait; 38 39 private $name; 40 private $json_name; 41 private $setter; 42 private $getter; 43 private $number; 44 private $label; 45 private $type; 46 private $message_type; 47 private $enum_type; 48 private $packed; 49 private $is_map; 50 private $oneof_index = -1; 51 52 public function __construct() 53 { 54 $this->public_desc = new \Google\Protobuf\FieldDescriptor($this); 55 } 56 57 public function setOneofIndex($index) 58 { 59 $this->oneof_index = $index; 60 } 61 62 public function getOneofIndex() 63 { 64 return $this->oneof_index; 65 } 66 67 public function setName($name) 68 { 69 $this->name = $name; 70 } 71 72 public function getName() 73 { 74 return $this->name; 75 } 76 77 public function setJsonName($json_name) 78 { 79 $this->json_name = $json_name; 80 } 81 82 public function getJsonName() 83 { 84 return $this->json_name; 85 } 86 87 public function setSetter($setter) 88 { 89 $this->setter = $setter; 90 } 91 92 public function getSetter() 93 { 94 return $this->setter; 95 } 96 97 public function setGetter($getter) 98 { 99 $this->getter = $getter; 100 } 101 102 public function getGetter() 103 { 104 return $this->getter; 105 } 106 107 public function setNumber($number) 108 { 109 $this->number = $number; 110 } 111 112 public function getNumber() 113 { 114 return $this->number; 115 } 116 117 public function setLabel($label) 118 { 119 $this->label = $label; 120 } 121 122 public function getLabel() 123 { 124 return $this->label; 125 } 126 127 public function isRepeated() 128 { 129 return $this->label === GPBLabel::REPEATED; 130 } 131 132 public function setType($type) 133 { 134 $this->type = $type; 135 } 136 137 public function getType() 138 { 139 return $this->type; 140 } 141 142 public function setMessageType($message_type) 143 { 144 $this->message_type = $message_type; 145 } 146 147 public function getMessageType() 148 { 149 return $this->message_type; 150 } 151 152 public function setEnumType($enum_type) 153 { 154 $this->enum_type = $enum_type; 155 } 156 157 public function getEnumType() 158 { 159 return $this->enum_type; 160 } 161 162 public function setPacked($packed) 163 { 164 $this->packed = $packed; 165 } 166 167 public function getPacked() 168 { 169 return $this->packed; 170 } 171 172 public function isPackable() 173 { 174 return $this->isRepeated() && self::isTypePackable($this->type); 175 } 176 177 public function isMap() 178 { 179 return $this->getType() == GPBType::MESSAGE && 180 !is_null($this->getMessageType()->getOptions()) && 181 $this->getMessageType()->getOptions()->getMapEntry(); 182 } 183 184 public function isTimestamp() 185 { 186 return $this->getType() == GPBType::MESSAGE && 187 $this->getMessageType()->getClass() === "Google\Protobuf\Timestamp"; 188 } 189 190 public function isWrapperType() 191 { 192 if ($this->getType() == GPBType::MESSAGE) { 193 $class = $this->getMessageType()->getClass(); 194 return in_array($class, [ 195 "Google\Protobuf\DoubleValue", 196 "Google\Protobuf\FloatValue", 197 "Google\Protobuf\Int64Value", 198 "Google\Protobuf\UInt64Value", 199 "Google\Protobuf\Int32Value", 200 "Google\Protobuf\UInt32Value", 201 "Google\Protobuf\BoolValue", 202 "Google\Protobuf\StringValue", 203 "Google\Protobuf\BytesValue", 204 ]); 205 } 206 return false; 207 } 208 209 private static function isTypePackable($field_type) 210 { 211 return ($field_type !== GPBType::STRING && 212 $field_type !== GPBType::GROUP && 213 $field_type !== GPBType::MESSAGE && 214 $field_type !== GPBType::BYTES); 215 } 216 217 public static function getFieldDescriptor($proto) 218 { 219 $type_name = null; 220 $type = $proto->getType(); 221 switch ($type) { 222 case GPBType::MESSAGE: 223 case GPBType::GROUP: 224 case GPBType::ENUM: 225 $type_name = $proto->getTypeName(); 226 break; 227 default: 228 break; 229 } 230 231 $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1; 232 $packed = false; 233 $options = $proto->getOptions(); 234 if ($options !== null) { 235 $packed = $options->getPacked(); 236 } 237 238 $field = new FieldDescriptor(); 239 $field->setName($proto->getName()); 240 241 $json_name = $proto->hasJsonName() ? $proto->getJsonName() : 242 lcfirst(implode('', array_map('ucwords', explode('_', $proto->getName())))); 243 if ($proto->hasJsonName()) { 244 $json_name = $proto->getJsonName(); 245 } else { 246 $proto_name = $proto->getName(); 247 $json_name = implode('', array_map('ucwords', explode('_', $proto_name))); 248 if ($proto_name[0] !== "_" && !ctype_upper($proto_name[0])) { 249 $json_name = lcfirst($json_name); 250 } 251 } 252 $field->setJsonName($json_name); 253 254 $camel_name = implode('', array_map('ucwords', explode('_', $proto->getName()))); 255 $field->setGetter('get' . $camel_name); 256 $field->setSetter('set' . $camel_name); 257 $field->setType($proto->getType()); 258 $field->setNumber($proto->getNumber()); 259 $field->setLabel($proto->getLabel()); 260 $field->setPacked($packed); 261 $field->setOneofIndex($oneof_index); 262 263 // At this time, the message/enum type may have not been added to pool. 264 // So we use the type name as place holder and will replace it with the 265 // actual descriptor in cross building. 266 switch ($type) { 267 case GPBType::MESSAGE: 268 $field->setMessageType($type_name); 269 break; 270 case GPBType::ENUM: 271 $field->setEnumType($type_name); 272 break; 273 default: 274 break; 275 } 276 277 return $field; 278 } 279 280 public static function buildFromProto($proto) 281 { 282 return FieldDescriptor::getFieldDescriptor($proto); 283 } 284} 285