Files
php-react-protocol/src/Line/LineProtocol.php
Christopher Vagnetoft 62a1167055 Initial commit
2026-04-02 22:29:35 +02:00

65 lines
1.7 KiB
PHP

<?php
namespace NoccyLabs\React\Protocol\Line;
use Closure;
use NoccyLabs\React\Protocol\ProtocolInterface;
class LineProtocol implements ProtocolInterface
{
public function __construct(
private readonly string $lineBreak = "\n",
private readonly bool $quoteStrings = false,
private readonly bool $escapeSpecial = false,
private readonly ?Closure $beforePackCb = null,
private readonly ?Closure $afterPackCb = null,
private readonly ?Closure $beforeUnpackCb = null,
private readonly ?Closure $afterUnpackCb = null,
)
{
}
public function packFrame(array $frame): string
{
if (is_callable($this->beforePackCb))
$frame = call_user_func($this->beforePackCb, $frame);
if ($this->escapeSpecial) {
$frame = array_map(quotemeta(...), $frame);
}
if ($this->quoteStrings) {
$frame = array_map(fn($v) => is_string($v) ? ('"'.str_replace('"',"\\\"",$v).'"') : $v, $frame);
}
$data = join(" ", $frame);
$data .= $this->lineBreak;
if (is_callable($this->afterPackCb))
$data = call_user_func($this->afterPackCb, $data);
return $data;
}
public function unpackFrame(string $data): array
{
return str_getcsv($data, ' ', '"', "\\");
}
public function consumeFrame(string &$data): ?array
{
// check for $this->lineBreak
$p = strpos($data, $this->lineBreak);
if ($p === false) {
return null;
}
// break on separator
$frame = substr($data, 0, $p);
$data = substr($data, $p + strlen($this->lineBreak));
return $this->unpackFrame($frame);
}
}