<?php class CompressionStream { private Closure $pumper; private Closure $finisher; private Closure $status; private function __construct( Closure $pumper, Closure $finisher, Closure $status ) { $this->pumper = $pumper; $this->finisher = $finisher; $this->status = $status; } public static function createInflater(): self { $context = inflate_init( ZLIB_ENCODING_DEFLATE ); return new self( function( string $chunk ) use ( $context ): string { $data = @inflate_add( $context, $chunk ); return $data === false ? '' : $data; }, function(): string { return ''; }, function() use ( $context ): bool { return inflate_get_status( $context ) === ZLIB_STREAM_END; } ); } public static function createDeflater(): self { $context = deflate_init( ZLIB_ENCODING_DEFLATE ); return new self( function( string $chunk ) use ( $context ): string { $data = deflate_add( $context, $chunk, ZLIB_NO_FLUSH ); return $data === false ? '' : $data; }, function() use ( $context ): string { $data = deflate_add( $context, '', ZLIB_FINISH ); return $data === false ? '' : $data; }, function(): bool { return false; } ); } public function pump( string $chunk ): string { return $chunk === '' ? '' : ($this->pumper)( $chunk ); } public function finish(): string { return ($this->finisher)(); } public function finished(): bool { return ($this->status)(); } }