Skip to content

Instantly share code, notes, and snippets.

@azjezz
Last active October 15, 2019 21:27
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/204575d521e68d8ed691934966fdbe35 to your computer and use it in GitHub Desktop.
Save azjezz/204575d521e68d8ed691934966fdbe35 to your computer and use it in GitHub Desktop.
MemoryHandle implementation. ( see hhvm/hsl-experimental#58 )
namespace Nuxed\IO;
/*
* This file is part of the Nuxed package.
*
* (c) Saif Eddin Gmati <azjezz@protonmail.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use namespace HH\Lib\{Experimental\IO, Math, Str};
class MemoryHandle implements IO\NonDisposableReadWriteHandle {
private ?Awaitable<mixed> $lastOperation;
protected int $position = 0;
public function __construct(protected string $data = '') {}
final protected function queuedAsync<T>(
(function(): Awaitable<T>) $next,
): Awaitable<T> {
$last = $this->lastOperation;
$queue = async {
await $last;
return await $next();
};
$this->lastOperation = $queue;
return $queue;
}
/**
* Possibly write some of the string.
*
* Returns the number of bytes written, which may be 0.
*/
final public function rawWriteBlocking(string $bytes): int {
$length = Str\length($bytes);
$this->data = Str\splice($this->data, $bytes, $this->position);
$this->position += $length;
return $length;
}
final public async function writeAsync(string $bytes): Awaitable<void> {
await $this->queuedAsync(async () ==> $this->rawWriteBlocking($bytes));
}
final public function rawReadBlocking(?int $max_bytes = null): string {
if ($this->isEndOfFile()) {
return '';
}
$length = Str\length($this->data);
$bytes = Str\slice($this->data, $this->position, $max_bytes);
$postion = $this->position + Str\length($bytes);
$this->position = $postion > $length ? $length : $postion;
return $bytes;
}
final public async function readAsync(
?int $max_bytes = null,
): Awaitable<string> {
return await $this->queuedAsync(async () ==> {
return $this->rawReadBlocking($max_bytes);
});
}
final public async function readLineAsync(
?int $max_bytes = null,
): Awaitable<string> {
$eol = Str\search($this->data, "\n", $this->position);
if ($max_bytes is null) {
$read = $eol is null
? $this->readAsync()
: $this->readAsync($this->position - $eol);
return await $read;
}
if ($eol is null) {
return await $this->readAsync($max_bytes);
}
$length = Str\length($this->data);
$mb = $this->position + $max_bytes;
if ($mb > $length) {
$mb = $length;
}
$max_bytes = Math\minva($eol + 1, $mb);
return await $this->readAsync($max_bytes);
}
final public function isEndOfFile(): bool {
$length = Str\length($this->data);
return $this->position >= $length;
}
final public async function closeAsync(): Awaitable<void> {
// do nothing.
}
final public async function flushAsync(): Awaitable<void> {
// do nothing.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment