First prototype
diff --git a/vendor/google/protobuf/src/Google/Protobuf/Internal/CodedInputStream.php b/vendor/google/protobuf/src/Google/Protobuf/Internal/CodedInputStream.php
new file mode 100644
index 0000000..33b1f5a
--- /dev/null
+++ b/vendor/google/protobuf/src/Google/Protobuf/Internal/CodedInputStream.php
@@ -0,0 +1,382 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\Uint64;
+
+class CodedInputStream
+{
+
+    private $buffer;
+    private $buffer_size_after_limit;
+    private $buffer_end;
+    private $current;
+    private $current_limit;
+    private $legitimate_message_end;
+    private $recursion_budget;
+    private $recursion_limit;
+    private $total_bytes_limit;
+    private $total_bytes_read;
+
+    const MAX_VARINT_BYTES = 10;
+    const DEFAULT_RECURSION_LIMIT = 100;
+    const DEFAULT_TOTAL_BYTES_LIMIT = 33554432; // 32 << 20, 32MB
+
+    public function __construct($buffer)
+    {
+        $start = 0;
+        $end = strlen($buffer);
+        $this->buffer = $buffer;
+        $this->buffer_size_after_limit = 0;
+        $this->buffer_end = $end;
+        $this->current = $start;
+        $this->current_limit = $end;
+        $this->legitimate_message_end = false;
+        $this->recursion_budget = self::DEFAULT_RECURSION_LIMIT;
+        $this->recursion_limit = self::DEFAULT_RECURSION_LIMIT;
+        $this->total_bytes_limit = self::DEFAULT_TOTAL_BYTES_LIMIT;
+        $this->total_bytes_read = $end - $start;
+    }
+
+    private function advance($amount)
+    {
+        $this->current += $amount;
+    }
+
+    public function bufferSize()
+    {
+        return $this->buffer_end - $this->current;
+    }
+
+    public function current()
+    {
+        return $this->total_bytes_read -
+            ($this->buffer_end - $this->current +
+            $this->buffer_size_after_limit);
+    }
+
+    public function substr($start, $end)
+    {
+        return substr($this->buffer, $start, $end - $start);
+    }
+
+    private function recomputeBufferLimits()
+    {
+        $this->buffer_end += $this->buffer_size_after_limit;
+        $closest_limit = min($this->current_limit, $this->total_bytes_limit);
+        if ($closest_limit < $this->total_bytes_read) {
+            // The limit position is in the current buffer.  We must adjust the
+            // buffer size accordingly.
+            $this->buffer_size_after_limit = $this->total_bytes_read -
+                $closest_limit;
+            $this->buffer_end -= $this->buffer_size_after_limit;
+        } else {
+            $this->buffer_size_after_limit = 0;
+        }
+    }
+
+    private function consumedEntireMessage()
+    {
+        return $this->legitimate_message_end;
+    }
+
+    /**
+     * Read uint32 into $var. Advance buffer with consumed bytes. If the
+     * contained varint is larger than 32 bits, discard the high order bits.
+     * @param $var.
+     */
+    public function readVarint32(&$var)
+    {
+        if (!$this->readVarint64($var)) {
+            return false;
+        }
+
+        if (PHP_INT_SIZE == 4) {
+            $var = bcmod($var, 4294967296);
+        } else {
+            $var &= 0xFFFFFFFF;
+        }
+
+        // Convert large uint32 to int32.
+        if ($var > 0x7FFFFFFF) {
+            if (PHP_INT_SIZE === 8) {
+                $var = $var | (0xFFFFFFFF << 32);
+            } else {
+                $var = bcsub($var, 4294967296);
+            }
+        }
+
+        $var = intval($var);
+        return true;
+    }
+
+    /**
+     * Read Uint64 into $var. Advance buffer with consumed bytes.
+     * @param $var.
+     */
+    public function readVarint64(&$var)
+    {
+        $count = 0;
+
+        if (PHP_INT_SIZE == 4) {
+            $high = 0;
+            $low = 0;
+            $b = 0;
+
+            do {
+                if ($this->current === $this->buffer_end) {
+                    return false;
+                }
+                if ($count === self::MAX_VARINT_BYTES) {
+                    return false;
+                }
+                $b = ord($this->buffer[$this->current]);
+                $bits = 7 * $count;
+                if ($bits >= 32) {
+                    $high |= (($b & 0x7F) << ($bits - 32));
+                } else if ($bits > 25){
+                    // $bits is 28 in this case.
+                    $low |= (($b & 0x7F) << 28);
+                    $high = ($b & 0x7F) >> 4;
+                } else {
+                    $low |= (($b & 0x7F) << $bits);
+                }
+
+                $this->advance(1);
+                $count += 1;
+            } while ($b & 0x80);
+
+            $var = GPBUtil::combineInt32ToInt64($high, $low);
+            if (bccomp($var, 0) < 0) {
+                $var = bcadd($var, "18446744073709551616");
+            }
+        } else {
+            $result = 0;
+            $shift = 0;
+
+            do {
+                if ($this->current === $this->buffer_end) {
+                    return false;
+                }
+                if ($count === self::MAX_VARINT_BYTES) {
+                    return false;
+                }
+
+                $byte = ord($this->buffer[$this->current]);
+                $result |= ($byte & 0x7f) << $shift;
+                $shift += 7;
+                $this->advance(1);
+                $count += 1;
+            } while ($byte > 0x7f);
+
+            $var = $result;
+        }
+
+        return true;
+    }
+
+    /**
+     * Read int into $var. If the result is larger than the largest integer, $var
+     * will be -1. Advance buffer with consumed bytes.
+     * @param $var.
+     */
+    public function readVarintSizeAsInt(&$var)
+    {
+        if (!$this->readVarint64($var)) {
+            return false;
+        }
+        $var = (int)$var;
+        return true;
+    }
+
+    /**
+     * Read 32-bit unsiged integer to $var. If the buffer has less than 4 bytes,
+     * return false. Advance buffer with consumed bytes.
+     * @param $var.
+     */
+    public function readLittleEndian32(&$var)
+    {
+        $data = null;
+        if (!$this->readRaw(4, $data)) {
+            return false;
+        }
+        $var = unpack('V', $data);
+        $var = $var[1];
+        return true;
+    }
+
+    /**
+     * Read 64-bit unsiged integer to $var. If the buffer has less than 8 bytes,
+     * return false. Advance buffer with consumed bytes.
+     * @param $var.
+     */
+    public function readLittleEndian64(&$var)
+    {
+        $data = null;
+        if (!$this->readRaw(4, $data)) {
+            return false;
+        }
+        $low = unpack('V', $data)[1];
+        if (!$this->readRaw(4, $data)) {
+            return false;
+        }
+        $high = unpack('V', $data)[1];
+        if (PHP_INT_SIZE == 4) {
+            $var = GPBUtil::combineInt32ToInt64($high, $low);
+        } else {
+            $var = ($high << 32) | $low;
+        }
+        return true;
+    }
+
+    /**
+     * Read tag into $var. Advance buffer with consumed bytes.
+     * @param $var.
+     */
+    public function readTag()
+    {
+        if ($this->current === $this->buffer_end) {
+            // Make sure that it failed due to EOF, not because we hit
+            // total_bytes_limit, which, unlike normal limits, is not a valid
+            // place to end a message.
+            $current_position = $this->total_bytes_read -
+                $this->buffer_size_after_limit;
+            if ($current_position >= $this->total_bytes_limit) {
+                // Hit total_bytes_limit_.  But if we also hit the normal limit,
+                // we're still OK.
+                $this->legitimate_message_end =
+                    ($this->current_limit === $this->total_bytes_limit);
+            } else {
+                $this->legitimate_message_end = true;
+            }
+            return 0;
+        }
+
+        $result = 0;
+        // The larget tag is 2^29 - 1, which can be represented by int32.
+        $success = $this->readVarint32($result);
+        if ($success) {
+            return $result;
+        } else {
+            return 0;
+        }
+    }
+
+    public function readRaw($size, &$buffer)
+    {
+        $current_buffer_size = 0;
+        if ($this->bufferSize() < $size) {
+            return false;
+        }
+
+        if ($size === 0) {
+          $buffer = "";
+        } else {
+          $buffer = substr($this->buffer, $this->current, $size);
+          $this->advance($size);
+        }
+
+        return true;
+    }
+
+    /* Places a limit on the number of bytes that the stream may read, starting
+     * from the current position.  Once the stream hits this limit, it will act
+     * like the end of the input has been reached until popLimit() is called.
+     *
+     * As the names imply, the stream conceptually has a stack of limits.  The
+     * shortest limit on the stack is always enforced, even if it is not the top
+     * limit.
+     *
+     * The value returned by pushLimit() is opaque to the caller, and must be
+     * passed unchanged to the corresponding call to popLimit().
+     *
+     * @param integer $byte_limit
+     * @throws \Exception Fail to push limit.
+     */
+    public function pushLimit($byte_limit)
+    {
+        // Current position relative to the beginning of the stream.
+        $current_position = $this->current();
+        $old_limit = $this->current_limit;
+
+        // security: byte_limit is possibly evil, so check for negative values
+        // and overflow.
+        if ($byte_limit >= 0 &&
+            $byte_limit <= PHP_INT_MAX - $current_position &&
+            $byte_limit <= $this->current_limit - $current_position) {
+            $this->current_limit = $current_position + $byte_limit;
+            $this->recomputeBufferLimits();
+        } else {
+            throw new GPBDecodeException("Fail to push limit.");
+        }
+
+        return $old_limit;
+    }
+
+    /* The limit passed in is actually the *old* limit, which we returned from
+     * PushLimit().
+     *
+     * @param integer $byte_limit
+     */
+    public function popLimit($byte_limit)
+    {
+        $this->current_limit = $byte_limit;
+        $this->recomputeBufferLimits();
+        // We may no longer be at a legitimate message end.  ReadTag() needs to
+        // be called again to find out.
+        $this->legitimate_message_end = false;
+    }
+
+    public function incrementRecursionDepthAndPushLimit(
+        $byte_limit, &$old_limit, &$recursion_budget)
+    {
+        $old_limit = $this->pushLimit($byte_limit);
+        $recursion_limit = --$this->recursion_limit;
+    }
+
+    public function decrementRecursionDepthAndPopLimit($byte_limit)
+    {
+        $result = $this->consumedEntireMessage();
+        $this->popLimit($byte_limit);
+        ++$this->recursion_budget;
+        return $result;
+    }
+
+    public function bytesUntilLimit()
+    {
+        if ($this->current_limit === PHP_INT_MAX) {
+            return -1;
+        }
+        return $this->current_limit - $this->current;
+    }
+}