Add php protobuffer support for transition to GTFS-realtime
[busui.git] / lib / Protobuf-PHP / library / DrSlump / Protobuf / Message.php
blob:a/lib/Protobuf-PHP/library/DrSlump/Protobuf/Message.php -> blob:b/lib/Protobuf-PHP/library/DrSlump/Protobuf/Message.php
--- a/lib/Protobuf-PHP/library/DrSlump/Protobuf/Message.php
+++ b/lib/Protobuf-PHP/library/DrSlump/Protobuf/Message.php
@@ -1,1 +1,377 @@
-
+<?php
+
+namespace DrSlump\Protobuf;
+
+use DrSlump\Protobuf;
+
+abstract class Message implements \ArrayAccess
+{
+    /** @var \Closure[] */
+    static protected $__extensions = array();
+
+    /** @var \DrSlump\Protobuf\Descriptor */
+    protected $_descriptor;
+    /** @var array Store data for extension fields */
+    protected $_extensions = array();
+    /** @var array Store data for unknown values */
+    protected $_unknown = array();
+
+    /**
+     * @static
+     * @abstract
+     * @return \DrSlump\Protobuf\Descriptor
+     */
+    public static function descriptor()
+    {
+        throw new \BadMethodCallException('This method should be implemented in inherited classes');
+    }
+
+    /**
+     * Register an extension configuration callback
+     *
+     * @static
+     * @param \Closure $fn
+     */
+    public static function extension(\Closure $fn)
+    {
+        static::$__extensions[] = $fn;
+    }
+
+    /**
+     * @param string $data
+     */
+    public function __construct($data = null)
+    {
+        // Cache the descriptor instance
+        $this->_descriptor = Protobuf::getRegistry()->getDescriptor($this);
+
+        // Assign default values to extensions
+        foreach ($this->_descriptor->getFields() as $f) {
+           if ($f->isExtension() && $f->hasDefault()) {
+               $this->_extensions[$f->getName()] = $f->getDefault();
+           }
+        }
+
+        if (NULL !== $data) {
+            $this->parse($data);
+        }
+    }
+
+    // Implements ArrayAccess for extensions and unknown fields
+
+    public function offsetExists($offset)
+    {
+        if (is_numeric($offset)) {
+            return $this->_has($offset);
+        } else {
+            return $this->hasExtension($offset);
+        }
+    }
+
+    public function offsetSet($offset, $value)
+    {
+        if (is_numeric($offset)) {
+            $this->_set($offset, $value);
+        } else {
+            $this->setExtension($offset, $value);
+        }
+    }
+
+    public function offsetGet( $offset )
+    {
+        if (is_numeric($offset)) {
+            return $this->_get($offset);
+        } else {
+            return $this->getExtension($offset);
+        }
+    }
+
+    public function offsetUnset( $offset )
+    {
+        if (is_numeric($offset)) {
+            $this->_clear($offset);
+        } else {
+            $this->clearExtension($offset);
+        }
+    }
+
+    /**
+     * Parse the given data to hydrate the object
+     *
+     * @param string $data
+     * @param CodecInterface|null $codec
+     */
+    public function parse($data, Protobuf\CodecInterface $codec = null)
+    {
+        $codec = Protobuf::getCodec($codec);
+        $codec->decode($this, $data);
+    }
+
+    /**
+     * Serialize the current object data
+     *
+     * @param CodecInterface|null $codec
+     * @return string
+     */
+    public function serialize(Protobuf\CodecInterface $codec = null)
+    {
+        $codec = Protobuf::getCodec($codec);
+        return $codec->encode($this);
+    }
+
+
+    /**
+     * Checks if the given tag number is set
+     *
+     * @param int $tag
+     * @return bool
+     */
+    public function _has($tag)
+    {
+        if ($this->_descriptor->hasField($tag)) {
+            $f = $this->_descriptor->getField($tag);
+            $name = $f->getName();
+
+            if ($f->isExtension()) {
+                return $f->isRepeated()
+                       ? count($this->_extensions[$name]) > 0
+                       : $this->_extensions[$name] !== NULL;
+            } else {
+                return $f->isRepeated()
+                       ? count($this->$name) > 0
+                       : $this->$name !== NULL;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the value by tag number
+     *
+     * @param int $tag
+     * @param int|null $idx
+     * @return mixed
+     */
+    public function _get($tag, $idx = null)
+    {
+        $f = $this->_descriptor->getField($tag);
+
+        if (!$f) {
+            return null;
+        }
+
+        $name = $f->getName();
+
+        if (!$f->isExtension()) {
+
+            return $idx !== NULL
+                   ? $this->{$name}[$idx]
+                   : $this->$name;
+
+        } else {
+
+            return $idx !== NULL
+                   ? $this->_extensions[$name][$idx]
+                   : $this->_extensions[$name];
+
+        }
+
+    }
+
+    /**
+     * Sets the value by tag number
+     *
+     * @throws \Exception If trying to set an unknown field
+     * @param int $tag
+     * @param mixed $value
+     * @param int|null $idx
+     * @return \DrSlump\Protobuf\Message - Fluent interface
+     */
+    public function _set($tag, $value, $idx = null)
+    {
+        $f = $this->_descriptor->getField($tag);
+
+        if (!$f) {
+            throw new \Exception('Unknown fields not supported');
+        }
+
+        $name = $f->getName();
+        if (!$f->isExtension()) {
+
+            if ($idx === NULL) {
+                $this->$name = $value;
+            } else {
+                $this->{$name}[$idx] = $value;
+            }
+
+        } else {
+            if ($idx === NULL) {
+                $this->_extensions[$name] = $value;
+            } else {
+                $this->_extensions[$name][$idx] = $value;
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Adds a new value to a repeated field by tag number
+     *
+     * @throws \Exception If trying to modify an unknown field
+     * @param int $tag
+     * @param mixed $value
+     * @return Message
+     */
+    public function _add($tag, $value)
+    {
+        $f = $this->_descriptor->getField($tag);
+
+        if (!$f) {
+            throw new \Exception('Unknown fields not supported');
+        }
+
+        $name = $f->getName();
+        if (!$f->isExtension()) {
+            $this->{$name}[] = $value;
+        } else {
+            $this->_extensions[$name][] = $value;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Clears/Resets a field by tag number
+     *
+     * @throws \Exception If trying to modify an unknown field
+     * @param int $tag
+     * @return \DrSlump\Protobuf\Message - Fluent interface
+     */
+    public function _clear($tag)
+    {
+        $f = $this->_descriptor->getField($tag);
+
+        if (!$f) {
+            throw new \Exception('Unknown fields not supported');
+        }
+
+        $name = $f->getName();
+        if (!$f->isExtension()) {
+            $this->$name = $f->isRepeated()
+                           ? array()
+                           : NULL;
+        } else {
+            $this->_extensions[$name] = $f->isRepeated()
+                                      ? array()
+                                      : NULL;
+        }
+
+        return $this;
+    }
+
+    // Extensions public methods.
+    // @todo Check if extension name is defined
+
+    /**
+     * Checks if an extension field is set
+     *
+     * @param string $extname
+     * @return bool
+     */
+    public function hasExtension($extname)
+    {
+        return isset($this->_extensions[$extname]);
+    }
+
+    /**
+     * Get the value of an extension field
+     *
+     * @param string $extname
+     * @param int|null $idx
+     * @return mixed
+     */
+    public function getExtension($extname, $idx = null)
+    {
+        if (!isset($this->_extensions[$extname])) return NULL;
+
+        return $idx === NULL
+               ? $this->_extensions[$extname]
+               : $this->_extensions[$extname][$idx];
+    }
+
+    /**
+     * Get all the values of a repeated extension field
+     *
+     * @param string $extname
+     * @return array
+     */
+    public function getExtensionList($extname)
+    {
+        return isset($this->_extensions[$extname])
+               ? $this->_extensions[$extname]
+               : array();
+    }
+
+    /**
+     * Set the value for an extension field
+     *
+     * @param string $extname
+     * @param mixed $value
+     * @param int|null $idx
+     * @return \DrSlump\Protobuf\Message - Fluent Interface
+     */
+    public function setExtension($extname, $value, $idx = null)
+    {
+        if (NULL !== $idx) {
+            if (empty($this->_extensions)) {
+                $this->_extensions[$extname] = array();
+            }
+            $this->_extensions[$extname][$idx] = $value;
+        }
+
+        $this->_extensions[$extname] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Adds a value to repeated extension field
+     *
+     * @param string $extname
+     * @param mixed $value
+     * @return \DrSlump\Protobuf\Message - Fluent Interface
+     */
+    public function addExtension($extname, $value)
+    {
+        $this->_extensions[$extname][] = $value;
+    }
+
+    /**
+     * @param  $extname
+     * @return void
+     */
+    public function clearExtension($extname)
+    {
+        unset($this->_extensions[$extname]);
+    }
+
+
+    public function addUnknown(Unknown $unknown)
+    {
+        $this->_unknown[] = $unknown;
+    }
+
+    public function getUnknown()
+    {
+        return $this->_unknown;
+    }
+
+    public function clearUnknown()
+    {
+        $this->_unknown = array();
+    }
+
+}
+