Completed
Pull Request — master (#54)
by thomas
25:27 queued 10:33
created

Buffertools::numToVarIntBin()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 1
1
<?php
2
3
namespace BitWasp\Buffertools;
4
5
class Buffertools
6
{
7
    public static function numToVarIntBin($decimal)
8
    {
9
        if ($decimal < 0xfd) {
10
            $bin = chr($decimal);
11
        } elseif ($decimal <= 0xffff) {
12
            // Uint16
13
            $bin = pack("Cv", 0xfd, $decimal);
14
        } elseif ($decimal <= 0xffffffff) {
15
            // Uint32
16
            $bin = pack("CV", 0xfe, $decimal);
17
        } else {
18
            // Todo, support for 64bit integers
19
            throw new \Exception('numToVarInt(): Integer too large');
20
        }
21
22
        return $bin;
23
    }
24
25
    /**
26
     * Convert a decimal number into a VarInt Buffer
27
     *
28
     * @param  integer $decimal
29
     * @return Buffer
30
     * @throws \Exception
31
     */
32
    public static function numToVarInt($decimal)
33
    {
34
        return new Buffer(static::numToVarIntBin($decimal));
35
    }
36
37
    /**
38
     * Flip byte order of this binary string. Accepts a string or Buffer,
39
     * and will return whatever type it was given.
40
     *
41
     * @param  string|BufferInterface $bytes
42
     * @return string|BufferInterface
43
     */
44
    public static function flipBytes($bytes)
45
    {
46
        $isBuffer = $bytes instanceof BufferInterface;
47
        if ($isBuffer) {
48
            $bytes = $bytes->getBinary();
49
        }
50
51
        $flipped = implode('', array_reverse(str_split($bytes, 1)));
52
        if ($isBuffer) {
53
            $flipped = new Buffer($flipped);
54
        }
55
56
        return $flipped;
57
    }
58
59
    /**
60
     * @param BufferInterface $buffer1
61
     * @param BufferInterface $buffer2
62
     * @param int    $size
63
     * @return BufferInterface
64
     */
65
    public static function concat(BufferInterface $buffer1, BufferInterface $buffer2, $size = null)
66
    {
67
        return new Buffer($buffer1->getBinary() . $buffer2->getBinary(), $size);
68
    }
69
70
    /**
71
     *  What if we don't have two buffers, or want to guard the types of the
72
     * sorting algorithm?
73
     *
74
     * The default behaviour should be, take a list of Buffers/SerializableInterfaces, and
75
     * sort their binary representation.
76
     *
77
     * If an anonymous function is provided, we completely defer the conversion of values to
78
     * Buffer to the $convertToBuffer callable.
79
     *
80
     * This is to allow anonymous functions which are responsible for converting the item to a buffer,
81
     * and which optionally type-hint the items in the array.
82
     *
83
     * @param array $items
84
     * @param callable $convertToBuffer
85
     * @return array
86
     */
87
    public static function sort(array $items, callable $convertToBuffer = null)
88
    {
89
        if (null == $convertToBuffer) {
90
            $convertToBuffer = function ($value) {
91
                if ($value instanceof BufferInterface) {
92
                    return $value;
93
                }
94
                if ($value instanceof SerializableInterface) {
95
                    return $value->getBuffer();
96
                }
97
                throw new \RuntimeException('Requested to sort unknown type');
98
            };
99
        }
100
101
        usort($items, function ($a, $b) use ($convertToBuffer) {
102
            $av = $convertToBuffer($a)->getBinary();
103
            $bv = $convertToBuffer($b)->getBinary();
104
            return $av == $bv ? 0 : $av > $bv ? 1 : -1;
105
        });
106
107
        return $items;
108
    }
109
}
110