data); $bytes = array_values($values !== false ? $values : []); $num = 0; $mult = 1; $len = count($bytes); while ($this->pos < $len) { $r = $bytes[$this->pos++]; // num = num | ((r & binary.BITS7) << len) $num = $num + ($r & 0b1111111) * $mult; $mult *= 128; if ($r <= 0b1111111) { return $num; } // Number.MAX_SAFE_INTEGER in JS if ($num > 9007199254740990) { throw new \OutOfBoundsException(); } } throw new InvalidArgumentException(); } public function getYjsMessageType(): int { $oldPos = $this->pos; $this->pos = 0; $messageType = $this->readVarUint(); $this->pos = $oldPos; return $messageType; } public function getYjsSyncType(): int { $oldPos = $this->pos; $this->pos = 0; $messageType = $this->readVarUint(); if ($messageType !== self::YJS_MESSAGE_SYNC) { throw new \ValueError('Message is not a sync message'); } $syncType = $this->readVarUint(); $this->pos = $oldPos; return $syncType; } /** * Based on https://github.com/yjs/y-protocols/blob/master/PROTOCOL.md#handling-read-only-users */ public function isUpdate(): bool { if ($this->getYjsMessageType() === self::YJS_MESSAGE_SYNC) { if (in_array($this->getYjsSyncType(), [self::YJS_MESSAGE_SYNC_STEP2, self::YJS_MESSAGE_SYNC_UPDATE])) { return true; } } return false; } }