Skip to content

Releases: azjezz/psl

Crown 5.5.0

12 Mar 20:23
8534d06

Choose a tag to compare

PSL 5.5.0

IO: Bounded Reads

Reader::readUntilBounded() reads from a handle until a suffix is found, just like readUntil(), but enforces a maximum byte limit. If the suffix is not encountered within $max_bytes, an IO\Exception\OverflowException is thrown.

This is essential when reading from untrusted sources. for example, capping HTTP header lines so a malicious client cannot exhaust memory by sending an endless line:

use Psl\IO;

$reader = new IO\Reader($connection);

// Read a header line, but never buffer more than 8KB
$line = $reader->readUntilBounded("\r\n", max_bytes: 8192);

Type: Type\json_decoded() and Type\nullish()

Two new type coercions from @veewee:

  • Type\json_decoded(TypeInterface $inner): accepts a JSON string and transparently decodes it, then coerces the result through $inner. Useful for APIs and form fields that pass structured data as JSON strings.

  • Type\nullish(TypeInterface $inner): matches null, the absence of a key (for shape fields), and the inner type. Ideal for optional-and-nullable shape fields where "missing" and "null" should be treated the same.


Documentation: psl.carthage.software/ | IO | Type


Full Changelog: 5.4.0...5.5.0

Crown 5.4.0

10 Mar 20:54
6ac0675

Choose a tag to compare

PSL 5.4.0

TCP: Backlog Configuration and Batch Accept

TCP\listen() now accepts a backlog parameter (default 512) to configure the OS-level queue of pending connections. The listener also now drains the accept backlog in a loop instead of accepting one connection per event-loop tick, dramatically improving throughput under high connection rates.

use Psl\TCP;

$listener = TCP\listen('127.0.0.1', 8080, backlog: 4096);

New: Dict\{filter_nonnull_by, map_nonnull}, Vec\{filter_nonnull_by, map_nonnull}

New collection helpers for filtering and mapping with null-awareness.


Documentation: psl.carthage.software/ | TCP


New Contributors

Full Changelog: 5.3.0...5.4.0

Crown 5.3.0

08 Mar 20:32
16350e2

Choose a tag to compare

PSL 5.3.0

New: IO\spool()

Create a handle that writes to memory until a threshold is reached, then transparently spills to a temporary file on disk. Useful for buffering data of unknown size without risking excessive memory usage.

use Psl\IO;

$handle = IO\spool(); // default 2MB threshold
$handle->writeAll($data);
$handle->seek(0);
$contents = $handle->readAll();
$handle->close();

// Custom threshold: spool to disk after 64 bytes
$small = IO\spool(maxMemory: 64);

The returned handle implements CloseHandleInterface, SeekHandleInterface, ReadHandleInterface, WriteHandleInterface, and StreamHandleInterface.


Documentation: psl.carthage.software/5.3.0/ | IO


Full Changelog: 5.2.0...5.3.0

Crown 5.2.0

07 Mar 03:54
98ec362

Choose a tag to compare

PSL 5.2.0

New: IP Component

Immutable, binary-backed value object for IPv4 and IPv6 addresses. Parse, classify, compare, and format IP addresses with a clean API.

use Psl\IP\Address;

$addr = Address::parse('192.168.1.1');
$addr->family;            // Family::V4
$addr->isPrivate();       // true
$addr->isGlobalUnicast(); // false
$addr->toArpaName();      // '1.1.168.192.in-addr.arpa'

$v6 = Address::v6('2001:db8::1');
$v6->toString();         // '2001:db8::1'
$v6->toExpandedString(); // '2001:0db8:0000:0000:0000:0000:0000:0001'

Improved: CIDR\Block::contains()

Block::contains() now accepts string|IP\Address:

use Psl\CIDR\Block;
use Psl\IP\Address;

$block = new Block('192.168.1.0/24');
$block->contains(Address::v4('192.168.1.100')); // true

Documentation: psl.carthage.software/5.2.0/ | IP | CIDR


Full Changelog: 5.1.0...5.2.0

Crown 5.1.0

05 Mar 16:05
18af163

Choose a tag to compare

PSL - Crown 5.1.0

Features

  • TLS connection pooling: New TLS\TCPConnector implements TCP\ConnectorInterface, enabling TLS connections to be pooled via TCP\SocketPool. Pass a TCPConnector to SocketPool and get automatic connection reuse without repeated TLS handshakes.
  • TLS\StreamInterface now extends TCP\StreamInterface, making TLS streams compatible with any API that accepts TCP streams.

Example

$pool = new TCP\SocketPool(
  new TLS\TCPConnector(
    new TCP\Connector(),
    new TLS\Connector($config),
  ),
);

$stream = $pool->checkout('example.com', 443);
// ... use stream ...
$pool->checkin($stream);

// Next checkout reuses the TLS connection
$stream = $pool->checkout('example.com', 443);

