generated from Nodarx/template
feat: initial version
Signed-off-by: Sebastian Krupinski <root@LAPTOP-7DVOR6NC>
This commit was merged in pull request #1.
This commit is contained in:
88
lib/Client/Protocol/ResponseHandler.php
Normal file
88
lib/Client/Protocol/ResponseHandler.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gricob\IMAP\Protocol;
|
||||
|
||||
use Generator;
|
||||
use Gricob\IMAP\Protocol\Response\Line\CommandContinuation;
|
||||
use Gricob\IMAP\Protocol\Response\Line\Line;
|
||||
use Gricob\IMAP\Protocol\Response\Line\Status\Status;
|
||||
use Gricob\IMAP\Protocol\Response\Line\Status\StatusType;
|
||||
use Gricob\IMAP\Protocol\Response\Parser\Parser;
|
||||
use Gricob\IMAP\Protocol\Response\Response;
|
||||
use Gricob\IMAP\Protocol\Response\ResponseBuilder;
|
||||
use Gricob\IMAP\Transport\ResponseStream;
|
||||
use RuntimeException;
|
||||
|
||||
readonly class ResponseHandler
|
||||
{
|
||||
public function __construct(private Parser $parser)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(string $statusTag, ResponseStream $stream, ContinuationHandler $continuationHandler): Response
|
||||
{
|
||||
$responseBuilder = new ResponseBuilder($statusTag);
|
||||
|
||||
do {
|
||||
$raw = $stream->readLine();
|
||||
while (preg_match('/\{(?<bytes>\d+)}\r\n$/', $raw, $matches)) {
|
||||
$raw .= $stream->read((int) $matches['bytes']);
|
||||
$raw .= $stream->readLine();
|
||||
}
|
||||
$line = $this->parser->parse($raw);
|
||||
|
||||
if ($line instanceof CommandContinuation) {
|
||||
$continuationHandler->continue();
|
||||
continue;
|
||||
}
|
||||
|
||||
$responseBuilder->addLine($line);
|
||||
} while (!$responseBuilder->hasStatus());
|
||||
|
||||
return $responseBuilder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams parsed response lines one at a time as a Generator, yielding each
|
||||
* untagged Line immediately as it arrives from the socket. The terminal
|
||||
* Status line is NOT yielded; instead it is set as the generator return
|
||||
* value so callers can retrieve it via $gen->getReturn() after exhaustion.
|
||||
*
|
||||
* @throws CommandFailed if the tagged status is NO or BAD
|
||||
*
|
||||
* @return Generator<int, Line, mixed, Status>
|
||||
*/
|
||||
public function stream(string $statusTag, ResponseStream $stream, ContinuationHandler $continuationHandler): Generator
|
||||
{
|
||||
$status = null;
|
||||
|
||||
do {
|
||||
$raw = $stream->readLine();
|
||||
while (preg_match('/\{(?<bytes>\d+)}\r\n$/', $raw, $matches)) {
|
||||
$raw .= $stream->read((int) $matches['bytes']);
|
||||
$raw .= $stream->readLine();
|
||||
}
|
||||
$line = $this->parser->parse($raw);
|
||||
|
||||
if ($line instanceof CommandContinuation) {
|
||||
$continuationHandler->continue();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($line instanceof Status && $line->tag === $statusTag) {
|
||||
$status = $line;
|
||||
break;
|
||||
}
|
||||
|
||||
yield $line;
|
||||
} while (true);
|
||||
|
||||
if ($status->type !== StatusType::OK) {
|
||||
throw CommandFailed::withStatus($status);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user