• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

azjezz / psl / 23100354439

15 Mar 2026 01:10AM UTC coverage: 95.628% (-2.8%) from 98.421%
23100354439

Pull #629

github

azjezz
feat(encoding): introduce streaming IO handles for Base64, QuotedPrintable, and Hex

Signed-off-by: azjezz <azjezz@protonmail.com>
Pull Request #629: feat(encoding): introduce streaming IO handles for Base64, QuotedPrintable, and Hex

479 of 797 new or added lines in 13 files covered. (60.1%)

2 existing lines in 1 file now uncovered.

10455 of 10933 relevant lines covered (95.63%)

32.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.24
/src/Psl/Encoding/Base64/DecodingWriteHandle.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Psl\Encoding\Base64;
6

7
use Psl\Async\CancellationTokenInterface;
8
use Psl\Async\NullCancellationToken;
9
use Psl\Encoding\Exception;
10
use Psl\IO;
11

12
use function preg_replace;
13
use function strlen;
14
use function substr;
15

16
/**
17
 * A write handle that accepts base64-encoded bytes, strips whitespace,
18
 * buffers until 4-byte groups are available, decodes and writes to the inner handle.
19
 */
20
final class DecodingWriteHandle implements IO\WriteHandleInterface
21
{
22
    use IO\WriteHandleConvenienceMethodsTrait;
23

24
    private string $remainder = '';
25

26
    public function __construct(
27
        private readonly IO\WriteHandleInterface $handle,
28
        private readonly Variant $variant = Variant::Standard,
29
        private readonly bool $padding = true,
30
    ) {}
3✔
31

32
    /**
33
     * {@inheritDoc}
34
     */
35
    public function tryWrite(string $bytes): int
36
    {
37
        $length = strlen($bytes);
3✔
38

39
        /** @var string $bytes */
40
        $bytes = preg_replace('/\s+/', '', $bytes);
3✔
41
        $data = $this->remainder . $bytes;
3✔
42

43
        $data_length = strlen($data);
3✔
44
        $usable = $data_length - ($data_length % 4);
3✔
45

46
        if ($usable > 0) {
3✔
47
            $decoded = decode(substr($data, 0, $usable), $this->variant, $this->padding);
2✔
48
            $this->handle->writeAll($decoded);
2✔
49
            $this->remainder = substr($data, $usable);
2✔
50
        } else {
51
            $this->remainder = $data;
1✔
52
        }
53

54
        return $length;
3✔
55
    }
56

57
    /**
58
     * {@inheritDoc}
59
     */
60
    public function write(string $bytes, CancellationTokenInterface $cancellation = new NullCancellationToken()): int
61
    {
62
        return $this->tryWrite($bytes);
3✔
63
    }
64

65
    /**
66
     * Flush any remaining buffered base64 data through the decoder to the inner handle.
67
     *
68
     * @throws Exception\RangeException If the remaining bytes do not form valid base64.
69
     */
70
    public function flush(): void
71
    {
72
        if ($this->remainder !== '') {
3✔
73
            $decoded = decode($this->remainder, $this->variant, $this->padding);
1✔
NEW
74
            $this->remainder = '';
×
NEW
75
            $this->handle->writeAll($decoded);
×
76
        }
77
    }
78
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc