diff --git a/lib/avro/datum.php b/lib/avro/datum.php index b328853..334a757 100644 --- a/lib/avro/datum.php +++ b/lib/avro/datum.php @@ -76,19 +76,24 @@ public static function encode_long($n): string { $n = (int) $n; $n = ($n << 1) ^ ($n >> 63); - $str = ''; + + if ($n >= 0 && $n < 0x80) { + return chr($n); + } + + $buf = []; if (($n & ~0x7F) != 0) { - $str .= chr(($n | 0x80) & 0xFF); - $n = self::unsigned_right_shift($n, 7); + $buf []= ($n | 0x80) & 0xFF; + $n = ($n >> 7) ^ (($n >> 63) << 57); // unsigned shift right ($n >>> 7) while ($n > 0x7F) { - $str .= chr(($n | 0x80) & 0xFF); - $n = self::unsigned_right_shift($n, 7); + $buf []= ($n | 0x80) & 0xFF; + $n >>= 7; // $n is always positive here } } - $str .= chr($n); - return $str; + $buf []= $n; + return pack("C*", ...$buf); } public static function decode_long(array $bytes): int { diff --git a/test/DatumIOTest.php b/test/DatumIOTest.php index a2086c1..dc9bd06 100644 --- a/test/DatumIOTest.php +++ b/test/DatumIOTest.php @@ -100,7 +100,13 @@ function data_provider() array('"long"', (int) -9223372036854775808, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), array('"long"', -(1<<62), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"), + array('"long"', -(1<<61), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"), array('"long"', -4294967295, "\xFD\xFF\xFF\xFF\x1F"), + array('"long"', -1<<24, "\xFF\xFF\xFF\x0F"), + array('"long"', -1<<16, "\xFF\xFF\x07"), + array('"long"', -255, "\xFD\x03"), + array('"long"', -128, "\xFF\x01"), + array('"long"', -127, "\xFD\x01"), array('"long"', -10, "\x13"), array('"long"', -3, "\005"), array('"long"', -2, "\003"), @@ -110,7 +116,13 @@ function data_provider() array('"long"', 2, "\004"), array('"long"', 3, "\006"), array('"long"', 10, "\x14"), + array('"long"', 127, "\xFE\x01"), + array('"long"', 128, "\x80\x02"), + array('"long"', 255, "\xFE\x03"), + array('"long"', 1<<16, "\x80\x80\x08"), + array('"long"', 1<<24, "\x80\x80\x80\x10"), array('"long"', 4294967295, "\xFE\xFF\xFF\xFF\x1F"), + array('"long"', 1<<61, "\x80\x80\x80\x80\x80\x80\x80\x80\x40"), array('"long"', 1<<62, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01"), array('"long"', 9223372036854775807, "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),