Completed
Pull Request — master (#30)
by Eugene
07:16
created

BufferUnpacker::extendWith()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 5
cts 7
cp 0.7143
rs 9.8333
c 0
b 0
f 0
cc 3
nc 2
nop 2
crap 3.2098
1
<?php
2
3
/*
4
 * This file is part of the rybakit/msgpack.php package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace MessagePack;
13
14
use MessagePack\Exception\InsufficientDataException;
15
use MessagePack\Exception\IntegerOverflowException;
16
use MessagePack\Exception\InvalidOptionException;
17
use MessagePack\Exception\UnpackingFailedException;
18
use MessagePack\TypeTransformer\CanUnpackExt;
19
20
class BufferUnpacker
21
{
22
    private $buffer;
23
    private $offset = 0;
24
    private $isBigIntAsStr;
25
    private $isBigIntAsGmp;
26
27
    /**
28
     * @var CanUnpackExt[]
29
     */
30
    private $transformers = [];
31
32
    /**
33
     * @param string $buffer
34
     * @param UnpackOptions|int|null $options
35
     * @param CanUnpackExt[] $transformers
36
     *
37
     * @throws InvalidOptionException
38
     */
39 242
    public function __construct(string $buffer = '', $options = null, array $transformers = [])
40
    {
41 242
        if (null === $options) {
42 241
            $options = UnpackOptions::fromDefaults();
43 8
        } elseif (!$options instanceof PackOptions) {
44 8
            $options = UnpackOptions::fromBitmask($options);
0 ignored issues
show
Bug introduced by
It seems like $options can also be of type object<MessagePack\UnpackOptions>; however, MessagePack\UnpackOptions::fromBitmask() does only seem to accept integer, 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...
45
        }
46
47 242
        $this->isBigIntAsStr = $options->isBigIntAsStrMode();
48 242
        $this->isBigIntAsGmp = $options->isBigIntAsGmpMode();
49
50 242
        $this->buffer = $buffer;
51
52 242
        if ([] !== $transformers) {
53
            $this->transformers = $transformers;
54
        }
55 242
    }
56
57 1
    public function extendWith(CanUnpackExt $transformer, CanUnpackExt ...$transformers) : self
58
    {
59 1
        $new = clone $this;
60 1
        $new->transformers[$transformer->getType()] = $transformer;
61
62 1
        if ([] !== $transformers) {
63
            foreach ($transformers as $t) {
64
                $new->transformers[$t->getType()] = $t;
65
            }
66
        }
67
68 1
        return $new;
69
    }
70
71 10
    public function append(string $data) : self
72
    {
73 10
        $this->buffer .= $data;
74
75 10
        return $this;
76
    }
77
78 215
    public function reset(string $buffer = '') : self
79
    {
80 215
        $this->buffer = $buffer;
81 215
        $this->offset = 0;
82
83 215
        return $this;
84
    }
85
86 3 View Code Duplication
    public function seek(int $offset) : self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
    {
88 3
        if ($offset < 0) {
89 1
            $offset += \strlen($this->buffer);
90
        }
91
92 3
        if (!isset($this->buffer[$offset])) {
93 1
            throw new \OutOfBoundsException("Unable to seek to position $offset.");
94
        }
95
96 2
        $this->offset = $offset;
97
98 2
        return $this;
99
    }
100
101 2 View Code Duplication
    public function skip(int $offset) : self
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102
    {
103 2
        $offset += $this->offset;
104
105 2
        if (!isset($this->buffer[$offset])) {
106 1
            throw new \OutOfBoundsException("Unable to seek to position $offset.");
107
        }
108
109 1
        $this->offset = $offset;
110
111 1
        return $this;
112
    }
113
114 2
    public function withBuffer(string $buffer) : self
115
    {
116 2
        $new = clone $this;
117 2
        $new->buffer = $buffer;
118 2
        $new->offset = 0;
119
120 2
        return $new;
121
    }
122
123 3
    public function tryUnpack() : array
124
    {
125 3
        $data = [];
126 3
        $offset = $this->offset;
127
128
        try {
129
            do {
130 3
                $data[] = $this->unpack();
131 3
                $offset = $this->offset;
132 3
            } while (isset($this->buffer[$this->offset]));
133 1
        } catch (InsufficientDataException $e) {
134 1
            $this->offset = $offset;
135
        }
136
137 3
        if ($this->offset) {
138 3
            $this->buffer = isset($this->buffer[$this->offset]) ? \substr($this->buffer, $this->offset) : '';
139 3
            $this->offset = 0;
140
        }
141
142 3
        return $data;
143
    }
144
145 147
    public function unpack()
146
    {
147 147
        if (!isset($this->buffer[$this->offset])) {
148 5
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
149
        }
150
151 144
        $c = \ord($this->buffer[$this->offset]);
152 144
        ++$this->offset;
153
154
        // fixint
155 144
        if ($c <= 0x7f) {
156 31
            return $c;
157
        }
158
        // fixstr
159 137 View Code Duplication
        if ($c >= 0xa0 && $c <= 0xbf) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160 18
            return ($c & 0x1f) ? $this->unpackStrData($c & 0x1f) : '';
161
        }
162
        // negfixint
163 130
        if ($c >= 0xe0) {
164 5
            return $c - 0x100;
165
        }
166
167 126
        switch ($c) {
168 126
            case 0xc0: return null;
169 124
            case 0xc2: return false;
170 119
            case 0xc3: return true;
171
172
            // fixmap
173 110
            case 0x80: return [];
174 109
            case 0x81: return [$this->unpack() => $this->unpack()];
175 106
            case 0x82: return [$this->unpack() => $this->unpack(), $this->unpack() => $this->unpack()];
176 103
            case 0x83: return [$this->unpack() => $this->unpack(), $this->unpack() => $this->unpack(), $this->unpack() => $this->unpack()];
177 103
            case 0x84: return $this->unpackMapData(4);
178 103
            case 0x85: return $this->unpackMapData(5);
179 103
            case 0x86: return $this->unpackMapData(6);
180 103
            case 0x87: return $this->unpackMapData(7);
181 103
            case 0x88: return $this->unpackMapData(8);
182 103
            case 0x89: return $this->unpackMapData(9);
183 103
            case 0x8a: return $this->unpackMapData(10);
184 103
            case 0x8b: return $this->unpackMapData(11);
185 103
            case 0x8c: return $this->unpackMapData(12);
186 103
            case 0x8d: return $this->unpackMapData(13);
187 103
            case 0x8e: return $this->unpackMapData(14);
188 103
            case 0x8f: return $this->unpackMapData(15);
189
190
            // fixarray
191 103
            case 0x90: return [];
192 102
            case 0x91: return [$this->unpack()];
193 102
            case 0x92: return [$this->unpack(), $this->unpack()];
194 99
            case 0x93: return [$this->unpack(), $this->unpack(), $this->unpack()];
195 98
            case 0x94: return $this->unpackArrayData(4);
196 98
            case 0x95: return $this->unpackArrayData(5);
197 98
            case 0x96: return $this->unpackArrayData(6);
198 98
            case 0x97: return $this->unpackArrayData(7);
199 98
            case 0x98: return $this->unpackArrayData(8);
200 98
            case 0x99: return $this->unpackArrayData(9);
201 98
            case 0x9a: return $this->unpackArrayData(10);
202 98
            case 0x9b: return $this->unpackArrayData(11);
203 98
            case 0x9c: return $this->unpackArrayData(12);
204 98
            case 0x9d: return $this->unpackArrayData(13);
205 98
            case 0x9e: return $this->unpackArrayData(14);
206 98
            case 0x9f: return $this->unpackArrayData(15);
207
208
            // bin
209 98
            case 0xc4: return $this->unpackStrData($this->unpackUint8());
210 93
            case 0xc5: return $this->unpackStrData($this->unpackUint16());
211 92
            case 0xc6: return $this->unpackStrData($this->unpackUint32());
212
213
            // float
214 91
            case 0xca: return $this->unpackFloat32();
215 88
            case 0xcb: return $this->unpackFloat64();
216
217
            // uint
218 84
            case 0xcc: return $this->unpackUint8();
219 80
            case 0xcd: return $this->unpackUint16();
220 73
            case 0xce: return $this->unpackUint32();
221 68
            case 0xcf: return $this->unpackUint64();
222
223
            // int
224 56
            case 0xd0: return $this->unpackInt8();
225 51
            case 0xd1: return $this->unpackInt16();
226 46
            case 0xd2: return $this->unpackInt32();
227 41
            case 0xd3: return $this->unpackInt64();
228
229
            // str
230 33
            case 0xd9: return $this->unpackStrData($this->unpackUint8());
231 29
            case 0xda: return $this->unpackStrData($this->unpackUint16());
232 27
            case 0xdb: return $this->unpackStrData($this->unpackUint32());
233
234
            // array
235 26
            case 0xdc: return $this->unpackArrayData($this->unpackUint16());
236 24
            case 0xdd: return $this->unpackArrayData($this->unpackUint32());
237
238
            // map
239 23
            case 0xde: return $this->unpackMapData($this->unpackUint16());
240 21
            case 0xdf: return $this->unpackMapData($this->unpackUint32());
241
242
            // ext
243 20
            case 0xd4: return $this->unpackExtData(1);
244 17
            case 0xd5: return $this->unpackExtData(2);
245 15
            case 0xd6: return $this->unpackExtData(4);
246 13
            case 0xd7: return $this->unpackExtData(8);
247 11
            case 0xd8: return $this->unpackExtData(16);
248 9
            case 0xc7: return $this->unpackExtData($this->unpackUint8());
249 5
            case 0xc8: return $this->unpackExtData($this->unpackUint16());
250 3
            case 0xc9: return $this->unpackExtData($this->unpackUint32());
251
        }
252
253 1
        throw UnpackingFailedException::unknownCode($c);
254
    }
255
256 3
    public function unpackNil()
257
    {
258 3
        if (!isset($this->buffer[$this->offset])) {
259 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
260
        }
261
262 2
        if ("\xc0" === $this->buffer[$this->offset]) {
263 1
            ++$this->offset;
264
265 1
            return null;
266
        }
267
268 1
        throw UnpackingFailedException::unexpectedCode(\ord($this->buffer[$this->offset++]), 'nil');
269
    }
270
271 5
    public function unpackBool()
272
    {
273 5
        if (!isset($this->buffer[$this->offset])) {
274 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
275
        }
276
277 4
        $c = \ord($this->buffer[$this->offset]);
278 4
        ++$this->offset;
279
280 4
        if (0xc2 === $c) {
281 2
            return false;
282
        }
283 2
        if (0xc3 === $c) {
284 1
            return true;
285
        }
286
287 1
        throw UnpackingFailedException::unexpectedCode($c, 'bool');
288
    }
289
290 40
    public function unpackInt()
291
    {
292 40
        if (!isset($this->buffer[$this->offset])) {
293 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
294
        }
295
296 39
        $c = \ord($this->buffer[$this->offset]);
297 39
        ++$this->offset;
298
299
        // fixint
300 39
        if ($c <= 0x7f) {
301 3
            return $c;
302
        }
303
        // negfixint
304 36
        if ($c >= 0xe0) {
305 3
            return $c - 0x100;
306
        }
307
308 33
        switch ($c) {
309
            // uint
310 33
            case 0xcc: return $this->unpackUint8();
311 30
            case 0xcd: return $this->unpackUint16();
312 27
            case 0xce: return $this->unpackUint32();
313 24
            case 0xcf: return $this->unpackUint64();
314
315
            // int
316 20
            case 0xd0: return $this->unpackInt8();
317 16
            case 0xd1: return $this->unpackInt16();
318 12
            case 0xd2: return $this->unpackInt32();
319 8
            case 0xd3: return $this->unpackInt64();
320
        }
321
322 1
        throw UnpackingFailedException::unexpectedCode($c, 'int');
323
    }
