1
0
Fork 0
mirror of https://github.com/shufflingpixels/php-io.git synced 2026-10-17 21:46:47 +02:00
php-io/README.md
Henrik Hautakoski 07ec405512 Adopt Go-style minimal interfaces for streams
Replace PSR-7 StreamInterface with a set of small, composable interfaces
(ReaderInterface, WriterInterface, SeekerInterface and their
combinations).
BinaryReader now depends only on ReaderInterface, BinaryWriter on
WriterInterface, making both easy to satisfy with any byte source or
sink.

Buffer and Resource are simplified — no capability flags, no
detach/close
lifecycle, no PSR-7 metadata methods. LimitedResource is replaced by
LimitedReader, a lightweight reader that enforces a byte count limit.
BinaryReader::read() is renamed to readExact() for clarity.

Tests updated throughout to match the new APIs.
2026-06-27 09:01:12 +02:00

177 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# php-io
A small, focused PHP I/O toolkit for working with streams and binary data.
`php-io` gives you:
- A minimal, Go-inspired interface hierarchy for byte streams
- In-memory and file-backed stream implementations
- `BinaryReader` and `BinaryWriter` for common integer formats (8/16/32-bit, LE/BE)
- Clear exception types for I/O failures
## Requirements
- PHP `>= 8.0`
## Installation
```bash
composer require shufflingpixels/php-io
```
## Quick Start
### Read binary values from an in-memory buffer
```php
<?php
use Shufflingpixels\IO\BinaryReader;
use Shufflingpixels\IO\Buffer;
$reader = new BinaryReader(new Buffer("\x34\x12\x80\xff"));
$a = $reader->readUInt16LE(); // 0x1234 => 4660
$b = $reader->readInt8(); // -128
$c = $reader->readInt8(); // -1
```
### Write binary values to a buffer
```php
<?php
use Shufflingpixels\IO\BinaryWriter;
use Shufflingpixels\IO\Buffer;
$buffer = new Buffer('');
$writer = new BinaryWriter($buffer);
$writer->writeUInt16LE(0x1234);
$writer->writeInt8(-1);
$buffer->seek(0);
$bytes = $buffer->read($buffer->length()); // "\x34\x12\xff"
```
### Seek and write in-place with a Buffer
```php
<?php
use Shufflingpixels\IO\Buffer;
$buffer = new Buffer('abcdef');
$buffer->seek(2);
$buffer->write('XY'); // data becomes: abXYef
$buffer->seek(-2, SEEK_END);
$tail = $buffer->read(2); // "ef"
```
### Open and use a file stream
```php
<?php
use Shufflingpixels\IO\File;
use Shufflingpixels\IO\FileMode;
$file = File::open('example.bin', FileMode::RW);
$file->write("ABC");
$file->seek(0);
$bytes = $file->read(3); // "ABC"
$file->close();
```
### Limit reads to a byte window
```php
<?php
use Shufflingpixels\IO\BinaryReader;
use Shufflingpixels\IO\Buffer;
use Shufflingpixels\IO\LimitedReader;
$buffer = new Buffer("header\x34\x12rest");
$buffer->seek(6); // skip header
$section = new LimitedReader($buffer, 2);
$reader = new BinaryReader($section);
$value = $reader->readUInt16LE(); // 0x1234 — cannot read past the 2-byte window
```
## Interfaces
`php-io` uses a minimal, composable interface hierarchy inspired by Go's `io` package.
Each interface adds exactly one capability.
| Interface | Methods |
|---|---|
| `ReaderInterface` | `read(int $length): string\|false` |
| `WriterInterface` | `write(string $data): int` |
| `SeekerInterface` | `seek()`, `tell()`, `eof()`, `length()` |
| `ReadSeekerInterface` | `ReaderInterface` + `SeekerInterface` |
| `WriteSeekerInterface` | `WriterInterface` + `SeekerInterface` |
| `ReadWriterInterface` | `ReaderInterface` + `WriterInterface` |
| `ReadWriteSeekerInterface` | `ReaderInterface` + `WriterInterface` + `SeekerInterface` |
`read()` returns `false` when the stream is at EOF.
## Implementations
| Class | Implements | Description |
|---|---|---|
| `Buffer` | `ReadWriteSeekerInterface` | In-memory stream backed by a PHP string |
| `Resource` | `ReadWriteSeekerInterface` | Base class wrapping a PHP file resource |
| `File` | `ReadWriteSeekerInterface` | File-backed stream opened via `FileMode` |
| `LimitedReader` | `ReaderInterface` | Limits reads to a fixed byte budget |
| `BinaryReader` | — | Typed binary reads over any `ReaderInterface` |
| `BinaryWriter` | — | Typed binary writes over any `WriterInterface` |
## BinaryReader methods
Integer names follow `read{Signedness}{Bits}{Endianness}`:
| Method | Size | Range |
|---|---|---|
| `readUInt8()` | 1 byte | 0–255 |
| `readInt8()` | 1 byte | −128–127 |
| `readUInt16LE()` / `readUInt16BE()` | 2 bytes | 0–65535 |
| `readInt16LE()` / `readInt16BE()` | 2 bytes | −32768–32767 |
| `readUInt32LE()` / `readUInt32BE()` | 4 bytes | 0–4294967295 |
| `readInt32LE()` / `readInt32BE()` | 4 bytes | −2147483648–2147483647 |
| `readPaddedString(int $length, string $pad_chars)` | `$length` bytes | strips trailing `$pad_chars` |
`readExact(int $length)` reads exactly `$length` bytes and throws `RuntimeException` if fewer are available.
## BinaryWriter methods
Integer names follow `write{Signedness}{Bits}{Endianness}`. All methods return bytes written.
| Method | Size |
|---|---|
| `writeUInt8()` / `writeInt8()` | 1 byte |
| `writeUInt16LE()` / `writeUInt16BE()` / `writeInt16LE()` / `writeInt16BE()` | 2 bytes |
| `writeUInt32LE()` / `writeUInt32BE()` / `writeInt32LE()` / `writeInt32BE()` | 4 bytes |
| `writePaddedString(string $data, int $length, string $pad_char)` | `$length` bytes |
## Exceptions
- `Shufflingpixels\IO\Exception\IOException` — generic stream/file I/O failures
- `Shufflingpixels\IO\Exception\EndOfStreamException` — subclass of `IOException`
## Running Tests
```bash
composer test
```
## License
AGPL-3.0