Full Changelog: 5.0.0...5.1.0

Crown 5.0.0

04 Mar 21:43
1bdb8ba

Choose a tag to compare

PSL - Crown 5.0

PSL 5.0 - nicknamed Crown - is the biggest release of the PHP Standard Library to date, introducing 10 new components, a complete networking stack rewrite, and significant performance improvements across the board.

Requires PHP 8.4+.

Crypto

Full-featured cryptography built on libsodium: symmetric and asymmetric encryption, digital signatures, AEAD, key derivation (KDF, HKDF), key exchange, and stream ciphers, all with a type-safe, hard-to-misuse API.

use Psl\Crypto\Symmetric;

$key = Symmetric\generate_key();
$ciphertext = Symmetric\seal('Hello, World!', $key);
$plaintext = Symmetric\open($ciphertext, $key);
// 'Hello, World!'
use Psl\Crypto\Signing;

$keyPair = Signing\generate_key_pair();
$signature = Signing\sign('This message is authentic.', $keyPair->secretKey);
$valid = Signing\verify($signature, 'This message is authentic.', $keyPair->publicKey);
// true

Binary

Structured binary data parsing and encoding with a fluent Reader/Writer API. Read and write integers, floats, and strings in any byte order. Ideal for building protocol parsers and working with binary formats.

use Psl\Binary\{Reader, Writer, Endianness};

$data = new Writer(endianness: Endianness::Big)
    ->u8(1)           // version
    ->u16(0x0042)     // type
    ->u32(5)          // payload length
    ->bytes('Hello')  // payload
    ->toString();

$reader = new Reader($data, Endianness::Big);
$version = $reader->u8();      // 1
$type    = $reader->u16();     // 0x0042
$length  = $reader->u32();     // 5
$payload = $reader->bytes($length); // 'Hello'

Networking Stack Rewrite

The Network, TCP, TLS, UDP, Unix, CIDR, and Socks components were rewritten from scratch with connection pooling, retry logic, socket pairs, and first-class TLS support.

use Psl\TCP;

$listener = TCP\listen('127.0.0.1');
$connection = $listener->accept();
$data = $connection->readAll();
$connection->writeAll($data);
use Psl\TLS;