324
325 7
    public function unpackFloat()
326
    {
327 7
        if (!isset($this->buffer[$this->offset])) {
328 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
329
        }
330
331 6
        $c = \ord($this->buffer[$this->offset]);
332 6
        ++$this->offset;
333
334 6
        if (0xcb === $c) {
335 3
            return $this->unpackFloat64();
336
        }
337 3
        if (0xca === $c) {
338 2
            return $this->unpackFloat32();
339
        }
340
341 1
        throw UnpackingFailedException::unexpectedCode($c, 'float');
342
    }
343
344 14
    public function unpackStr()
345
    {
346 14
        if (!isset($this->buffer[$this->offset])) {
347 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
348
        }
349
350 13
        $c = \ord($this->buffer[$this->offset]);
351 13
        ++$this->offset;
352
353 13 View Code Duplication
        if ($c >= 0xa0 && $c <= 0xbf) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354 5
            return ($c & 0x1f) ? $this->unpackStrData($c & 0x1f) : '';
355
        }
356 8
        if (0xd9 === $c) {
357 4
            return $this->unpackStrData($this->unpackUint8());
358
        }
359 4
        if (0xda === $c) {
360 2
            return $this->unpackStrData($this->unpackUint16());
361
        }
362 2
        if (0xdb === $c) {
363 1
            return $this->unpackStrData($this->unpackUint32());
364
        }
365
366 1
        throw UnpackingFailedException::unexpectedCode($c, 'str');
367
    }
