Encoding#

Changed in version 2.0: options array is replaced with named parameters

Note

Parameter order is not guaranteed for options, use named parameters

Scalars and arrays#

Changed in version 4.1: floats now throw an exception instead of becoming strings

<?php

use Arokettu\Bencode\Bencode;

// non sequential array will become a dictionary
$encoded = Bencode::encode([
    // sequential array will become a list
    'arr' => [1,2,3,4],
    // integer is stored as is
    'int' => 123,
    // true will be an integer 1
    'true' => true,
    // false and null values will be skipped
    'false' => false,
    // string can contain any binary data
    'string' => "test\0test",
]);
// "d" .
// "3:arr" . "l" . "i1e" . "i2e" . "i3e" . "i4e" . "e" .
// "3:int" . "i123e" .
// "6:string" . "9:test\0test" .
// "4:true" . "i1e" .
// "e"

Objects#

ArrayObject and stdClass#

Changed in version 3.0: Traversable objects no longer become dictionaries automatically

ArrayObject and stdClass become dictionaries:

<?php

use Arokettu\Bencode\Bencode;

$encoded = Bencode::encode(
    new ArrayObject([1,2,3])
); // "d1:0i1e1:1i2e1:2i3ee"

$std = new stdClass();
$std->a = '123';
$std->b = 456;
$encoded = Bencode::encode($std);
// "d1:a3:1231:bi456ee"

Big integer support#

Added in version 1.5/2.5: GMP support

Added in version 1.6/2.6: Pear’s Math_BigInteger, brick/math, BigIntType support

Added in version 4.3: BCMath support

Note

More in the decoding section

Note

BcMath\Number must represent an integer value (scale=0), decimal values will be rejected

GMP object, BCMath object, Pear’s Math_BigInteger, brick/math BigInteger, and internal type BigIntType (simple numeric string wrapper) will become integers:

<?php

use Arokettu\Bencode\Bencode;
use Arokettu\Bencode\Types\BigIntType;
use BcMath\Number;
use Brick\Math\BigInteger;

$encoded = Bencode::encode([
    'gmp' => gmp_pow(2, 96),
    'bcmath' => new Number(2)->pow(96),
    'brick' => BigInteger::of(2)->power(96),
    'pear' => (new Math_BigInteger(1))->bitwise_leftShift(96),
    'internal' => new BigIntType('7922816251426433759354395033'),
]); // "d6:bcmathi79228162514264337593543950336e5:bricki792..."

Stringable#

Changed in version 3.0: Stringable objects no longer become strings automatically

You can convert Stringable objects to strings using useStringable option:

<?php

use Arokettu\Bencode\Bencode;

class ToString
{
    public function __toString()
    {
        return 'I am string';
    }
}

$encoded = Bencode::encode(
    new ToString(),
    useStringable: true,
); // "11:I am string"

Object Wrappers#

Added in version 1.7/2.7/3.0: DictType

You can use any traversable as a list by wrapping it with ListType. Keys will be discarded in that case:

<?php

use Arokettu\Bencode\Bencode;
use Arokettu\Bencode\Types\ListType;

$encoded = Bencode::encode(
    new ListType(new ArrayObject([1,2,3]))
); // "li1ei2ei3ee"

You can use any traversable as a dictionary by wrapping it with DictType. Keys will be cast to string and must be unique:

<?php

use Arokettu\Bencode\Bencode;
use Arokettu\Bencode\Types\DictType;

$encoded = Bencode::encode(new DictType(
    (function () {
        yield 'key1' => 'value1';
        yield 'key2' => 'value2';
    })()
)); // "d4:key16:value14:key26:value2e"

BencodeSerializable#

Added in version 1.2.

Added in version 1.7/2.7/3.0: JsonSerializable handling

You can also force object representation by implementing BencodeSerializable interface. This will work exactly like JsonSerializable interface:

<?php

use Arokettu\Bencode\Bencode;
use Arokettu\Bencode\Types\BencodeSerializable;

class MyFile implements BencodeSerializable
{
    public function bencodeSerialize(): mixed
    {
        return [
            'class' => static::class,
            'name'  => 'myfile.torrent',
            'size'  => 5 * 1024 * 1024,
        ];
    }
}

$file = new MyFile;

$encoded = Bencode::encode($file);
// "d5:class6:MyFile4:name14:myfile.torrent4:sizei5242880ee"

Optionally you can use JsonSerializable itself too:

<?php

use Arokettu\Bencode\Bencode;

class MyFile implements JsonSerializable
{
    public function jsonSerialize()
    {
        return [
            'class' => static::class,
            'name'  => 'myfile.torrent',
            'size'  => 5 * 1024 * 1024,
        ];
    }
}

$file = new MyFile;

$encoded = Bencode::encode(
    $file,
    useJsonSerializable: true,
); // "d5:class6:MyFile4:name14:myfile.torrent4:sizei5242880ee"

Working with files#

Changed in version 3.0: ($filename, $data)($data, $filename)

Save data to file:

<?php

use Arokettu\Bencode\Bencode;

Bencode::dump($data, 'testfile.torrent');

Working with streams#

Added in version 1.5/2.5.

Save data to a writable stream or to a new php://temp if no stream is specified:

<?php

use Arokettu\Bencode\Bencode;

Bencode::encodeToStream($data, fopen('...', 'w'));

Encoder object#

Added in version 1.7/2.7/3.0.

Encoder object can be configured on creation and used multiple times:

<?php

use Arokettu\Bencode\Bencode;
use Arokettu\Bencode\Encoder;

$encoder = new Encoder(useStringable: true);
// all calls available:
$encoder->encode($data);
$encoder->encodeToStream($data, $stream);
$encoder->dump($data, $filename);