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