368
369 7
    public function unpackBin()
370
    {
371 7
        if (!isset($this->buffer[$this->offset])) {
372 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
373
        }
374
375 6
        $c = \ord($this->buffer[$this->offset]);
376 6
        ++$this->offset;
377
378 6
        if (0xc4 === $c) {
379 3
            return $this->unpackStrData($this->unpackUint8());
380
        }
381 3
        if (0xc5 === $c) {
382 1
            return $this->unpackStrData($this->unpackUint16());
383
        }
384 2
        if (0xc6 === $c) {
385 1
            return $this->unpackStrData($this->unpackUint32());
386
        }
387
388 1
        throw UnpackingFailedException::unexpectedCode($c, 'bin');
389
    }
390
391 9
    public function unpackArray()
392
    {
393 9
        $size = $this->unpackArrayHeader();
394
395 7
        $array = [];
396 7
        while ($size--) {
397 6
            $array[] = $this->unpack();
398
        }
399
400 7
        return $array;
401
    }
402
403 9 View Code Duplication
    public function unpackArrayHeader()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404
    {
405 9
        if (!isset($this->buffer[$this->offset])) {
406 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
407
        }
408
409 8
        $c = \ord($this->buffer[$this->offset]);
410 8
        ++$this->offset;
411
412 8
        if ($c >= 0x90 && $c <= 0x9f) {
413 4
            return $c & 0xf;
414
        }
415 4
        if (0xdc === $c) {
416 2
            return $this->unpackUint16();
417
        }
418 2
        if (0xdd === $c) {
419 1
            return $this->unpackUint32();
420
        }
421
422 1
        throw UnpackingFailedException::unexpectedCode($c, 'array header');
423
    }
424
425 13
    public function unpackMap()
426
    {
427 13
        $size = $this->unpackMapHeader();
428
429 11
        $map = [];
430 11
        while ($size--) {
431 10
            $map[$this->unpack()] = $this->unpack();
432
        }
433
434 11
        return $map;
435
    }
436
437 13 View Code Duplication
    public function unpackMapHeader()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
438
    {
439 13
        if (!isset($this->buffer[$this->offset])) {
440 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
441
        }
442
443 12
        $c = \ord($this->buffer[$this->offset]);
444 12
        ++$this->offset;
445
446 12
        if ($c >= 0x80 && $c <= 0x8f) {
447 8
            return $c & 0xf;
448
        }
449 4
        if (0xde === $c) {
450 2
            return $this->unpackUint16();
451
        }
452 2
        if (0xdf === $c) {
453 1
            return $this->unpackUint32();
454
        }
455
456 1
        throw UnpackingFailedException::unexpectedCode($c, 'map header');
457
    }
458
459 10
    public function unpackExt()
460
    {
461 10
        if (!isset($this->buffer[$this->offset])) {
462 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
463
        }
464
465 9
        $c = \ord($this->buffer[$this->offset]);
466 9
        ++$this->offset;
467
468 9
        switch ($c) {
469 9
            case 0xd4: return $this->unpackExtData(1);
470 8
            case 0xd5: return $this->unpackExtData(2);
471 7
            case 0xd6: return $this->unpackExtData(4);
472 6
            case 0xd7: return $this->unpackExtData(8);
473 5
            case 0xd8: return $this->unpackExtData(16);
474 4
            case 0xc7: return $this->unpackExtData($this->unpackUint8());
475 3
            case 0xc8: return $this->unpackExtData($this->unpackUint16());
476 2
            case 0xc9: return $this->unpackExtData($this->unpackUint32());
477
        }
478
479 1
        throw UnpackingFailedException::unexpectedCode($c, 'ext header');
480
    }
481
482 34
    private function unpackUint8()
483
    {
484 34
        if (!isset($this->buffer[$this->offset])) {
485 2
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
486
        }
487
488 32
        return \ord($this->buffer[$this->offset++]);
489
    }
490
491 28
    private function unpackUint16()
492
    {
493 28
        if (!isset($this->buffer[$this->offset + 1])) {
494 2
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 2);
495
        }
496
497 26
        $hi = \ord($this->buffer[$this->offset]);
498 26
        $lo = \ord($this->buffer[++$this->offset]);
499 26
        ++$this->offset;
500
501 26
        return $hi << 8 | $lo;
502
    }
503
504 20
    private function unpackUint32()
505
    {
506 20
        if (!isset($this->buffer[$this->offset + 3])) {
507 2
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
508
        }
509
510 18
        $num = \unpack('N', $this->buffer, $this->offset)[1];
511 18
        $this->offset += 4;
512
513 18
        return $num;
514
    }
515
516 16 View Code Duplication
    private function unpackUint64()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
517
    {
518 16
        if (!isset($this->buffer[$this->offset + 7])) {
519 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
520
        }
521
522 15
        $num = \unpack('J', $this->buffer, $this->offset)[1];
523 15
        $this->offset += 8;
524
525 15
        return $num < 0 ? $this->handleIntOverflow($num) : $num;
526
    }
527
528 9
    private function unpackInt8()
529
    {
530 9
        if (!isset($this->buffer[$this->offset])) {
531 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
532
        }
533
534 8
        $num = \ord($this->buffer[$this->offset]);
535 8
        ++$this->offset;
536
537 8
        return $num > 0x7f ? $num - 0x100 : $num;
538
    }
539
540 9
    private function unpackInt16()
541
    {
542 9
        if (!isset($this->buffer[$this->offset + 1])) {
543 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 2);
544
        }
545
546 8
        $hi = \ord($this->buffer[$this->offset]);
547 8
        $lo = \ord($this->buffer[++$this->offset]);
548 8
        ++$this->offset;
549
550 8
        return $hi > 0x7f ? $hi << 8 | $lo - 0x10000 : $hi << 8 | $lo;
551
    }
552
553 9 View Code Duplication
    private function unpackInt32()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
554
    {
555 9
        if (!isset($this->buffer[$this->offset + 3])) {
556 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
557
        }
558
559 8
        $num = \unpack('N', $this->buffer, $this->offset)[1];
560 8
        $this->offset += 4;
561
562 8
        return $num > 0x7fffffff ? $num - 0x100000000 : $num;
563
    }
564
565 15
    private function unpackInt64()
566
    {
567 15
        if (!isset($this->buffer[$this->offset + 7])) {
568 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
569
        }
570
571 14
        $num = \unpack('J', $this->buffer, $this->offset)[1];
572 14
        $this->offset += 8;
573
574 14
        return $num;
575
    }
576
577 5
    private function unpackFloat32()
578
    {
579 5
        if (!isset($this->buffer[$this->offset + 3])) {
580 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
581
        }
582
583 4
        $num = \unpack('G', $this->buffer, $this->offset)[1];
584 4
        $this->offset += 4;
585
586 4
        return $num;
587
    }
588
589 7
    private function unpackFloat64()
590
    {
591 7
        if (!isset($this->buffer[$this->offset + 7])) {
592 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
593
        }
594
595 6
        $num = \unpack('E', $this->buffer, $this->offset)[1];
596 6
        $this->offset += 8;
597
598 6
        return $num;
599
    }
600
601 47
    private function unpackStrData($length)
602
    {
603 47
        if (!isset($this->buffer[$this->offset + $length - 1])) {
604 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
605
        }
606
607 47
        $str = \substr($this->buffer, $this->offset, $length);
608 47
        $this->offset += $length;
609
610 47
        return $str;
611
    }
612
613 4
    private function unpackArrayData($size)
614
    {
615 4
        $array = [];
616 4
        while ($size--) {
617 4
            $array[] = $this->unpack();
618
        }
619
620 4
        return $array;
621
    }
622
623 5
    private function unpackMapData($size)
624
    {
625 5
        $map = [];
626 5
        while ($size--) {
627 5
            $map[$this->unpack()] = $this->unpack();
628
        }
629
630 5
        return $map;
631
    }
632
633 24
    private function unpackExtData($length)
634
    {
635 24
        if (!isset($this->buffer[$this->offset + $length - 1])) {
636 5
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
637
        }
638
639
        // int8
640 19
        $type = \ord($this->buffer[$this->offset]);
641 19
        ++$this->offset;
642
643 19
        if ($type > 0x7f) {
644
            $type -= 0x100;
645
        }
646
647 19
        if (isset($this->transformers[$type])) {
648 1
            return $this->transformers[$type]->unpackExt($this, $length);
649
        }
650
651 18
        $data = \substr($this->buffer, $this->offset, $length);
652 18
        $this->offset += $length;
653
654 18
        return new Ext($type, $data);
655
    }
656
657 5
    private function handleIntOverflow($value)
658
    {
659 5
        if ($this->isBigIntAsStr) {
660 3
            return \sprintf('%u', $value);
661
        }
662 2
        if ($this->isBigIntAsGmp) {
663 1
            return \gmp_init(\sprintf('%u', $value));
664
        }
665
666 1
        throw new IntegerOverflowException($value);
667
    }
668
}
669