<?php require_once __DIR__ . '/StreamReader.php'; interface CompressionStream { public function stream( StreamReader $stream, int $chunkSize = 8192 ): Generator; } class ZlibExtractorStream implements CompressionStream { public function stream( StreamReader $stream, int $chunkSize = 8192 ): Generator { $context = \inflate_init( \ZLIB_ENCODING_DEFLATE ); $done = false; while( !$done && !$stream->eof() ) { $chunk = $stream->read( $chunkSize ); $done = $chunk === ''; if( !$done ) { $before = \inflate_get_read_len( $context ); @\inflate_add( $context, $chunk ); $data = \substr( $chunk, 0, \inflate_get_read_len( $context ) - $before ); if( $data !== '' ) { yield $data; } $done = \inflate_get_status( $context ) === \ZLIB_STREAM_END; } } } } class ZlibInflaterStream implements CompressionStream { public function stream( StreamReader $stream, int $chunkSize = 8192 ): Generator { $context = \inflate_init( \ZLIB_ENCODING_DEFLATE ); $done = false; while( !$done && !$stream->eof() ) { $chunk = $stream->read( $chunkSize ); $done = $chunk === ''; if( !$done ) { $data = @\inflate_add( $context, $chunk ); if( $data !== false && $data !== '' ) { yield $data; } $done = \inflate_get_status( $context ) === \ZLIB_STREAM_END; } } } }