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 // TODO: once proto2 is supported, this default should be false 233 // for proto2. 234 if ($proto->getLabel() === GPBLabel::REPEATED && 235 $proto->getType() !== GPBType::MESSAGE && 236 $proto->getType() !== GPBType::GROUP && 237 $proto->getType() !== GPBType::STRING && 238 $proto->getType() !== GPBType::BYTES) { 239 $packed = true; 240 } else { 241 $packed = false; 242 } 243 $options = $proto->getOptions(); 244 if ($options !== null) { 245 $packed = $options->getPacked(); 246 } 247 248 $field = new FieldDescriptor(); 249 $field->setName($proto->getName()); 250 251 $json_name = $proto->hasJsonName() ? $proto->getJsonName() : 252 lcfirst(implode('', array_map('ucwords', explode('_', $proto->getName())))); 253 if ($proto->hasJsonName()) { 254 $json_name = $proto->getJsonName(); 255 } else { 256 $proto_name = $proto->getName(); 257 $json_name = implode('', array_map('ucwords', explode('_', $proto_name))); 258 if ($proto_name[0] !== "_" && !ctype_upper($proto_name[0])) { 259 $json_name = lcfirst($json_name); 260 } 261 } 262 $field->setJsonName($json_name); 263 264 $camel_name = implode('', array_map('ucwords', explode('_', $proto->getName()))); 265 $field->setGetter('get' . $camel_name); 266 $field->setSetter('set' . $camel_name); 267 $field->setType($proto->getType()); 268 $field->setNumber($proto->getNumber()); 269 $field->setLabel($proto->getLabel()); 270 $field->setPacked($packed); 271 $field->setOneofIndex($oneof_index); 272 273 // At this time, the message/enum type may have not been added to pool. 274 // So we use the type name as place holder and will replace it with the 275 // actual descriptor in cross building. 276 switch ($type) { 277 case GPBType::MESSAGE: 278 $field->setMessageType($type_name); 279 break; 280 case GPBType::ENUM: 281 $field->setEnumType($type_name); 282 break; 283 default: 284 break; 285 } 286 287 return $field; 288 } 289 290 public static function buildFromProto($proto) 291 { 292 return FieldDescriptor::getFieldDescriptor($proto); 293 } 294} 295