Skip to content

Commit

Permalink
Merge ea01c9a into 5d602c5
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Aug 22, 2019
2 parents 5d602c5 + ea01c9a commit 7981def
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 12 deletions.
9 changes: 9 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,14 @@
"platform": {
"php": "7.0.0"
}
},
"scripts": {
"check": [
"@cs",
"@test"
],
"cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
}
}
10 changes: 5 additions & 5 deletions examples/gzip-compress.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?php

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\ZlibOutputStream;
use Amp\Loop;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;

require __DIR__ . "/../vendor/autoload.php";
require __DIR__."/../vendor/autoload.php";

Loop::run(function () {
$stdin = new ResourceInputStream(STDIN);
$stdout = new ResourceOutputStream(STDOUT);
$stdin = getStdin();
$stdout = getStdout();

$gzout = new ZlibOutputStream($stdout, ZLIB_ENCODING_GZIP);

Expand Down
10 changes: 5 additions & 5 deletions examples/gzip-decompress.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?php

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\ZlibInputStream;
use Amp\Loop;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;

require __DIR__ . "/../vendor/autoload.php";
require __DIR__."/../vendor/autoload.php";

Loop::run(function () {
$stdin = new ResourceInputStream(STDIN);
$stdout = new ResourceOutputStream(STDOUT);
$stdin = getStdin();
$stdout = getStdout();

$gzin = new ZlibInputStream($stdin, ZLIB_ENCODING_GZIP);

Expand Down
18 changes: 18 additions & 0 deletions examples/readline-echo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\ZlibOutputStream;
use Amp\Loop;
use function Amp\ByteStream\bufferEcho;
use function Amp\ByteStream\readLine;

require __DIR__ . "/../vendor/autoload.php";

Loop::run(function () {
yield bufferEcho("Hello from async PHP!\n");
$question = yield readLine("What is your question? ");
yield bufferEcho("I see your question is $question.\n");
yield bufferEcho("\nUnfortunately, I'm just a small script and I can't answer that, feel free to contact us at #amphp on freenode though!\n\n");
yield bufferEcho("Bye!\n\n");
});
52 changes: 52 additions & 0 deletions lib/LineReader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Amp\ByteStream;

use Amp\Promise;
use function Amp\call;

final class LineReader
{
/** @var string */
private $buffer = "";

/** @var InputStream */
private $source;

public function __construct(InputStream $inputStream)
{
$this->source = $inputStream;
}

/**
* @return Promise<string|null>
*/
public function readLine(): Promise
{
return call(function () {
while (null !== $chunk = yield $this->source->read()) {
$this->buffer .= $chunk;

if (($pos = \strpos($this->buffer, "\n")) !== false) {
$line = \substr($this->buffer, 0, $pos);
$this->buffer = \substr($this->buffer, $pos + 1);
return \rtrim($line, "\r");
}
}

if ($this->buffer === "") {
return null;
}

if (($pos = \strpos($this->buffer, "\n")) !== false) {
$line = \substr($this->buffer, 0, $pos);
$this->buffer = \substr($this->buffer, $pos + 1);
return \rtrim($line, "\r");
}

$line = $this->buffer;
$this->buffer = "";
return \rtrim($line, "\r");
});
}
}
41 changes: 39 additions & 2 deletions lib/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function getInputBufferStream(): ResourceInputStream
$stream = Loop::getState($key);

if (!$stream) {
$stream = new ResourceInputStream(\fopen('php://input', 'rb'));
$stream = new ResourceInputStream(\fopen('php://input', 'r'));
Loop::setState($key, $stream);
}

Expand All @@ -93,7 +93,7 @@ function getOutputBufferStream(): ResourceOutputStream
$stream = Loop::getState($key);

if (!$stream) {
$stream = new ResourceOutputStream(\fopen('php://output', 'wb'));
$stream = new ResourceOutputStream(\fopen('php://output', 'w'));
Loop::setState($key, $stream);
}

Expand Down Expand Up @@ -155,3 +155,40 @@ function getStderr(): ResourceOutputStream

return $stream;
}


/**
* Buffered async readline function.
*
* @param string $prompt Optional prompt to print to console
*
* @return \Amp\Promise Will resolve with the read line
*/
function readLine(string $prompt = ''): Promise
{
return call(static function () use ($prompt) {
static $key = InputStream::class . '\\stdinLine';

$stream = Loop::getState($key);

if (!$stream) {
$stream = new LineReader(getStdin());
Loop::setState($key, $stream);
}
if ($prompt) {
yield getStdout()->write($prompt);
}
return $stream->readLine();
});
}

/**
* Simple wrapper function to asynchronously write a string to the PHP output buffer.
*
* @param string $string
* @return Promise
*/
function bufferEcho($string): Promise
{
return getOutputBufferStream()->write($string);
}
72 changes: 72 additions & 0 deletions test/LineReaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php /** @noinspection PhpUnhandledExceptionInspection */

namespace Amp\ByteStream;

use Amp\Iterator;
use Amp\PHPUnit\TestCase;
use function Amp\call;
use function Amp\Promise\wait;

class LineReaderTest extends TestCase
{
public function testSingleLine()
{
$this->check(["abc"], ["abc"]);
}

public function testMultiLineLf()
{
$this->check(["abc\nef"], ["abc", "ef"]);
}

public function testMultiLineCrLf()
{
$this->check(["abc\r\nef"], ["abc", "ef"]);
}

public function testMultiLineEmptyNewlineStart()
{
$this->check(["\r\nabc\r\nef\r\n"], ["", "abc", "ef"]);
}

public function testMultiLineEmptyNewlineEnd()
{
$this->check(["abc\r\nef\r\n"], ["abc", "ef"]);
}

public function testMultiLineEmptyNewlineMiddle()
{
$this->check(["abc\r\n\r\nef\r\n"], ["abc", "", "ef"]);
}

public function testEmpty()
{
$this->check([], []);
}

public function testEmptyCrLf()
{
$this->check(["\r\n"], [""]);
}

public function testMultiLineSlow()
{
$this->check(["a", "bc", "\r", "\n\r\nef\r", "\n"], ["abc", "", "ef"]);
}

private function check(array $chunks, array $expectedLines)
{
wait(call(static function () use ($chunks, $expectedLines) {
$inputStream = new IteratorStream(Iterator\fromIterable($chunks));

$reader = new LineReader($inputStream);
$lines = [];

while (null !== $line = yield $reader->readLine()) {
$lines[] = $line;
}

self::assertSame($expectedLines, $lines);
}));
}
}
20 changes: 20 additions & 0 deletions test/ResourceOutputStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Loop;
use PHPUnit\Framework\TestCase;
use function Amp\ByteStream\bufferEcho;
use function Amp\Promise\wait;

class ResourceOutputStreamTest extends TestCase
Expand Down Expand Up @@ -66,4 +68,22 @@ public function testClosedRemoteSocket()
wait($stream->write("foobar"));
wait($stream->write("foobar"));
}

public function testEcho()
{
Loop::run(function () {
$data = "\n".\base64_encode(\random_bytes(10))."\n";
$found = false;
\ob_start(static function ($match) use (&$found, $data) {
if ($match === $data) {
$found = true;
return '';
}
return $match;
});
yield bufferEcho($data);
\ob_end_flush();
$this->assertTrue($found, "Data wasn't sent to the output buffer");
});
}
}

0 comments on commit 7981def

Please sign in to comment.