lang/php/lib/Datum/AvroIOBinaryEncoder.php (83 lines of code) (raw):

<?php /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Apache\Avro\Datum; use Apache\Avro\Avro; use Apache\Avro\AvroGMP; use Apache\Avro\AvroIO; /** * Encodes and writes Avro data to an AvroIO object using * Avro binary encoding. * * @package Avro */ class AvroIOBinaryEncoder { /** * @var AvroIO */ private $io; /** * @param AvroIO $io object to which data is to be written. * */ public function __construct($io) { Avro::checkPlatform(); $this->io = $io; } /** * @param null $datum actual value is ignored */ public function writeNull($datum) { return null; } /** * @param boolean $datum */ public function writeBoolean($datum) { $byte = $datum ? chr(1) : chr(0); $this->write($byte); } /** * @param string $datum */ public function write($datum) { $this->io->write($datum); } /** * @param int $datum */ public function writeInt($datum) { $this->writeLong($datum); } /** * @param int $n */ public function writeLong($n) { if (Avro::usesGmp()) { $this->write(AvroGMP::encodeLong($n)); } else { $this->write(self::encodeLong($n)); } } /** * @param int|string $n * @returns string long $n encoded as bytes * @internal This relies on 64-bit PHP. */ public static function encodeLong($n) { $n = (int) $n; $n = ($n << 1) ^ ($n >> 63); if ($n >= 0 && $n < 0x80) { return chr($n); } $buf = []; if (($n & ~0x7F) != 0) { $buf[] = ($n | 0x80) & 0xFF; $n = ($n >> 7) ^ (($n >> 63) << 57); // unsigned shift right ($n >>> 7) while ($n > 0x7F) { $buf[] = ($n | 0x80) & 0xFF; $n >>= 7; // $n is always positive here } } $buf[] = $n; return pack("C*", ...$buf); } /** * @param float $datum * @uses self::floatToIntBits() */ public function writeFloat($datum) { $this->write(self::floatToIntBits($datum)); } /** * Performs encoding of the given float value to a binary string * * XXX: This is <b>not</b> endian-aware! The {@link Avro::checkPlatform()} * called in {@link AvroIOBinaryEncoder::__construct()} should ensure the * library is only used on little-endian platforms, which ensure the little-endian * encoding required by the Avro spec. * * @param float $float * @returns string bytes * @see Avro::checkPlatform() */ public static function floatToIntBits($float) { return pack('g', (float) $float); } /** * @param float $datum * @uses self::doubleToLongBits() */ public function writeDouble($datum) { $this->write(self::doubleToLongBits($datum)); } /** * Performs encoding of the given double value to a binary string * * XXX: This is <b>not</b> endian-aware! See comments in * {@link AvroIOBinaryEncoder::floatToIntBits()} for details. * * @param double $double * @returns string bytes */ public static function doubleToLongBits($double) { return pack('e', (double) $double); } /** * @param string $str * @uses self::writeBytes() */ public function writeString($str) { $this->writeBytes($str); } /** * @param string $bytes */ public function writeBytes($bytes) { $this->writeLong(strlen($bytes)); $this->write($bytes); } }