aboutsummaryrefslogtreecommitdiffhomepage
path: root/php/src/Google/Protobuf/Internal/GPBUtil.php
diff options
context:
space:
mode:
Diffstat (limited to 'php/src/Google/Protobuf/Internal/GPBUtil.php')
-rw-r--r--php/src/Google/Protobuf/Internal/GPBUtil.php139
1 files changed, 136 insertions, 3 deletions
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index 7fa4a673..76f84cbd 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -32,14 +32,29 @@
namespace Google\Protobuf\Internal;
+use Google\Protobuf\Duration;
+use Google\Protobuf\FieldMask;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\MapField;
+function camel2underscore($input) {
+ preg_match_all(
+ '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
+ $input,
+ $matches);
+ $ret = $matches[0];
+ foreach ($ret as &$match) {
+ $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
+ }
+ return implode('_', $ret);
+}
+
class GPBUtil
{
const NANOS_PER_MILLISECOND = 1000000;
const NANOS_PER_MICROSECOND = 1000;
+ const TYPE_URL_PREFIX = 'type.googleapis.com/';
public static function divideInt64ToInt32($value, &$high, &$low, $trim = false)
{
@@ -358,7 +373,7 @@ class GPBUtil
}
return $result;
}
-
+
public static function parseTimestamp($timestamp)
{
// prevent parsing timestamps containing with the non-existant year "0000"
@@ -370,7 +385,7 @@ class GPBUtil
if (substr($timestamp, -1, 1) === "z") {
throw new \Exception("Timezone cannot be a lowercase z.");
}
-
+
$nanoseconds = 0;
$periodIndex = strpos($timestamp, ".");
if ($periodIndex !== false) {
@@ -411,9 +426,15 @@ class GPBUtil
$value->setNanos($nanoseconds);
return $value;
}
-
+
public static function formatTimestamp($value)
{
+ if (bccomp($value->getSeconds(), "253402300800") != -1) {
+ throw new GPBDecodeException("Duration number too large.");
+ }
+ if (bccomp($value->getSeconds(), "-62135596801") != 1) {
+ throw new GPBDecodeException("Duration number too small.");
+ }
$nanoseconds = static::getNanosecondsForTimestamp($value->getNanos());
if (!empty($nanoseconds)) {
$nanoseconds = ".".$nanoseconds;
@@ -422,6 +443,93 @@ class GPBUtil
return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z");
}
+ public static function parseDuration($value)
+ {
+ if (strlen($value) < 2 || substr($value, -1) !== "s") {
+ throw new GPBDecodeException("Missing s after duration string");
+ }
+ $number = substr($value, 0, -1);
+ if (bccomp($number, "315576000001") != -1) {
+ throw new GPBDecodeException("Duration number too large.");
+ }
+ if (bccomp($number, "-315576000001") != 1) {
+ throw new GPBDecodeException("Duration number too small.");
+ }
+ $pos = strrpos($number, ".");
+ if ($pos !== false) {
+ $seconds = substr($number, 0, $pos);
+ if (bccomp($seconds, 0) < 0) {
+ $nanos = bcmul("0" . substr($number, $pos), -1000000000);
+ } else {
+ $nanos = bcmul("0" . substr($number, $pos), 1000000000);
+ }
+ } else {
+ $seconds = $number;
+ $nanos = 0;
+ }
+ $duration = new Duration();
+ $duration->setSeconds($seconds);
+ $duration->setNanos($nanos);
+ return $duration;
+ }
+
+ public static function formatDuration($value)
+ {
+ if (bccomp($value->getSeconds(), "315576000001") != -1) {
+ throw new GPBDecodeException("Duration number too large.");
+ }
+ if (bccomp($value->getSeconds(), "-315576000001") != 1) {
+ throw new GPBDecodeException("Duration number too small.");
+ }
+ return strval(bcadd($value->getSeconds(),
+ $value->getNanos() / 1000000000.0, 9));
+ }
+
+
+
+ public static function parseFieldMask($paths_string)
+ {
+ $path_strings = explode(",", $paths_string);
+ $field_mask = new FieldMask();
+ $paths = $field_mask->getPaths();
+ foreach($path_strings as &$path_string) {
+ $field_strings = explode(".", $path_string);
+ foreach($field_strings as &$field_string) {
+ $field_string = camel2underscore($field_string);
+ }
+ $path_string = implode(".", $field_strings);
+ $paths[] = $path_string;
+ }
+ return $field_mask;
+ }
+
+ public static function formatFieldMask($field_mask)
+ {
+ $converted_paths = [];
+ foreach($field_mask->getPaths() as $path) {
+ $fields = explode('.', $path);
+ $converted_path = [];
+ foreach ($fields as $field) {
+ $segments = explode('_', $field);
+ $start = true;
+ $converted_segments = "";
+ foreach($segments as $segment) {
+ if (!$start) {
+ $converted = ucfirst($segment);
+ } else {
+ $converted = $segment;
+ $start = false;
+ }
+ $converted_segments .= $converted;
+ }
+ $converted_path []= $converted_segments;
+ }
+ $converted_path = implode(".", $converted_path);
+ $converted_paths []= $converted_path;
+ }
+ return implode(",", $converted_paths);
+ }
+
public static function getNanosecondsForTimestamp($nanoseconds)
{
if ($nanoseconds == 0) {
@@ -435,4 +543,29 @@ class GPBUtil
}
return sprintf('%09d', $nanoseconds);
}
+
+ public static function hasSpecialJsonMapping($msg)
+ {
+ return is_a($msg, 'Google\Protobuf\Any') ||
+ is_a($msg, "Google\Protobuf\ListValue") ||
+ is_a($msg, "Google\Protobuf\Struct") ||
+ is_a($msg, "Google\Protobuf\Value") ||
+ is_a($msg, "Google\Protobuf\Duration") ||
+ is_a($msg, "Google\Protobuf\Timestamp") ||
+ is_a($msg, "Google\Protobuf\FieldMask") ||
+ static::hasJsonValue($msg);
+ }
+
+ public static function hasJsonValue($msg)
+ {
+ return is_a($msg, "Google\Protobuf\DoubleValue") ||
+ is_a($msg, "Google\Protobuf\FloatValue") ||
+ is_a($msg, "Google\Protobuf\Int64Value") ||
+ is_a($msg, "Google\Protobuf\UInt64Value") ||
+ is_a($msg, "Google\Protobuf\Int32Value") ||
+ is_a($msg, "Google\Protobuf\UInt32Value") ||
+ is_a($msg, "Google\Protobuf\BoolValue") ||
+ is_a($msg, "Google\Protobuf\StringValue") ||
+ is_a($msg, "Google\Protobuf\BytesValue");
+ }
}