Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  specify next release
  bump minimum version of psalm
  add Streams entrypoint
  remove unreachable null coalesce
  • Loading branch information
Baptouuuu committed Dec 4, 2022
2 parents 17a5bc8 + 3fa0aa3 commit ee6a55e
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 7 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog

## 3.3.0 - 2022-12-04

### Added

- `Innmind\Stream\Streams` to have a central point from where to open watch for streams

## 3.2.0 - 2022-03-19

### Added
Expand Down
12 changes: 7 additions & 5 deletions README.md
Expand Up @@ -17,10 +17,10 @@ composer require innmind/stream
File handling:

```php
use Innmind\Stream\Readable\Stream;
use Innmind\Stream\Streams;
use Innmind\Url\Path;

$file = Stream::open(Path::of('/some/path/to/a/file'));
$file = Streams::of()->readable()->open(Path::of('/some/path/to/a/file'));

while (!$file->end()) {
echo $file->readLine()->match(
Expand All @@ -40,13 +40,15 @@ Socket handling:
```php
use Innmind\Stream\{
Stream\Bidirectional,
Watch\Select,
Streams,
};
use Innmind\TimeContinuum\Earth\ElapsedPeriod;
use Innmind\Immutable\Either;

$socket = new Bidirectional(stream_socket_client('unix:///path/to/socket.sock'));
$select = Select::timeoutAfter(new ElapsedPeriod(60 * 1000)) // select with a 1 minute timeout
$socket = Bidirectional::of(\stream_socket_client('unix:///path/to/socket.sock'));
$select = Streams::of()
->watch()
->timeoutAfter(new ElapsedPeriod(60 * 1000)) // select with a 1 minute timeout
->forRead($socket);

do {
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -36,7 +36,7 @@
"require-dev": {
"phpunit/phpunit": "~9.0",
"symfony/process": "~6.0",
"vimeo/psalm": "^4.21",
"vimeo/psalm": "^4.30",
"nikic/php-parser": "^4.13.2",
"innmind/black-box": "^4.8",
"innmind/coding-standard": "~2.0"
Expand Down
36 changes: 36 additions & 0 deletions src/Streams.php
@@ -0,0 +1,36 @@
<?php
declare(strict_types = 1);

namespace Innmind\Stream;

final class Streams
{
private function __construct()
{
}

public static function of(): self
{
return new self;
}

public function temporary(): Streams\Temporary
{
return Streams\Temporary::of();
}

public function readable(): Streams\Readable
{
return Streams\Readable::of();
}

public function writable(): Streams\Writable
{
return Streams\Writable::of();
}

public function watch(): Streams\Watch
{
return Streams\Watch::of();
}
}
27 changes: 27 additions & 0 deletions src/Streams/Readable.php
@@ -0,0 +1,27 @@
<?php
declare(strict_types = 1);

namespace Innmind\Stream\Streams;

use Innmind\Stream\Readable as Read;
use Innmind\Url\Path;

final class Readable
{
private function __construct()
{
}

/**
* @internal
*/
public static function of(): self
{
return new self;
}

public function open(Path $path): Read
{
return Read\Stream::open($path);
}
}
29 changes: 29 additions & 0 deletions src/Streams/Temporary.php
@@ -0,0 +1,29 @@
<?php
declare(strict_types = 1);

namespace Innmind\Stream\Streams;

use Innmind\Stream\{
Bidirectional,
Stream,
};

final class Temporary
{
private function __construct()
{
}

/**
* @internal
*/
public static function of(): self
{
return new self;
}

public function new(): Bidirectional
{
return Stream\Bidirectional::of(\fopen('php://temp', 'r+'));
}
}
35 changes: 35 additions & 0 deletions src/Streams/Watch.php
@@ -0,0 +1,35 @@
<?php
declare(strict_types = 1);

namespace Innmind\Stream\Streams;

use Innmind\Stream\{
Watch as WatchInterface,
Watch\Select,
};
use Innmind\TimeContinuum\ElapsedPeriod;

final class Watch
{
private function __construct()
{
}

/**
* @internal
*/
public static function of(): self
{
return new self;
}

public function timeoutAfter(ElapsedPeriod $timeout): WatchInterface
{
return Select::timeoutAfter($timeout);
}

public function waitForever(): WatchInterface
{
return Select::waitForever();
}
}
27 changes: 27 additions & 0 deletions src/Streams/Writable.php
@@ -0,0 +1,27 @@
<?php
declare(strict_types = 1);

namespace Innmind\Stream\Streams;

use Innmind\Stream\Writable as Write;
use Innmind\Url\Path;

final class Writable
{
private function __construct()
{
}

/**
* @internal
*/
public static function of(): self
{
return new self;
}

public function open(Path $path): Write
{
return Write\Stream::of(\fopen($path->toString(), 'w'));
}
}
2 changes: 1 addition & 1 deletion src/Watch/Select.php
Expand Up @@ -93,7 +93,7 @@ public function __invoke(): Maybe
*/
$writable = $this
->write
->filter(static fn($resource) => \in_array($resource, $write ?? [], true))
->filter(static fn($resource) => \in_array($resource, $write, true))
->values()
->reduce(
Set::of(),
Expand Down
99 changes: 99 additions & 0 deletions tests/StreamsTest.php
@@ -0,0 +1,99 @@
<?php
declare(strict_types = 1);

namespace Tests\Innmind\Stream;

use Innmind\Stream\{
Streams,
Watch\Select,
};
use Innmind\TimeContinuum\Earth\ElapsedPeriod;
use Innmind\Url\Path;
use Innmind\Immutable\Str;
use PHPUnit\Framework\TestCase;

class StreamsTest extends TestCase
{
public function testOpeningATemporaryStreamAlwaysReturnANewOne()
{
$streams = Streams::of();
$a = $streams->temporary()->new()->write(Str::of('a'))->match(
static fn($a) => $a,
static fn() => null,
);
$b = $streams->temporary()->new()->write(Str::of('b'))->match(
static fn($a) => $a,
static fn() => null,
);

$this->assertNotNull($a);
$this->assertNotNull($b);
$this->assertNotSame($a, $b);
$this->assertSame(
'a',
$a->toString()->match(
static fn($string) => $string,
static fn() => null,
),
);
$this->assertSame(
'b',
$b->toString()->match(
static fn($string) => $string,
static fn() => null,
),
);
}

public function testOpenReadable()
{
$self = Streams::of()
->readable()
->open(Path::of(__FILE__))
->toString()
->match(
static fn($self) => $self,
static fn() => null,
);

$this->assertSame(\file_get_contents(__FILE__), $self);
}

public function testOpenWritable()
{
$path = Path::of(\tempnam(\sys_get_temp_dir(), 'streams'));
$streams = Streams::of();
$streams
->writable()
->open($path)
->write(Str::of('foo'));

$this->assertSame(
'foo',
$streams
->readable()
->open($path)
->toString()
->match(
static fn($string) => $string,
static fn() => null,
),
);
}

public function testWatch()
{
$this->assertInstanceOf(
Select::class,
Streams::of()
->watch()
->waitForever(),
);
$this->assertInstanceOf(
Select::class,
Streams::of()
->watch()
->timeoutAfter(new ElapsedPeriod(1)),
);
}
}

0 comments on commit ee6a55e

Please sign in to comment.