$tls = TLS\connect('example.com', 443);
$tls->writeAll("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
$tls->shutdown();
$response = $tls->readAll();
use Psl\CIDR;

$block = new CIDR\Block('192.168.1.0/24');
$block->contains('192.168.1.100'); // true
$block->contains('192.168.2.1');   // false

Process

Async process management with non-blocking I/O, inspired by Rust's Command API. A safer, higher-level replacement for proc_open and friends. Psl\Shell\execute is now powered by it under the hood.

use Psl\Process\Command;

$output = Command::create('echo')
    ->withArguments(['Hello', 'from', 'process'])
    ->output();

if ($output->status->isSuccessful()) {
    $output->stdout; // 'Hello from process'
}

Terminal & Ansi

A full terminal UI framework: buffered rendering, layouts, widgets, keyboard/mouse event handling, and ANSI styling. Build rich interactive TUI applications entirely in PHP.

use Psl\Async;
use Psl\Terminal;
use Psl\Terminal\{Event, Widget};

Async\main(static function (): int {
    $app = Terminal\Application::create(new MyState(), title: 'My App');

    $app->on(Event\Key::class, static function (Event\Key $event) use ($app): void {
        if ($event->is('ctrl+c')) {
            $app->stop();
        }
    });

    return $app->run(static function (Terminal\Frame $frame, MyState $state): void {
        Widget\Paragraph::new([
            Widget\Line::new([Widget\Span::raw('Hello, World!')]),
        ])->render($frame->rect(), $frame->buffer());
    });
});

Here's a system monitor UI demo built entirely with Psl\Terminal (source):

system-monitor

You can even build fully functional terminal games (source):

snake

DateTime Additions

New Period and Interval types for representing and manipulating durations and time spans.

use Psl\DateTime;

$period = DateTime\Period::fromParts(years: 1, months: 6, days: 15);
$period->toIso8601(); // 'P1Y6M15D'

$start = DateTime\DateTime::fromParts(DateTime\Timezone::UTC, 2024, 3, 15);
$end = DateTime\DateTime::fromParts(DateTime\Timezone::UTC, 2025, 7, 20);
$between = DateTime\Period::between($start, $end);
// 1 year(s), 4 month(s), 5 day(s)

Performance

Optimizations across Vec, Dict, Str, Iter, Type, and more components. Benchmarks show up to 100% improvement in certain functions.

Documentation

A new documentation website is available at psl.carthage.software.

Breaking Changes

  • PHP 8.4 is now the minimum required version
  • Complete networking stack rewrite (Network, TCP, Unix)
  • Psl\Env\temp_dir() now always returns a canonicalized path
  • Filesystem\create_temporary_file() now canonicalizes the temporary directory path
  • Migrated to PHPUnit 13

Bug Fixes

  • Vec\range() now uses strict comparison for float precision

Documentation: https://psl.carthage.software/


Full Changelog: 4.3.0...5.0.0

Noise 4.3.0

24 Feb 01:59
74c95be

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 4.2.1...4.3.0

Noise 4.2.1

04 Feb 07:33
4.2.1
28c6752

Choose a tag to compare

What's Changed

Full Changelog: 4.2.0...4.2.1

Noise 4.2.0

30 Oct 15:28
4.2.0
15153a6

Choose a tag to compare

What's Changed

Full Changelog: 4.1.0...4.2.0

Noise 4.1.0

23 Oct 11:54
4.1.0
8b96289

Choose a tag to compare

Psl Noise - 4.1.0

This release introduces two major new data structure components to the PHP Standard Library: Tree and Graph. These additions bring powerful hierarchical and relational data manipulation tools to PHP developers with PSL's signature type-safe API.

What's Changed

  • chore: upgrade to mago beta-31 by @azjezz in #538
  • chore: upgrade to mago beta-32 by @azjezz in #539
  • feat: add reflection-based type functions for class members by @azjezz in #543
  • chore: migrate from make to just by @azjezz in #544
  • chore(ga): bump extractions/setup-just from 2 to 3 by @dependabot[bot] in #545
  • feat: add Tree component for hierarchical data structures by @azjezz in #546
  • feat: add Graph component with directed and undirected graph support by @azjezz in #547
  • chore: add veewee to GitHub sponsors by @azjezz in #548

✨ New Features

🌳 Psl\Tree Component

A comprehensive tree data structure implementation for working with hierarchical data.

Features: Immutable tree nodes, functional operations (map, filter, reduce, fold), traversal algorithms (pre-order, post-order, level-order), search utilities, and conversion functions.

use Psl\Tree;

// Create and manipulate trees
$tree = Tree\tree('root', [
    Tree\leaf('child1'),
    Tree\tree('child2', [Tree\leaf('grandchild')]),
]);

// Functional operations
$doubled = Tree\map($tree, fn($x) => $x . '!');
$values = Tree\pre_order($tree); // ['root', 'child1', 'child2', 'grandchild']
$count = Tree\count($tree); // 4

// Build from database records
$tree = Tree\from_list(
    $records,
    fn($r) => $r['id'],
    fn($r) => $r['parent_id'],
    fn($r) => $r['name']
);

Use Cases: File systems, organizational hierarchies, DOM structures, category trees, menu systems.

Full Documentation


🕸️ Psl\Graph Component

A robust graph data structure implementation supporting both directed and undirected graphs with algorithms for analysis and pathfinding.

Features: Immutable graphs, weighted/unweighted edges, BFS/DFS traversal, shortest path (Dijkstra/BFS), topological sorting, cycle detection, flexible node types.

use Psl\Graph;

// Create and traverse graphs
$graph = Graph\directed();
$graph = Graph\add_edge($graph, 'A', 'B');
$graph = Graph\add_edge($graph, 'B', 'C');

$path = Graph\shortest_path($graph, 'A', 'C'); // ['A', 'B', 'C']
$sorted = Graph\topological_sort($graph); // ['A', 'B', 'C']

// Weighted graphs
$graph = Graph\add_edge($graph, 'NYC', 'Boston', 215);
$graph = Graph\add_edge($graph, 'NYC', 'Philadelphia', 95);
$graph = Graph\add_edge($graph, 'Philadelphia', 'Boston', 310);
$route = Graph\shortest_path($graph, 'NYC', 'Boston'); // ['NYC', 'Boston']

// Undirected graphs
$social = Graph\undirected();
$social = Graph\add_edge($social, 'Alice', 'Bob');

Use Cases: Dependency resolution, route finding, social networks, state machines, task scheduling.

Full Documentation


🔍 Reflection-Based Type Functions

New type functions for runtime validation of class members using PHP's reflection API:

  • Type\constant_name_of() - Validate constant names
  • Type\enum_case_of() - Validate enum case names
  • Type\method_name_of() - Validate method names (case-insensitive)
  • Type\property_name_of() - Validate property names

Each includes visibility-specific variants (public_*, protected_*, private_*).

use Psl\Type;

Type\method_name_of(MyClass::class)->assert('someMethod');
Type\property_name_of(MyClass::class)->assert('someProperty');
Type\public_constant_name_of(MyClass::class)->assert('SOME_CONSTANT');

Full Documentation


🛠️ Tooling Updates

  • Migration to just: Migrated from make to just for improved cross-platform compatibility and developer experience

⬆️ Dependency Updates

  • mago updated to 1.0.0-beta.32
  • actions/setup-just bumped from v2 to v3
  • Various development dependency updates

🤝 Contributors

@veewee has been added to GitHub sponsors

Full Changelog: 4.0.1...4.1.0