rfc:dedicated_stream_bucket

This is an old revision of the document!


Dedicated StreamBucket class

  • Date: 2024-01-19
  • Author: Máté Kocsis kocsismate@php.net
  • Status: Draft
  • Target: next minor version (possibly PHP 8.4)

Introduction

When using user filters for stream processing, one of the fundamental concepts is stream buckets. A stream bucket is effectively a chunk of stream which can be extracted from bucket brigades. Most probably, this metaphor comes from firefighting bucket brigades who pass buckets of water to each other, standing in a chain.

Back to our original topic, here is an example for a very basic stream filter:

class simple_filter extends php_user_filter {
    function filter($in, $out, &$consumed, $closing) {
        while ($bucket = stream_bucket_make_writeable($in)) {
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}
 
stream_filter_register("simple", "simple_filter")

Disclaimer: the example is copy-pasted from https://stackoverflow.com/questions/27103269/what-is-a-bucket-brigade. Courtesy of Bob for providing such an exceptional answer to explain the behavior of user stream filters.

$in and $out are the two sides of the stream bucket brigade: items come from the former one, and you have to pass them to the latter one. The stream_bucket_make_writeable() function can be used to get the bucket from the brigade, while the stream_bucket_new() function is used to create a new bucket.

Discussion

There are a few slightly unfortunate issues how stream buckets are handled which are discussed in the following sections.

Lack of a dedicated class

The original problem why this RFC is submitted is that there is no dedicated class for stream buckets: stream_bucket_make_writeable() and stream_bucket_new() create just stdClass instances and fill in their $bucket, $data, and $datalen properties on the go.

$bucket = stream_bucket_new(fopen('php://temp', 'w+'), '');
var_dump($bucket);
 
/*
object(stdClass)#1 (3) {
  ["bucket"]=>
  resource(7) of type (userfilter.bucket)
  ["data"]=>
  string(0) ""
  ["datalen"]=>
  int(0)
}
*/

As a consequence, their return type is no more specific than object. Similarly, the second parameters of the stream_bucket_append() and the stream_bucket_prepend() functions (which expect stream buckets) accept any kind of objects by checking the existence of the necessary properties.

If we had a dedicated class for stream buckets then the advantages were the usual: better feedback could be provided by static analysis tools, while autocomplete in IDEs worked out of the box. Additionally, by having typed properties for the $data and the $datalen properties, we could get additional safeguards.

The $bucket property

The $bucket property is a stream bucket resource which is about to be migrated to an object in a major PHP version as per Resource to object conversion. However, this property won't be useful anymore as soon as it becomes an object, since it can be inlined directly into the containing stream bucket class. Therefore, this RFC proposes to get rid of this property when the conversion happens. Until then, a deprecation is emitted in order to let people know about the planned change.

The $datalen property

The name of this property doesn't conform to the currently used naming conventions: we usually try to avoid abbreviations whenever possible (e.g. when the full name is not too verbose, and the abbreviation is not an extremely common term - like $id). Since the difference between len and length is just 3 characters, I don't think that using this abbreviation is really worth it. Therefore, this RFC proposes to add a $dataLength property.

Additionally, the $datalen property would become deprecated in favor of $dataLength in the subsequent minor or major version after the targeted version (possibly PHP 8.5 or PHP 9.0), and would be removed in the next to next major version (possibly PHP 10).

The proposed class

The final form of the proposed class is the following:

final class StreamBucket
{
    /**
     * @var resource
     * @deprecated
     */
    public $bucket;
    public string $data;
    /** @deprecated */
    public int $datalen;
    public int $dataLength;
}

Vote

The vote requires 2/3 majority in order to be accepted.

Primary vote

Add the StreamBucket class as proposed?
Real name yes no
alcaeus (alcaeus)  
asgrim (asgrim)  
brzuchal (brzuchal)  
crell (crell)  
dams (dams)  
derick (derick)  
devnexen (devnexen)  
ericmann (ericmann)  
galvao (galvao)  
gasolwu (gasolwu)  
kocsismate (kocsismate)  
mbeccati (mbeccati)  
mcmic (mcmic)  
nicolasgrekas (nicolasgrekas)  
nielsdos (nielsdos)  
petk (petk)  
reywob (reywob)  
saki (saki)  
sergey (sergey)  
svpernova09 (svpernova09)  
Final result: 20 0
This poll has been closed.
rfc/dedicated_stream_bucket.1705674021.txt.gz · Last modified: 2024/01/19 14:20 by kocsismate