1ffe3c632Sopenharmony_ci<?php
2ffe3c632Sopenharmony_ci
3ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format
4ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc.  All rights reserved.
5ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/
6ffe3c632Sopenharmony_ci//
7ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
8ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are
9ffe3c632Sopenharmony_ci// met:
10ffe3c632Sopenharmony_ci//
11ffe3c632Sopenharmony_ci//     * Redistributions of source code must retain the above copyright
12ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer.
13ffe3c632Sopenharmony_ci//     * Redistributions in binary form must reproduce the above
14ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer
15ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the
16ffe3c632Sopenharmony_ci// distribution.
17ffe3c632Sopenharmony_ci//     * Neither the name of Google Inc. nor the names of its
18ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from
19ffe3c632Sopenharmony_ci// this software without specific prior written permission.
20ffe3c632Sopenharmony_ci//
21ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32ffe3c632Sopenharmony_ci
33ffe3c632Sopenharmony_cinamespace Google\Protobuf\Internal;
34ffe3c632Sopenharmony_ci
35ffe3c632Sopenharmony_ciuse Google\Protobuf\Duration;
36ffe3c632Sopenharmony_ciuse Google\Protobuf\FieldMask;
37ffe3c632Sopenharmony_ciuse Google\Protobuf\Internal\GPBType;
38ffe3c632Sopenharmony_ciuse Google\Protobuf\Internal\RepeatedField;
39ffe3c632Sopenharmony_ciuse Google\Protobuf\Internal\MapField;
40ffe3c632Sopenharmony_ci
41ffe3c632Sopenharmony_cifunction camel2underscore($input) {
42ffe3c632Sopenharmony_ci    preg_match_all(
43ffe3c632Sopenharmony_ci        '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
44ffe3c632Sopenharmony_ci        $input,
45ffe3c632Sopenharmony_ci        $matches);
46ffe3c632Sopenharmony_ci    $ret = $matches[0];
47ffe3c632Sopenharmony_ci    foreach ($ret as &$match) {
48ffe3c632Sopenharmony_ci        $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
49ffe3c632Sopenharmony_ci    }
50ffe3c632Sopenharmony_ci    return implode('_', $ret);
51ffe3c632Sopenharmony_ci}
52ffe3c632Sopenharmony_ci
53ffe3c632Sopenharmony_ciclass GPBUtil
54ffe3c632Sopenharmony_ci{
55ffe3c632Sopenharmony_ci    const NANOS_PER_MILLISECOND = 1000000;
56ffe3c632Sopenharmony_ci    const NANOS_PER_MICROSECOND = 1000;
57ffe3c632Sopenharmony_ci    const TYPE_URL_PREFIX = 'type.googleapis.com/';
58ffe3c632Sopenharmony_ci
59ffe3c632Sopenharmony_ci    public static function divideInt64ToInt32($value, &$high, &$low, $trim = false)
60ffe3c632Sopenharmony_ci    {
61ffe3c632Sopenharmony_ci        $isNeg = (bccomp($value, 0) < 0);
62ffe3c632Sopenharmony_ci        if ($isNeg) {
63ffe3c632Sopenharmony_ci            $value = bcsub(0, $value);
64ffe3c632Sopenharmony_ci        }
65ffe3c632Sopenharmony_ci
66ffe3c632Sopenharmony_ci        $high = bcdiv($value, 4294967296);
67ffe3c632Sopenharmony_ci        $low = bcmod($value, 4294967296);
68ffe3c632Sopenharmony_ci        if (bccomp($high, 2147483647) > 0) {
69ffe3c632Sopenharmony_ci            $high = (int) bcsub($high, 4294967296);
70ffe3c632Sopenharmony_ci        } else {
71ffe3c632Sopenharmony_ci            $high = (int) $high;
72ffe3c632Sopenharmony_ci        }
73ffe3c632Sopenharmony_ci        if (bccomp($low, 2147483647) > 0) {
74ffe3c632Sopenharmony_ci            $low = (int) bcsub($low, 4294967296);
75ffe3c632Sopenharmony_ci        } else {
76ffe3c632Sopenharmony_ci            $low = (int) $low;
77ffe3c632Sopenharmony_ci        }
78ffe3c632Sopenharmony_ci
79ffe3c632Sopenharmony_ci        if ($isNeg) {
80ffe3c632Sopenharmony_ci            $high = ~$high;
81ffe3c632Sopenharmony_ci            $low = ~$low;
82ffe3c632Sopenharmony_ci            $low++;
83ffe3c632Sopenharmony_ci            if (!$low) {
84ffe3c632Sopenharmony_ci                $high = (int)($high + 1);
85ffe3c632Sopenharmony_ci            }
86ffe3c632Sopenharmony_ci        }
87ffe3c632Sopenharmony_ci
88ffe3c632Sopenharmony_ci        if ($trim) {
89ffe3c632Sopenharmony_ci            $high = 0;
90ffe3c632Sopenharmony_ci        }
91ffe3c632Sopenharmony_ci    }
92ffe3c632Sopenharmony_ci
93ffe3c632Sopenharmony_ci    public static function checkString(&$var, $check_utf8)
94ffe3c632Sopenharmony_ci    {
95ffe3c632Sopenharmony_ci        if (is_array($var) || is_object($var)) {
96ffe3c632Sopenharmony_ci            throw new \InvalidArgumentException("Expect string.");
97ffe3c632Sopenharmony_ci        }
98ffe3c632Sopenharmony_ci        if (!is_string($var)) {
99ffe3c632Sopenharmony_ci            $var = strval($var);
100ffe3c632Sopenharmony_ci        }
101ffe3c632Sopenharmony_ci        if ($check_utf8 && !preg_match('//u', $var)) {
102ffe3c632Sopenharmony_ci            throw new \Exception("Expect utf-8 encoding.");
103ffe3c632Sopenharmony_ci        }
104ffe3c632Sopenharmony_ci    }
105ffe3c632Sopenharmony_ci
106ffe3c632Sopenharmony_ci    public static function checkEnum(&$var)
107ffe3c632Sopenharmony_ci    {
108ffe3c632Sopenharmony_ci      static::checkInt32($var);
109ffe3c632Sopenharmony_ci    }
110ffe3c632Sopenharmony_ci
111ffe3c632Sopenharmony_ci    public static function checkInt32(&$var)
112ffe3c632Sopenharmony_ci    {
113ffe3c632Sopenharmony_ci        if (is_numeric($var)) {
114ffe3c632Sopenharmony_ci            $var = intval($var);
115ffe3c632Sopenharmony_ci        } else {
116ffe3c632Sopenharmony_ci            throw new \Exception("Expect integer.");
117ffe3c632Sopenharmony_ci        }
118ffe3c632Sopenharmony_ci    }
119ffe3c632Sopenharmony_ci
120ffe3c632Sopenharmony_ci    public static function checkUint32(&$var)
121ffe3c632Sopenharmony_ci    {
122ffe3c632Sopenharmony_ci        if (is_numeric($var)) {
123ffe3c632Sopenharmony_ci            if (PHP_INT_SIZE === 8) {
124ffe3c632Sopenharmony_ci                $var = intval($var);
125ffe3c632Sopenharmony_ci                $var |= ((-(($var >> 31) & 0x1)) & ~0xFFFFFFFF);
126ffe3c632Sopenharmony_ci            } else {
127ffe3c632Sopenharmony_ci                if (bccomp($var, 0x7FFFFFFF) > 0) {
128ffe3c632Sopenharmony_ci                    $var = bcsub($var, "4294967296");
129ffe3c632Sopenharmony_ci                }
130ffe3c632Sopenharmony_ci                $var = (int) $var;
131ffe3c632Sopenharmony_ci            }
132ffe3c632Sopenharmony_ci        } else {
133ffe3c632Sopenharmony_ci            throw new \Exception("Expect integer.");
134ffe3c632Sopenharmony_ci        }
135ffe3c632Sopenharmony_ci    }
136ffe3c632Sopenharmony_ci
137ffe3c632Sopenharmony_ci    public static function checkInt64(&$var)
138ffe3c632Sopenharmony_ci    {
139ffe3c632Sopenharmony_ci        if (is_numeric($var)) {
140ffe3c632Sopenharmony_ci            if (PHP_INT_SIZE == 8) {
141ffe3c632Sopenharmony_ci                $var = intval($var);
142ffe3c632Sopenharmony_ci            } else {
143ffe3c632Sopenharmony_ci                if (is_float($var) ||
144ffe3c632Sopenharmony_ci                    is_integer($var) ||
145ffe3c632Sopenharmony_ci                    (is_string($var) &&
146ffe3c632Sopenharmony_ci                         bccomp($var, "9223372036854774784") < 0)) {
147ffe3c632Sopenharmony_ci                    $var = number_format($var, 0, ".", "");
148ffe3c632Sopenharmony_ci                }
149ffe3c632Sopenharmony_ci            }
150ffe3c632Sopenharmony_ci        } else {
151ffe3c632Sopenharmony_ci            throw new \Exception("Expect integer.");
152ffe3c632Sopenharmony_ci        }
153ffe3c632Sopenharmony_ci    }
154ffe3c632Sopenharmony_ci
155ffe3c632Sopenharmony_ci    public static function checkUint64(&$var)
156ffe3c632Sopenharmony_ci    {
157ffe3c632Sopenharmony_ci        if (is_numeric($var)) {
158ffe3c632Sopenharmony_ci            if (PHP_INT_SIZE == 8) {
159ffe3c632Sopenharmony_ci                $var = intval($var);
160ffe3c632Sopenharmony_ci            } else {
161ffe3c632Sopenharmony_ci                $var = number_format($var, 0, ".", "");
162ffe3c632Sopenharmony_ci            }
163ffe3c632Sopenharmony_ci        } else {
164ffe3c632Sopenharmony_ci            throw new \Exception("Expect integer.");
165ffe3c632Sopenharmony_ci        }
166ffe3c632Sopenharmony_ci    }
167ffe3c632Sopenharmony_ci
168ffe3c632Sopenharmony_ci    public static function checkFloat(&$var)
169ffe3c632Sopenharmony_ci    {
170ffe3c632Sopenharmony_ci        if (is_float($var) || is_numeric($var)) {
171ffe3c632Sopenharmony_ci            $var = floatval($var);
172ffe3c632Sopenharmony_ci        } else {
173ffe3c632Sopenharmony_ci            throw new \Exception("Expect float.");
174ffe3c632Sopenharmony_ci        }
175ffe3c632Sopenharmony_ci    }
176ffe3c632Sopenharmony_ci
177ffe3c632Sopenharmony_ci    public static function checkDouble(&$var)
178ffe3c632Sopenharmony_ci    {
179ffe3c632Sopenharmony_ci        if (is_float($var) || is_numeric($var)) {
180ffe3c632Sopenharmony_ci            $var = floatval($var);
181ffe3c632Sopenharmony_ci        } else {
182ffe3c632Sopenharmony_ci            throw new \Exception("Expect float.");
183ffe3c632Sopenharmony_ci        }
184ffe3c632Sopenharmony_ci    }
185ffe3c632Sopenharmony_ci
186ffe3c632Sopenharmony_ci    public static function checkBool(&$var)
187ffe3c632Sopenharmony_ci    {
188ffe3c632Sopenharmony_ci        if (is_array($var) || is_object($var)) {
189ffe3c632Sopenharmony_ci            throw new \Exception("Expect boolean.");
190ffe3c632Sopenharmony_ci        }
191ffe3c632Sopenharmony_ci        $var = boolval($var);
192ffe3c632Sopenharmony_ci    }
193ffe3c632Sopenharmony_ci
194ffe3c632Sopenharmony_ci    public static function checkMessage(&$var, $klass, $newClass = null)
195ffe3c632Sopenharmony_ci    {
196ffe3c632Sopenharmony_ci        if (!$var instanceof $klass && !is_null($var)) {
197ffe3c632Sopenharmony_ci            throw new \Exception("Expect $klass.");
198ffe3c632Sopenharmony_ci        }
199ffe3c632Sopenharmony_ci    }
200ffe3c632Sopenharmony_ci
201ffe3c632Sopenharmony_ci    public static function checkRepeatedField(&$var, $type, $klass = null)
202ffe3c632Sopenharmony_ci    {
203ffe3c632Sopenharmony_ci        if (!$var instanceof RepeatedField && !is_array($var)) {
204ffe3c632Sopenharmony_ci            throw new \Exception("Expect array.");
205ffe3c632Sopenharmony_ci        }
206ffe3c632Sopenharmony_ci        if (is_array($var)) {
207ffe3c632Sopenharmony_ci            $tmp = new RepeatedField($type, $klass);
208ffe3c632Sopenharmony_ci            foreach ($var as $value) {
209ffe3c632Sopenharmony_ci                $tmp[] = $value;
210ffe3c632Sopenharmony_ci            }
211ffe3c632Sopenharmony_ci            return $tmp;
212ffe3c632Sopenharmony_ci        } else {
213ffe3c632Sopenharmony_ci            if ($var->getType() != $type) {
214ffe3c632Sopenharmony_ci                throw new \Exception(
215ffe3c632Sopenharmony_ci                    "Expect repeated field of different type.");
216ffe3c632Sopenharmony_ci            }
217ffe3c632Sopenharmony_ci            if ($var->getType() === GPBType::MESSAGE &&
218ffe3c632Sopenharmony_ci                $var->getClass() !== $klass &&
219ffe3c632Sopenharmony_ci                $var->getLegacyClass() !== $klass) {
220ffe3c632Sopenharmony_ci                throw new \Exception(
221ffe3c632Sopenharmony_ci                    "Expect repeated field of " . $klass . ".");
222ffe3c632Sopenharmony_ci            }
223ffe3c632Sopenharmony_ci            return $var;
224ffe3c632Sopenharmony_ci        }
225ffe3c632Sopenharmony_ci    }
226ffe3c632Sopenharmony_ci
227ffe3c632Sopenharmony_ci    public static function checkMapField(&$var, $key_type, $value_type, $klass = null)
228ffe3c632Sopenharmony_ci    {
229ffe3c632Sopenharmony_ci        if (!$var instanceof MapField && !is_array($var)) {
230ffe3c632Sopenharmony_ci            throw new \Exception("Expect dict.");
231ffe3c632Sopenharmony_ci        }
232ffe3c632Sopenharmony_ci        if (is_array($var)) {
233ffe3c632Sopenharmony_ci            $tmp = new MapField($key_type, $value_type, $klass);
234ffe3c632Sopenharmony_ci            foreach ($var as $key => $value) {
235ffe3c632Sopenharmony_ci                $tmp[$key] = $value;
236ffe3c632Sopenharmony_ci            }
237ffe3c632Sopenharmony_ci            return $tmp;
238ffe3c632Sopenharmony_ci        } else {
239ffe3c632Sopenharmony_ci            if ($var->getKeyType() != $key_type) {
240ffe3c632Sopenharmony_ci                throw new \Exception("Expect map field of key type.");
241ffe3c632Sopenharmony_ci            }
242ffe3c632Sopenharmony_ci            if ($var->getValueType() != $value_type) {
243ffe3c632Sopenharmony_ci                throw new \Exception("Expect map field of value type.");
244ffe3c632Sopenharmony_ci            }
245ffe3c632Sopenharmony_ci            if ($var->getValueType() === GPBType::MESSAGE &&
246ffe3c632Sopenharmony_ci                $var->getValueClass() !== $klass &&
247ffe3c632Sopenharmony_ci                $var->getLegacyValueClass() !== $klass) {
248ffe3c632Sopenharmony_ci                throw new \Exception(
249ffe3c632Sopenharmony_ci                    "Expect map field of " . $klass . ".");
250ffe3c632Sopenharmony_ci            }
251ffe3c632Sopenharmony_ci            return $var;
252ffe3c632Sopenharmony_ci        }
253ffe3c632Sopenharmony_ci    }
254ffe3c632Sopenharmony_ci
255ffe3c632Sopenharmony_ci    public static function Int64($value)
256ffe3c632Sopenharmony_ci    {
257ffe3c632Sopenharmony_ci        return new Int64($value);
258ffe3c632Sopenharmony_ci    }
259ffe3c632Sopenharmony_ci
260ffe3c632Sopenharmony_ci    public static function Uint64($value)
261ffe3c632Sopenharmony_ci    {
262ffe3c632Sopenharmony_ci        return new Uint64($value);
263ffe3c632Sopenharmony_ci    }
264ffe3c632Sopenharmony_ci
265ffe3c632Sopenharmony_ci    public static function getClassNamePrefix(
266ffe3c632Sopenharmony_ci        $classname,
267ffe3c632Sopenharmony_ci        $file_proto)
268ffe3c632Sopenharmony_ci    {
269ffe3c632Sopenharmony_ci        $option = $file_proto->getOptions();
270ffe3c632Sopenharmony_ci        $prefix = is_null($option) ? "" : $option->getPhpClassPrefix();
271ffe3c632Sopenharmony_ci        if ($prefix !== "") {
272ffe3c632Sopenharmony_ci            return $prefix;
273ffe3c632Sopenharmony_ci        }
274ffe3c632Sopenharmony_ci
275ffe3c632Sopenharmony_ci        $reserved_words = array(
276ffe3c632Sopenharmony_ci            "abstract"=>0, "and"=>0, "array"=>0, "as"=>0, "break"=>0,
277ffe3c632Sopenharmony_ci            "callable"=>0, "case"=>0, "catch"=>0, "class"=>0, "clone"=>0,
278ffe3c632Sopenharmony_ci            "const"=>0, "continue"=>0, "declare"=>0, "default"=>0, "die"=>0,
279ffe3c632Sopenharmony_ci            "do"=>0, "echo"=>0, "else"=>0, "elseif"=>0, "empty"=>0,
280ffe3c632Sopenharmony_ci            "enddeclare"=>0, "endfor"=>0, "endforeach"=>0, "endif"=>0,
281ffe3c632Sopenharmony_ci            "endswitch"=>0, "endwhile"=>0, "eval"=>0, "exit"=>0, "extends"=>0,
282ffe3c632Sopenharmony_ci            "final"=>0, "for"=>0, "foreach"=>0, "function"=>0, "global"=>0,
283ffe3c632Sopenharmony_ci            "goto"=>0, "if"=>0, "implements"=>0, "include"=>0,
284ffe3c632Sopenharmony_ci            "include_once"=>0, "instanceof"=>0, "insteadof"=>0, "interface"=>0,
285ffe3c632Sopenharmony_ci            "isset"=>0, "list"=>0, "namespace"=>0, "new"=>0, "or"=>0,
286ffe3c632Sopenharmony_ci            "print"=>0, "private"=>0, "protected"=>0, "public"=>0, "require"=>0,
287ffe3c632Sopenharmony_ci            "require_once"=>0, "return"=>0, "static"=>0, "switch"=>0,
288ffe3c632Sopenharmony_ci            "throw"=>0, "trait"=>0, "try"=>0, "unset"=>0, "use"=>0, "var"=>0,
289ffe3c632Sopenharmony_ci            "while"=>0, "xor"=>0, "int"=>0, "float"=>0, "bool"=>0, "string"=>0,
290ffe3c632Sopenharmony_ci            "true"=>0, "false"=>0, "null"=>0, "void"=>0, "iterable"=>0
291ffe3c632Sopenharmony_ci        );
292ffe3c632Sopenharmony_ci
293ffe3c632Sopenharmony_ci        if (array_key_exists(strtolower($classname), $reserved_words)) {
294ffe3c632Sopenharmony_ci            if ($file_proto->getPackage() === "google.protobuf") {
295ffe3c632Sopenharmony_ci                return "GPB";
296ffe3c632Sopenharmony_ci            } else {
297ffe3c632Sopenharmony_ci                return "PB";
298ffe3c632Sopenharmony_ci            }
299ffe3c632Sopenharmony_ci        }
300ffe3c632Sopenharmony_ci
301ffe3c632Sopenharmony_ci        return "";
302ffe3c632Sopenharmony_ci    }
303ffe3c632Sopenharmony_ci
304ffe3c632Sopenharmony_ci    public static function getLegacyClassNameWithoutPackage(
305ffe3c632Sopenharmony_ci        $name,
306ffe3c632Sopenharmony_ci        $file_proto)
307ffe3c632Sopenharmony_ci    {
308ffe3c632Sopenharmony_ci        $classname = implode('_', explode('.', $name));
309ffe3c632Sopenharmony_ci        return static::getClassNamePrefix($classname, $file_proto) . $classname;
310ffe3c632Sopenharmony_ci    }
311ffe3c632Sopenharmony_ci
312ffe3c632Sopenharmony_ci    public static function getClassNameWithoutPackage(
313ffe3c632Sopenharmony_ci        $name,
314ffe3c632Sopenharmony_ci        $file_proto)
315ffe3c632Sopenharmony_ci    {
316ffe3c632Sopenharmony_ci        $parts = explode('.', $name);
317ffe3c632Sopenharmony_ci        foreach ($parts as $i => $part) {
318ffe3c632Sopenharmony_ci            $parts[$i] = static::getClassNamePrefix($parts[$i], $file_proto) . $parts[$i];
319ffe3c632Sopenharmony_ci        }
320ffe3c632Sopenharmony_ci        return implode('\\', $parts);
321ffe3c632Sopenharmony_ci    }
322ffe3c632Sopenharmony_ci
323ffe3c632Sopenharmony_ci    public static function getFullClassName(
324ffe3c632Sopenharmony_ci        $proto,
325ffe3c632Sopenharmony_ci        $containing,
326ffe3c632Sopenharmony_ci        $file_proto,
327ffe3c632Sopenharmony_ci        &$message_name_without_package,
328ffe3c632Sopenharmony_ci        &$classname,
329ffe3c632Sopenharmony_ci        &$legacy_classname,
330ffe3c632Sopenharmony_ci        &$fullname)
331ffe3c632Sopenharmony_ci    {
332ffe3c632Sopenharmony_ci        // Full name needs to start with '.'.
333ffe3c632Sopenharmony_ci        $message_name_without_package = $proto->getName();
334ffe3c632Sopenharmony_ci        if ($containing !== "") {
335ffe3c632Sopenharmony_ci            $message_name_without_package =
336ffe3c632Sopenharmony_ci                $containing . "." . $message_name_without_package;
337ffe3c632Sopenharmony_ci        }
338ffe3c632Sopenharmony_ci
339ffe3c632Sopenharmony_ci        $package = $file_proto->getPackage();
340ffe3c632Sopenharmony_ci        if ($package === "") {
341ffe3c632Sopenharmony_ci            $fullname = $message_name_without_package;
342ffe3c632Sopenharmony_ci        } else {
343ffe3c632Sopenharmony_ci            $fullname = $package . "." . $message_name_without_package;
344ffe3c632Sopenharmony_ci        }
345ffe3c632Sopenharmony_ci
346ffe3c632Sopenharmony_ci        $class_name_without_package =
347ffe3c632Sopenharmony_ci            static::getClassNameWithoutPackage($message_name_without_package, $file_proto);
348ffe3c632Sopenharmony_ci        $legacy_class_name_without_package =
349ffe3c632Sopenharmony_ci            static::getLegacyClassNameWithoutPackage(
350ffe3c632Sopenharmony_ci                $message_name_without_package, $file_proto);
351ffe3c632Sopenharmony_ci
352ffe3c632Sopenharmony_ci        $option = $file_proto->getOptions();
353ffe3c632Sopenharmony_ci        if (!is_null($option) && $option->hasPhpNamespace()) {
354ffe3c632Sopenharmony_ci            $namespace = $option->getPhpNamespace();
355ffe3c632Sopenharmony_ci            if ($namespace !== "") {
356ffe3c632Sopenharmony_ci                $classname = $namespace . "\\" . $class_name_without_package;
357ffe3c632Sopenharmony_ci                $legacy_classname =
358ffe3c632Sopenharmony_ci                    $namespace . "\\" . $legacy_class_name_without_package;
359ffe3c632Sopenharmony_ci                return;
360ffe3c632Sopenharmony_ci            } else {
361ffe3c632Sopenharmony_ci                $classname = $class_name_without_package;
362ffe3c632Sopenharmony_ci                $legacy_classname = $legacy_class_name_without_package;
363ffe3c632Sopenharmony_ci                return;
364ffe3c632Sopenharmony_ci            }
365ffe3c632Sopenharmony_ci        }
366ffe3c632Sopenharmony_ci
367ffe3c632Sopenharmony_ci        if ($package === "") {
368ffe3c632Sopenharmony_ci            $classname = $class_name_without_package;
369ffe3c632Sopenharmony_ci            $legacy_classname = $legacy_class_name_without_package;
370ffe3c632Sopenharmony_ci        } else {
371ffe3c632Sopenharmony_ci            $parts = array_map('ucwords', explode('.', $package));
372ffe3c632Sopenharmony_ci            foreach ($parts as $i => $part) {
373ffe3c632Sopenharmony_ci                $parts[$i] = self::getClassNamePrefix($part, $file_proto).$part;
374ffe3c632Sopenharmony_ci            }
375ffe3c632Sopenharmony_ci            $classname =
376ffe3c632Sopenharmony_ci                implode('\\', $parts) .
377ffe3c632Sopenharmony_ci                "\\".self::getClassNamePrefix($class_name_without_package,$file_proto).
378ffe3c632Sopenharmony_ci                $class_name_without_package;
379ffe3c632Sopenharmony_ci            $legacy_classname =
380ffe3c632Sopenharmony_ci                implode('\\', array_map('ucwords', explode('.', $package))).
381ffe3c632Sopenharmony_ci                "\\".$legacy_class_name_without_package;
382ffe3c632Sopenharmony_ci        }
383ffe3c632Sopenharmony_ci    }
384ffe3c632Sopenharmony_ci
385ffe3c632Sopenharmony_ci    public static function combineInt32ToInt64($high, $low)
386ffe3c632Sopenharmony_ci    {
387ffe3c632Sopenharmony_ci        $isNeg = $high < 0;
388ffe3c632Sopenharmony_ci        if ($isNeg) {
389ffe3c632Sopenharmony_ci            $high = ~$high;
390ffe3c632Sopenharmony_ci            $low = ~$low;
391ffe3c632Sopenharmony_ci            $low++;
392ffe3c632Sopenharmony_ci            if (!$low) {
393ffe3c632Sopenharmony_ci                $high = (int) ($high + 1);
394ffe3c632Sopenharmony_ci            }
395ffe3c632Sopenharmony_ci        }
396ffe3c632Sopenharmony_ci        $result = bcadd(bcmul($high, 4294967296), $low);
397ffe3c632Sopenharmony_ci        if ($low < 0) {
398ffe3c632Sopenharmony_ci            $result = bcadd($result, 4294967296);
399ffe3c632Sopenharmony_ci        }
400ffe3c632Sopenharmony_ci        if ($isNeg) {
401ffe3c632Sopenharmony_ci          $result = bcsub(0, $result);
402ffe3c632Sopenharmony_ci        }
403ffe3c632Sopenharmony_ci        return $result;
404ffe3c632Sopenharmony_ci    }
405ffe3c632Sopenharmony_ci
406ffe3c632Sopenharmony_ci    public static function parseTimestamp($timestamp)
407ffe3c632Sopenharmony_ci    {
408ffe3c632Sopenharmony_ci        // prevent parsing timestamps containing with the non-existent year "0000"
409ffe3c632Sopenharmony_ci        // DateTime::createFromFormat parses without failing but as a nonsensical date
410ffe3c632Sopenharmony_ci        if (substr($timestamp, 0, 4) === "0000") {
411ffe3c632Sopenharmony_ci            throw new \Exception("Year cannot be zero.");
412ffe3c632Sopenharmony_ci        }
413ffe3c632Sopenharmony_ci        // prevent parsing timestamps ending with a lowercase z
414ffe3c632Sopenharmony_ci        if (substr($timestamp, -1, 1) === "z") {
415ffe3c632Sopenharmony_ci            throw new \Exception("Timezone cannot be a lowercase z.");
416ffe3c632Sopenharmony_ci        }
417ffe3c632Sopenharmony_ci
418ffe3c632Sopenharmony_ci        $nanoseconds = 0;
419ffe3c632Sopenharmony_ci        $periodIndex = strpos($timestamp, ".");
420ffe3c632Sopenharmony_ci        if ($periodIndex !== false) {
421ffe3c632Sopenharmony_ci            $nanosecondsLength = 0;
422ffe3c632Sopenharmony_ci            // find the next non-numeric character in the timestamp to calculate
423ffe3c632Sopenharmony_ci            // the length of the nanoseconds text
424ffe3c632Sopenharmony_ci            for ($i = $periodIndex + 1, $length = strlen($timestamp); $i < $length; $i++) {
425ffe3c632Sopenharmony_ci                if (!is_numeric($timestamp[$i])) {
426ffe3c632Sopenharmony_ci                    $nanosecondsLength = $i - ($periodIndex + 1);
427ffe3c632Sopenharmony_ci                    break;
428ffe3c632Sopenharmony_ci                }
429ffe3c632Sopenharmony_ci            }
430ffe3c632Sopenharmony_ci            if ($nanosecondsLength % 3 !== 0) {
431ffe3c632Sopenharmony_ci                throw new \Exception("Nanoseconds must be disible by 3.");
432ffe3c632Sopenharmony_ci            }
433ffe3c632Sopenharmony_ci            if ($nanosecondsLength > 9) {
434ffe3c632Sopenharmony_ci                throw new \Exception("Nanoseconds must be in the range of 0 to 999,999,999 nanoseconds.");
435ffe3c632Sopenharmony_ci            }
436ffe3c632Sopenharmony_ci            if ($nanosecondsLength > 0) {
437ffe3c632Sopenharmony_ci                $nanoseconds = substr($timestamp, $periodIndex + 1, $nanosecondsLength);
438ffe3c632Sopenharmony_ci                $nanoseconds = intval($nanoseconds);
439ffe3c632Sopenharmony_ci
440ffe3c632Sopenharmony_ci                // remove the nanoseconds and preceding period from the timestamp
441ffe3c632Sopenharmony_ci                $date = substr($timestamp, 0, $periodIndex);
442ffe3c632Sopenharmony_ci                $timezone = substr($timestamp, $periodIndex + $nanosecondsLength + 1);
443ffe3c632Sopenharmony_ci                $timestamp = $date.$timezone;
444ffe3c632Sopenharmony_ci            }
445ffe3c632Sopenharmony_ci        }
446ffe3c632Sopenharmony_ci
447ffe3c632Sopenharmony_ci        $date = \DateTime::createFromFormat(\DateTime::RFC3339, $timestamp, new \DateTimeZone("UTC"));
448ffe3c632Sopenharmony_ci        if ($date === false) {
449ffe3c632Sopenharmony_ci            throw new \Exception("Invalid RFC 3339 timestamp.");
450ffe3c632Sopenharmony_ci        }
451ffe3c632Sopenharmony_ci
452ffe3c632Sopenharmony_ci        $value = new \Google\Protobuf\Timestamp();
453ffe3c632Sopenharmony_ci        $seconds = $date->format("U");
454ffe3c632Sopenharmony_ci        $value->setSeconds($seconds);
455ffe3c632Sopenharmony_ci        $value->setNanos($nanoseconds);
456ffe3c632Sopenharmony_ci        return $value;
457ffe3c632Sopenharmony_ci    }
458ffe3c632Sopenharmony_ci
459ffe3c632Sopenharmony_ci    public static function formatTimestamp($value)
460ffe3c632Sopenharmony_ci    {
461ffe3c632Sopenharmony_ci        if (bccomp($value->getSeconds(), "253402300800") != -1) {
462ffe3c632Sopenharmony_ci          throw new GPBDecodeException("Duration number too large.");
463ffe3c632Sopenharmony_ci        }
464ffe3c632Sopenharmony_ci        if (bccomp($value->getSeconds(), "-62135596801") != 1) {
465ffe3c632Sopenharmony_ci          throw new GPBDecodeException("Duration number too small.");
466ffe3c632Sopenharmony_ci        }
467ffe3c632Sopenharmony_ci        $nanoseconds = static::getNanosecondsForTimestamp($value->getNanos());
468ffe3c632Sopenharmony_ci        if (!empty($nanoseconds)) {
469ffe3c632Sopenharmony_ci            $nanoseconds = ".".$nanoseconds;
470ffe3c632Sopenharmony_ci        }
471ffe3c632Sopenharmony_ci        $date = new \DateTime('@'.$value->getSeconds(), new \DateTimeZone("UTC"));
472ffe3c632Sopenharmony_ci        return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z");
473ffe3c632Sopenharmony_ci    }
474ffe3c632Sopenharmony_ci
475ffe3c632Sopenharmony_ci    public static function parseDuration($value)
476ffe3c632Sopenharmony_ci    {
477ffe3c632Sopenharmony_ci        if (strlen($value) < 2 || substr($value, -1) !== "s") {
478ffe3c632Sopenharmony_ci          throw new GPBDecodeException("Missing s after duration string");
479ffe3c632Sopenharmony_ci        }
480ffe3c632Sopenharmony_ci        $number = substr($value, 0, -1);
481ffe3c632Sopenharmony_ci        if (bccomp($number, "315576000001") != -1) {
482ffe3c632Sopenharmony_ci          throw new GPBDecodeException("Duration number too large.");
483ffe3c632Sopenharmony_ci        }
484ffe3c632Sopenharmony_ci        if (bccomp($number, "-315576000001") != 1) {
485ffe3c632Sopenharmony_ci          throw new GPBDecodeException("Duration number too small.");
486ffe3c632Sopenharmony_ci        }
487ffe3c632Sopenharmony_ci        $pos = strrpos($number, ".");
488ffe3c632Sopenharmony_ci        if ($pos !== false) {
489ffe3c632Sopenharmony_ci            $seconds = substr($number, 0, $pos);
490ffe3c632Sopenharmony_ci            if (bccomp($seconds, 0) < 0) {
491ffe3c632Sopenharmony_ci                $nanos = bcmul("0" . substr($number, $pos), -1000000000);
492ffe3c632Sopenharmony_ci            } else {
493ffe3c632Sopenharmony_ci                $nanos = bcmul("0" . substr($number, $pos), 1000000000);
494ffe3c632Sopenharmony_ci            }
495ffe3c632Sopenharmony_ci        } else {
496ffe3c632Sopenharmony_ci            $seconds = $number;
497ffe3c632Sopenharmony_ci            $nanos = 0;
498ffe3c632Sopenharmony_ci        }
499ffe3c632Sopenharmony_ci        $duration = new Duration();
500ffe3c632Sopenharmony_ci        $duration->setSeconds($seconds);
501ffe3c632Sopenharmony_ci        $duration->setNanos($nanos);
502ffe3c632Sopenharmony_ci        return $duration;
503ffe3c632Sopenharmony_ci    }
504ffe3c632Sopenharmony_ci
505ffe3c632Sopenharmony_ci    public static function formatDuration($value)
506ffe3c632Sopenharmony_ci    {
507ffe3c632Sopenharmony_ci        if (bccomp($value->getSeconds(), '315576000001') != -1) {
508ffe3c632Sopenharmony_ci            throw new GPBDecodeException('Duration number too large.');
509ffe3c632Sopenharmony_ci        }
510ffe3c632Sopenharmony_ci        if (bccomp($value->getSeconds(), '-315576000001') != 1) {
511ffe3c632Sopenharmony_ci            throw new GPBDecodeException('Duration number too small.');
512ffe3c632Sopenharmony_ci        }
513ffe3c632Sopenharmony_ci
514ffe3c632Sopenharmony_ci        $nanos = $value->getNanos();
515ffe3c632Sopenharmony_ci        if ($nanos === 0) {
516ffe3c632Sopenharmony_ci            return (string) $value->getSeconds();
517ffe3c632Sopenharmony_ci        }
518ffe3c632Sopenharmony_ci
519ffe3c632Sopenharmony_ci        if ($nanos % 1000000 === 0) {
520ffe3c632Sopenharmony_ci            $digits = 3;
521ffe3c632Sopenharmony_ci        } elseif ($nanos % 1000 === 0) {
522ffe3c632Sopenharmony_ci            $digits = 6;
523ffe3c632Sopenharmony_ci        } else {
524ffe3c632Sopenharmony_ci            $digits = 9;
525ffe3c632Sopenharmony_ci        }
526ffe3c632Sopenharmony_ci
527ffe3c632Sopenharmony_ci        $nanos = bcdiv($nanos, '1000000000', $digits);
528ffe3c632Sopenharmony_ci        return bcadd($value->getSeconds(), $nanos, $digits);
529ffe3c632Sopenharmony_ci    }
530ffe3c632Sopenharmony_ci
531ffe3c632Sopenharmony_ci    public static function parseFieldMask($paths_string)
532ffe3c632Sopenharmony_ci    {
533ffe3c632Sopenharmony_ci        $field_mask = new FieldMask();
534ffe3c632Sopenharmony_ci        if (strlen($paths_string) === 0) {
535ffe3c632Sopenharmony_ci            return $field_mask;
536ffe3c632Sopenharmony_ci        }
537ffe3c632Sopenharmony_ci        $path_strings = explode(",", $paths_string);
538ffe3c632Sopenharmony_ci        $paths = $field_mask->getPaths();
539ffe3c632Sopenharmony_ci        foreach($path_strings as &$path_string) {
540ffe3c632Sopenharmony_ci            $field_strings = explode(".", $path_string);
541ffe3c632Sopenharmony_ci            foreach($field_strings as &$field_string) {
542ffe3c632Sopenharmony_ci                $field_string = camel2underscore($field_string);
543ffe3c632Sopenharmony_ci            }
544ffe3c632Sopenharmony_ci            $path_string = implode(".", $field_strings);
545ffe3c632Sopenharmony_ci            $paths[] = $path_string;
546ffe3c632Sopenharmony_ci        }
547ffe3c632Sopenharmony_ci        return $field_mask;
548ffe3c632Sopenharmony_ci    }
549ffe3c632Sopenharmony_ci
550ffe3c632Sopenharmony_ci    public static function formatFieldMask($field_mask)
551ffe3c632Sopenharmony_ci    {
552ffe3c632Sopenharmony_ci        $converted_paths = [];
553ffe3c632Sopenharmony_ci        foreach($field_mask->getPaths() as $path) {
554ffe3c632Sopenharmony_ci            $fields = explode('.', $path);
555ffe3c632Sopenharmony_ci            $converted_path = [];
556ffe3c632Sopenharmony_ci            foreach ($fields as $field) {
557ffe3c632Sopenharmony_ci                $segments = explode('_', $field);
558ffe3c632Sopenharmony_ci                $start = true;
559ffe3c632Sopenharmony_ci                $converted_segments = "";
560ffe3c632Sopenharmony_ci                foreach($segments as $segment) {
561ffe3c632Sopenharmony_ci                  if (!$start) {
562ffe3c632Sopenharmony_ci                    $converted = ucfirst($segment);
563ffe3c632Sopenharmony_ci                  } else {
564ffe3c632Sopenharmony_ci                    $converted = $segment;
565ffe3c632Sopenharmony_ci                    $start = false;
566ffe3c632Sopenharmony_ci                  }
567ffe3c632Sopenharmony_ci                  $converted_segments .= $converted;
568ffe3c632Sopenharmony_ci                }
569ffe3c632Sopenharmony_ci                $converted_path []= $converted_segments;
570ffe3c632Sopenharmony_ci            }
571ffe3c632Sopenharmony_ci            $converted_path = implode(".", $converted_path);
572ffe3c632Sopenharmony_ci            $converted_paths []= $converted_path;
573ffe3c632Sopenharmony_ci        }
574ffe3c632Sopenharmony_ci        return implode(",", $converted_paths);
575ffe3c632Sopenharmony_ci    }
576ffe3c632Sopenharmony_ci
577ffe3c632Sopenharmony_ci    public static function getNanosecondsForTimestamp($nanoseconds)
578ffe3c632Sopenharmony_ci    {
579ffe3c632Sopenharmony_ci        if ($nanoseconds == 0) {
580ffe3c632Sopenharmony_ci            return '';
581ffe3c632Sopenharmony_ci        }
582ffe3c632Sopenharmony_ci        if ($nanoseconds % static::NANOS_PER_MILLISECOND == 0) {
583ffe3c632Sopenharmony_ci            return sprintf('%03d', $nanoseconds / static::NANOS_PER_MILLISECOND);
584ffe3c632Sopenharmony_ci        }
585ffe3c632Sopenharmony_ci        if ($nanoseconds % static::NANOS_PER_MICROSECOND == 0) {
586ffe3c632Sopenharmony_ci            return sprintf('%06d', $nanoseconds / static::NANOS_PER_MICROSECOND);
587ffe3c632Sopenharmony_ci        }
588ffe3c632Sopenharmony_ci        return sprintf('%09d', $nanoseconds);
589ffe3c632Sopenharmony_ci    }
590ffe3c632Sopenharmony_ci
591ffe3c632Sopenharmony_ci    public static function hasSpecialJsonMapping($msg)
592ffe3c632Sopenharmony_ci    {
593ffe3c632Sopenharmony_ci        return is_a($msg, 'Google\Protobuf\Any')         ||
594ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\ListValue")   ||
595ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Struct")      ||
596ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Value")       ||
597ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Duration")    ||
598ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Timestamp")   ||
599ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\FieldMask")   ||
600ffe3c632Sopenharmony_ci               static::hasJsonValue($msg);
601ffe3c632Sopenharmony_ci    }
602ffe3c632Sopenharmony_ci
603ffe3c632Sopenharmony_ci    public static function hasJsonValue($msg)
604ffe3c632Sopenharmony_ci    {
605ffe3c632Sopenharmony_ci        return is_a($msg, "Google\Protobuf\DoubleValue") ||
606ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\FloatValue")  ||
607ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Int64Value")  ||
608ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\UInt64Value") ||
609ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\Int32Value")  ||
610ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\UInt32Value") ||
611ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\BoolValue")   ||
612ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\StringValue") ||
613ffe3c632Sopenharmony_ci               is_a($msg, "Google\Protobuf\BytesValue");
614ffe3c632Sopenharmony_ci    }
615ffe3c632Sopenharmony_ci}
616