Files
niro-gen5w/backend/php/NiroRawSnappy.php
T

63 lines
1.8 KiB
PHP

<?php
declare(strict_types=1);
/**
* Minimal raw Snappy encoder for the V038 native TFS decoder.
*
* The head unit advertises application/x-snappy-framed, but the native
* response path calls snappy::Uncompress on a raw Snappy block. Literal-only
* blocks are valid raw Snappy and avoid a platform extension dependency.
*/
final class NiroRawSnappy
{
public static function encodeLiteral(string $plain): string
{
$length = strlen($plain);
if ($length > 8 * 1024 * 1024) {
throw new InvalidArgumentException('Snappy input exceeds limit');
}
$encoded = self::varint($length);
$offset = 0;
while ($offset < $length) {
$chunkLength = min(65536, $length - $offset);
$encoded .= self::literalTag($chunkLength);
$encoded .= substr($plain, $offset, $chunkLength);
$offset += $chunkLength;
}
return $encoded;
}
private static function varint(int $value): string
{
$encoded = '';
do {
$byte = $value & 0x7f;
$value >>= 7;
if ($value !== 0) {
$byte |= 0x80;
}
$encoded .= chr($byte);
} while ($value !== 0);
return $encoded;
}
private static function literalTag(int $length): string
{
if ($length < 1 || $length > 65536) {
throw new InvalidArgumentException('Invalid Snappy literal length');
}
if ($length <= 60) {
return chr(($length - 1) << 2);
}
$value = $length - 1;
$bytes = '';
while ($value !== 0) {
$bytes .= chr($value & 0xff);
$value >>= 8;
}
return chr((59 + strlen($bytes)) << 2) . $bytes;
}
}