Completed
Push — master ( 633e0e...b839ec )
by thomas
35:09 queued 20:14
created

Parser::writeBytes()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 18
rs 9.2
cc 4
eloc 9
nc 6
nop 3
1
<?php
2
3
namespace BitWasp\Buffertools;
4
5
use BitWasp\Buffertools\Exceptions\ParserOutOfRange;
6
use Mdanter\Ecc\EccFactory;
7
use Mdanter\Ecc\Math\GmpMathInterface;
8
9
class Parser
10
{
11
    /**
12
     * @var string
13
     */
14
    private $string;
15
16
    /**
17
     * @var \Mdanter\Ecc\Math\GmpMathInterface
18
     */
19
    private $math;
20
21
    /**
22
     * @var int
23
     */
24
    private $position = 0;
25
26
    /**
27
     * Instantiate class, optionally taking Buffer or HEX.
28
     *
29
     * @param null|string|BufferInterface $input
30
     * @param GmpMathInterface|null $math
31
     */
32
    public function __construct($input = null, GmpMathInterface $math = null)
33
    {
34
        $this->math = $math ?: EccFactory::getAdapter();
35
36
        if (!$input instanceof BufferInterface) {
37
            $input = Buffer::hex($input, null, $this->math);
38
        }
39
40
        $this->string = $input->getBinary();
41
        $this->position = 0;
42
    }
43
44
    /**
45
     * Get the position pointer of the parser - ie, how many bytes from 0
46
     *
47
     * @return int
48
     */
49
    public function getPosition()
50
    {
51
        return $this->position;
52
    }
53
54
    /**
55
     * Parse $bytes bytes from the string, and return the obtained buffer
56
     *
57
     * @param  integer $bytes
58
     * @param  bool $flipBytes
59
     * @return Buffer
60
     * @throws \Exception
61
     */
62
    public function readBytes($bytes, $flipBytes = false)
63
    {
64
        $string = substr($this->string, $this->getPosition(), $bytes);
65
        $length = strlen($string);
66
67
        if ($length == 0) {
68
            throw new ParserOutOfRange('Could not parse string of required length (empty)');
69
        } elseif ($length < $bytes) {
70
            throw new ParserOutOfRange('Could not parse string of required length (too short)');
71
        }
72
73
        $this->position += $bytes;
74
75
        if ($flipBytes) {
76
            $string = Buffertools::flipBytes($string);
77
        }
78
79
        return new Buffer($string, $length, $this->math);
0 ignored issues
show
Bug introduced by
It seems like $string defined by \BitWasp\Buffertools\Buf...ols::flipBytes($string) on line 76 can also be of type object<BitWasp\Buffertools\Buffer>; however, BitWasp\Buffertools\Buffer::__construct() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
80
    }
81
82
    /**
83
     * Write $data as $bytes bytes. Can be flipped if needed.
84
     *
85
     * @param  integer $bytes
86
     * @param  $data
87
     * @param  bool $flipBytes
88
     * @return $this
89
     */
90
    public function writeBytes($bytes, $data, $flipBytes = false)
91
    {
92
        // Treat $data to ensure it's a buffer, with the correct size
93
        if ($data instanceof SerializableInterface) {
94
            $data = $data->getBuffer();
95
        }
96
97
        if (is_string($data)) {
98
            // Convert to a buffer
99
            $data = Buffer::hex($data, $bytes, $this->math);
100
        } else if (!($data instanceof BufferInterface)) {
101
            throw new \RuntimeException('Invalid data passed to Parser::writeBytes');
102
        }
103
104
        $this->writeBuffer($bytes, $data, $flipBytes);
105
106
        return $this;
107
    }
108
109
    /**
110
     * Write $data as $bytes bytes. Can be flipped if needed.
111
     *
112
     * @param  integer $bytes
113
     * @param  string $data
114
     * @param  bool $flipBytes
115
     * @return $this
116
     */
117
    public function writeRawBinary($bytes, $data, $flipBytes = false)
118
    {
119
        return $this->writeBuffer($bytes, new Buffer($data, $bytes), $flipBytes);
120
    }
121
122
    /**
123
     * @param BufferInterface $buffer
124
     * @param bool $flipBytes
125
     * @param int $bytes
126
     * @return $this
127
     */
128
    public function writeBuffer($bytes, BufferInterface $buffer, $flipBytes = false)
129
    {
130
        // only create a new buffer if the size does not match
131
        if ($buffer->getSize() != $bytes) {
132
            $buffer = new Buffer($buffer->getBinary(), $bytes, $this->math);
133
        }
134
135
        $this->appendBuffer($buffer, $flipBytes);
136
137
        return $this;
138
    }
139
140
    /**
141
     * @param BufferInterface $buffer
142
     * @param bool $flipBytes
143
     * @return $this
144
     */
145
    public function appendBuffer(BufferInterface $buffer, $flipBytes = false)
146
    {
147
        $this->appendBinary($buffer->getBinary(), $flipBytes);
148
        return $this;
149
    }
150
151
    /**
152
     * @param string $binary
153
     * @param bool $flipBytes
154
     * @return $this
155
     */
156
    public function appendBinary($binary, $flipBytes = false)
157
    {
158
        if ($flipBytes) {
159
            $binary = Buffertools::flipBytes($binary);
160
        }
161
162
        $this->string .= $binary;
163
        return $this;
164
    }
165
166
    /**
167
     * Take an array containing serializable objects.
168
     * @param SerializableInterface[]|Buffer[]
169
     * @return $this
170
     */
171
    public function writeArray($serializable)
172
    {
173
        $parser = new Parser(Buffertools::numToVarInt(count($serializable)), $this->math);
174
        foreach ($serializable as $object) {
175
            if ($object instanceof SerializableInterface) {
176
                $object = $object->getBuffer();
177
            }
178
179
            if ($object instanceof BufferInterface) {
180
                $parser->writeBytes($object->getSize(), $object);
181
            } else {
182
                throw new \RuntimeException('Input to writeArray must be Buffer[], or SerializableInterface[]');
183
            }
184
        }
185
186
        $this->string .= $parser->getBuffer()->getBinary();
187
188
        return $this;
189
    }
190
191
    /**
192
     * Return the string as a buffer
193
     *
194
     * @return BufferInterface
195
     */
196
    public function getBuffer()
197
    {
198
        return new Buffer($this->string, null, $this->math);
199
    }
200
}
201