Last active
October 15, 2019 21:27
-
-
Save azjezz/204575d521e68d8ed691934966fdbe35 to your computer and use it in GitHub Desktop.
MemoryHandle implementation. ( see hhvm/hsl-experimental#58 )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Nuxed\IO; | |
/* | |
* This file is part of the Nuxed package. | |
* | |
* (c) Saif Eddin Gmati <[email protected]> | |
* | |
* 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