feat: speed improvements

Signed-off-by: Sebastian Krupinski <root@LAPTOP-7DVOR6NC>
This commit is contained in:
Sebastian Krupinski
2026-02-20 23:34:30 -05:00
committed by Sebastian Krupinski
parent 7889428a4c
commit 5dafcbd90d
2 changed files with 82 additions and 14 deletions

View File

@@ -33,22 +33,39 @@ use Gricob\IMAP\Protocol\Response\Line\Status\Code\UnseenCode;
use Gricob\IMAP\Protocol\Response\Line\Status\Status;
use Gricob\IMAP\Protocol\Response\Line\Status\StatusType;
readonly class Parser
class Parser
{
private Lexer $lexer;
/**
* Preloaded literal streams for the current parse() call.
* Populated by parse() when ResponseHandler has already read large
* literals into php://temp resources to keep them out of the lexer.
*
* @var list<resource>
*/
private array $literalStreams = [];
/** Sequential index into $literalStreams consumed by literal(). */
private int $nextLiteralIndex = 0;
public function __construct()
{
$this->lexer = new Lexer();
}
/**
* @param list<resource> $literalStreams Pre-extracted large literal streams
* (see ResponseHandler::readNextRaw).
* @throws ParseError
*/
public function parse(string $raw): Line
public function parse(string $raw, array $literalStreams = []): Line
{
$raw = $this->sanitizeInvalidEncoding($raw);
$this->literalStreams = $literalStreams;
$this->nextLiteralIndex = 0;
$this->lexer->setInput($raw);
$this->lexer->moveNext();
@@ -1076,6 +1093,15 @@ readonly class Parser
$this->getToken(TokenType::CLOSE_BRACES);
$this->getToken(TokenType::CRLF);
// If ResponseHandler preloaded this literal (because it was too large
// to tokenise safely), consume from the php://temp resource instead
// of reading token-by-token through the lexer.
if (isset($this->literalStreams[$this->nextLiteralIndex])) {
$resource = $this->literalStreams[$this->nextLiteralIndex++];
rewind($resource);
return (string) stream_get_contents($resource);
}
$value = '';
while (strlen($value) < $size) {
$value .= $this->getToken()->value;