blob: 98b516fecc521d14760c4fc6655554304ebb084a [file] [log] [blame]
avm9996399bb77c2020-01-27 03:15:08 +01001<?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}