Skip to content

Instantly share code, notes, and snippets.

@azjezz
Created October 24, 2019 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azjezz/bdbe3f887af9551344753c4cbb039b2b to your computer and use it in GitHub Desktop.
Save azjezz/bdbe3f887af9551344753c4cbb039b2b to your computer and use it in GitHub Desktop.
<<__ReturnDisposable>>
function closeOnScopeExit<<<__Enforceable>> reify T as Mode>(
Handle<T> $handle,
): DisposableHandle<T> {
return new DisposableHandle<T>($handle);
}
final class DisposableHandle<<<__Enforceable>> reify T as Mode>
implements Handle<T>, \IAsyncDisposable {
public function __construct(private Handle<T> $impl) {}
public function readAsync(
?int $max_bytes = null,
): Awaitable<string> where T as Read {
return $this->impl->readAsync($max_bytes);
}
public function readLineAsync(
?int $max_bytes = null,
): Awaitable<string> where T as Read {
return $this->impl->readLineAsync($max_bytes);
}
public function readRawBlocking(
?int $max_bytes = null,
): string where T as Read {
return $this->impl->readRawBlocking($max_bytes);
}
public function writeAsync(
string $content,
): Awaitable<void> where T as Write {
return $this->impl->writeAsync($content);
}
public function writeRawBlocking(string $content): int where T as Write {
return $this->impl->writeRawBlocking($content);
}
public function flushAsync(): Awaitable<void> where T as Write {
return $this->impl->flushAsync();
}
public function seekAsync(
int $position,
): Awaitable<void> where T as Seekable {
return $this->impl->seekAsync($position);
}
public function tell(): int where T as Seekable {
return $this->impl->tell();
}
public function isEndOfFile(): bool {
return $this->impl->isEndOfFile();
}
public function closeAsync(): Awaitable<void> {
return $this->impl->closeAsync();
}
/**
* This method is invoked exactly once at the end of the scope of the
* await using statement, unless the program terminates with a fatal error.
*/
public function __disposeAsync(): Awaitable<void> {
return $this->closeAsync();
}
}
async function emit(
Handle<SeekableRead> $response,
Handle<Write> $output,
int $bytes = 8420,
): Awaitable<void> {
await using ($response = closeOnScopeExit<SeekableRead>($response)) {
await using ($output = closeOnScopeExit<Write>($output)) {
await $response->seekAsync(0);
while (!$response->isEndOfFile()) {
$content = await $response->readAsync($bytes);
await $output->writeAsync($content);
}
await $output->flushAsync();
}
}
}
interface Handle<<<__Enforceable>> T as Mode> {
// ReadHandle methods
public function readAsync(
?int $max_bytes = null,
): Awaitable<string> where T as Read ;
public function readLineAsync(
?int $max_bytes = null,
): Awaitable<string> where T as Read ;
public function readRawBlocking(
?int $max_bytes = null,
): string where T as Read ;
// WriteHandle methods
public function writeAsync(
string $content,
): Awaitable<void> where T as Write ;
public function writeRawBlocking(string $content): int where T as Write ;
public function flushAsync(): Awaitable<void> where T as Write ;
// SeekableHandle methods
public function seekAsync(
int $position,
): Awaitable<void> where T as Seekable ;
public function tell(): int where T as Seekable ;
// Base methods
public function isEndOfFile(): bool;
public function closeAsync(): Awaitable<void>;
}
<<__Sealed(Read::class, Write::class, Seekable::class)>>
interface Mode {}
// Seekable
<<__Sealed(SeekableRead::class, SeekableWrite::class)>>
interface Seekable extends Mode {}
// Read
<<__Sealed(ReadWrite::class, SeekableRead::class)>>
interface Read extends Mode {}
<<__Sealed(SeekableReadWrite::class)>>
interface SeekableRead extends Read, Seekable {}
// Write
<<__Sealed(ReadWrite::class, SeekableWrite::class)>>
interface Write extends Mode {}
<<__Sealed(SeekableReadWrite::class)>>
interface SeekableWrite extends Write, Seekable {}
// Read + Write
<<__Sealed(SeekableReadWrite::class)>>
interface ReadWrite extends Read, Write {}
<<__Sealed()>>
/*final */interface SeekableReadWrite
extends SeekableWrite, SeekableRead, ReadWrite {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment