Completed
Pull Request — master (#30)
by Eugene
06:01
created

BufferUnpacker::extendWith()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 6
cts 6
cp 1
rs 9.8333
c 0
b 0
f 0
cc 3
nc 2
nop 2
crap 3
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 242
     * @throws InvalidOptionException
38
     */
39 242
    public function __construct(string $buffer = '', $options = null, array $transformers = [])
40 241
    {
41 8
        if (null === $options) {
42 8
            $options = UnpackOptions::fromDefaults();
43
        } elseif (!$options instanceof PackOptions) {
44
            $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 242
        }
46 242
47
        $this->isBigIntAsStr = $options->isBigIntAsStrMode();
48 242
        $this->isBigIntAsGmp = $options->isBigIntAsGmpMode();
49 242
50
        $this->buffer = $buffer;
51 1
52
        if ([] !== $transformers) {
53 1
            $this->transformers = $transformers;
54
        }
55 1
    }
56
57
    public function extendWith(CanUnpackExt $transformer, CanUnpackExt ...$transformers) : self
58 10
    {
59
        $new = clone $this;
60 10
        $new->transformers[$transformer->getType()] = $transformer;
61
62 10
        if ([] !== $transformers) {
63
            foreach ($transformers as $t) {
64
                $new->transformers[$t->getType()] = $t;
65 215
            }
66
        }
67 215
68 215
        return $new;
69
    }
70 215
71
    public function append(string $data) : self
72
    {
73 3
        $this->buffer .= $data;
74
75 3
        return $this;
76 1
    }
77
78
    public function reset(string $buffer = '') : self
79 3
    {
80 1
        $this->buffer = $buffer;
81
        $this->offset = 0;
82
83 2
        return $this;
84
    }
85 2
86 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 2
        if ($offset < 0) {
89
            $offset += \strlen($this->buffer);
90 2
        }
91
92 2
        if (!isset($this->buffer[$offset])) {
93 1
            throw new \OutOfBoundsException("Unable to seek to position $offset.");
94
        }
95
96 1
        $this->offset = $offset;
97
98 1
        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 2
105 2
        if (!isset($this->buffer[$offset])) {
106
            throw new \OutOfBoundsException("Unable to seek to position $offset.");
107 2
        }
108
109
        $this->offset = $offset;
110 3
111
        return $this;
112 3
    }
113 3
114
    public function withBuffer(string $buffer) : self
115
    {
116
        $new = clone $this;
117 3
        $new->buffer = $buffer;
118 3
        $new->offset = 0;
119 3
120 1
        return $new;
121 1
    }
122
123
    public function tryUnpack() : array
124 3
    {
125 3
        $data = [];
126 3
        $offset = $this->offset;
127
128
        try {
129 3
            do {
130
                $data[] = $this->unpack();
131
                $offset = $this->offset;
132 147
            } while (isset($this->buffer[$this->offset]));
133
        } catch (InsufficientDataException $e) {
134 147
            $this->offset = $offset;
135 5
        }
136
137
        if ($this->offset) {
138 144
            $this->buffer = isset($this->buffer[$this->offset]) ? \substr($this->buffer, $this->offset) : '';
139 144
            $this->offset = 0;
140
        }
141
142 144
        return $data;
143 31
    }
144
145
    public function unpack()
146 137
    {
147 18
        if (!isset($this->buffer[$this->offset])) {
148
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
149
        }
150 130
151 5
        $c = \ord($this->buffer[$this->offset]);
152
        ++$this->offset;
153
154 126
        // fixint
155 126
        if ($c <= 0x7f) {
156 124
            return $c;
157 119
        }
158
        // fixstr
159 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 110
            return ($c & 0x1f) ? $this->unpackStrData($c & 0x1f) : '';
161 109
        }
162 106
        // negfixint
163 103
        if ($c >= 0xe0) {
164 103
            return $c - 0x100;
165 103
        }
166 103
167 103
        switch ($c) {
168 103
            case 0xc0: return null;
169 103
            case 0xc2: return false;
170 103
            case 0xc3: return true;
171 103
172 103
            // fixmap
173 103
            case 0x80: return [];
174 103
            case 0x81: return [$this->unpack() => $this->unpack()];
175 103
            case 0x82: return [$this->unpack() => $this->unpack(), $this->unpack() => $this->unpack()];
176
            case 0x83: return [$this->unpack() => $this->unpack(), $this->unpack() => $this->unpack(), $this->unpack() => $this->unpack()];
177
            case 0x84: return $this->unpackMapData(4);
178 103
            case 0x85: return $this->unpackMapData(5);
179 102
            case 0x86: return $this->unpackMapData(6);
180 102
            case 0x87: return $this->unpackMapData(7);
181 99
            case 0x88: return $this->unpackMapData(8);
182 98
            case 0x89: return $this->unpackMapData(9);
183 98
            case 0x8a: return $this->unpackMapData(10);
184 98
            case 0x8b: return $this->unpackMapData(11);
185 98
            case 0x8c: return $this->unpackMapData(12);
186 98
            case 0x8d: return $this->unpackMapData(13);
187 98
            case 0x8e: return $this->unpackMapData(14);
188 98
            case 0x8f: return $this->unpackMapData(15);
189 98
190 98
            // fixarray
191 98
            case 0x90: return [];
192 98
            case 0x91: return [$this->unpack()];
193 98
            case 0x92: return [$this->unpack(), $this->unpack()];
194
            case 0x93: return [$this->unpack(), $this->unpack(), $this->unpack()];
195
            case 0x94: return $this->unpackArrayData(4);
196 98
            case 0x95: return $this->unpackArrayData(5);
197 93
            case 0x96: return $this->unpackArrayData(6);
198 92
            case 0x97: return $this->unpackArrayData(7);
199
            case 0x98: return $this->unpackArrayData(8);
200
            case 0x99: return $this->unpackArrayData(9);
201 91
            case 0x9a: return $this->unpackArrayData(10);
202 88
            case 0x9b: return $this->unpackArrayData(11);
203
            case 0x9c: return $this->unpackArrayData(12);
204
            case 0x9d: return $this->unpackArrayData(13);
205 84
            case 0x9e: return $this->unpackArrayData(14);
206 80
            case 0x9f: return $this->unpackArrayData(15);
207 73
208 68
            // bin
209
            case 0xc4: return $this->unpackStrData($this->unpackUint8());
210
            case 0xc5: return $this->unpackStrData($this->unpackUint16());
211 56
            case 0xc6: return $this->unpackStrData($this->unpackUint32());
212 51
213 46
            // float
214 41
            case 0xca: return $this->unpackFloat32();
215
            case 0xcb: return $this->unpackFloat64();
216
217 33
            // uint
218 29
            case 0xcc: return $this->unpackUint8();
219 27
            case 0xcd: return $this->unpackUint16();
220
            case 0xce: return $this->unpackUint32();
221
            case 0xcf: return $this->unpackUint64();
222 26
223 24
            // int
224
            case 0xd0: return $this->unpackInt8();
225
            case 0xd1: return $this->unpackInt16();
226 23
            case 0xd2: return $this->unpackInt32();
227 21
            case 0xd3: return $this->unpackInt64();
228
229
            // str
230 20
            case 0xd9: return $this->unpackStrData($this->unpackUint8());
231 17
            case 0xda: return $this->unpackStrData($this->unpackUint16());
232 15
            case 0xdb: return $this->unpackStrData($this->unpackUint32());
233 13
234 11
            // array
235 9
            case 0xdc: return $this->unpackArrayData($this->unpackUint16());
236 5
            case 0xdd: return $this->unpackArrayData($this->unpackUint32());
237 3
238
            // map
239
            case 0xde: return $this->unpackMapData($this->unpackUint16());
240 1
            case 0xdf: return $this->unpackMapData($this->unpackUint32());
241
242
            // ext
243 3
            case 0xd4: return $this->unpackExtData(1);
244
            case 0xd5: return $this->unpackExtData(2);
245 3
            case 0xd6: return $this->unpackExtData(4);
246 1
            case 0xd7: return $this->unpackExtData(8);
247
            case 0xd8: return $this->unpackExtData(16);
248
            case 0xc7: return $this->unpackExtData($this->unpackUint8());
249 2
            case 0xc8: return $this->unpackExtData($this->unpackUint16());
250 1
            case 0xc9: return $this->unpackExtData($this->unpackUint32());
251
        }
252 1
253
        throw UnpackingFailedException::unknownCode($c);
254
    }
255 1
256
    public function unpackNil()
257
    {
258 5
        if (!isset($this->buffer[$this->offset])) {
259
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
260 5
        }
261 1
262
        if ("\xc0" === $this->buffer[$this->offset]) {
263
            ++$this->offset;
264 4
265 4
            return null;
266
        }
267 4
268 2
        throw UnpackingFailedException::unexpectedCode(\ord($this->buffer[$this->offset++]), 'nil');
269
    }
270 2
271 1
    public function unpackBool()
272
    {
273
        if (!isset($this->buffer[$this->offset])) {
274 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
275
        }
276
277 40
        $c = \ord($this->buffer[$this->offset]);
278
        ++$this->offset;
279 40
280 1
        if (0xc2 === $c) {
281
            return false;
282
        }
283 39
        if (0xc3 === $c) {
284 39
            return true;
285
        }
286
287 39
        throw UnpackingFailedException::unexpectedCode($c, 'bool');
288 3
    }
289
290
    public function unpackInt()
291 36
    {
292 3
        if (!isset($this->buffer[$this->offset])) {
293
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
294
        }
295 33
296
        $c = \ord($this->buffer[$this->offset]);
297 33
        ++$this->offset;
298 30
299 27
        // fixint
300 24
        if ($c <= 0x7f) {
301
            return $c;
302
        }
303 20
        // negfixint
304 16
        if ($c >= 0xe0) {
305 12
            return $c - 0x100;
306 8
        }
307
308
        switch ($c) {
309 1
            // uint
310
            case 0xcc: return $this->unpackUint8();
311
            case 0xcd: return $this->unpackUint16();
312 7
            case 0xce: return $this->unpackUint32();
313
            case 0xcf: return $this->unpackUint64();
314 7
315 1
            // int
316
            case 0xd0: return $this->unpackInt8();
317
            case 0xd1: return $this->unpackInt16();
318 6
            case 0xd2: return $this->unpackInt32();
319 6
            case 0xd3: return $this->unpackInt64();
320
        }
321 6
322 3
        throw UnpackingFailedException::unexpectedCode($c, 'int');
323
    }
324 3
325 2
    public function unpackFloat()
326
    {
327
        if (!isset($this->buffer[$this->offset])) {
328 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
329
        }
330
331 14
        $c = \ord($this->buffer[$this->offset]);
332
        ++$this->offset;
333 14
334 1
        if (0xcb === $c) {
335
            return $this->unpackFloat64();
336
        }
337 13
        if (0xca === $c) {
338 13
            return $this->unpackFloat32();
339
        }
340 13
341 5
        throw UnpackingFailedException::unexpectedCode($c, 'float');
342
    }
343 8
344 4
    public function unpackStr()
345
    {
346 4
        if (!isset($this->buffer[$this->offset])) {
347 2
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
348
        }
349 2
350 1
        $c = \ord($this->buffer[$this->offset]);
351
        ++$this->offset;
352
353 1 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
            return ($c & 0x1f) ? $this->unpackStrData($c & 0x1f) : '';
355
        }
356 7
        if (0xd9 === $c) {
357
            return $this->unpackStrData($this->unpackUint8());
358 7
        }
359 1
        if (0xda === $c) {
360
            return $this->unpackStrData($this->unpackUint16());
361
        }
362 6
        if (0xdb === $c) {
363 6
            return $this->unpackStrData($this->unpackUint32());
364
        }
365 6
366 3
        throw UnpackingFailedException::unexpectedCode($c, 'str');
367
    }
368 3
369 1
    public function unpackBin()
370
    {
371 2
        if (!isset($this->buffer[$this->offset])) {
372 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
373
        }
374
375 1
        $c = \ord($this->buffer[$this->offset]);
376
        ++$this->offset;
377
378 9
        if (0xc4 === $c) {
379
            return $this->unpackStrData($this->unpackUint8());
380 9
        }
381
        if (0xc5 === $c) {
382 7
            return $this->unpackStrData($this->unpackUint16());
383 7
        }
384 6
        if (0xc6 === $c) {
385
            return $this->unpackStrData($this->unpackUint32());
386
        }
387 7
388
        throw UnpackingFailedException::unexpectedCode($c, 'bin');
389
    }
390 9
391
    public function unpackArray()
392 9
    {
393 1
        $size = $this->unpackArrayHeader();
394
395
        $array = [];
396 8
        while ($size--) {
397 8
            $array[] = $this->unpack();
398
        }
399 8
400 4
        return $array;
401
    }
402 4
403 2 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 2
        if (!isset($this->buffer[$this->offset])) {
406 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
407
        }
408
409 1
        $c = \ord($this->buffer[$this->offset]);
410
        ++$this->offset;
411
412 13
        if ($c >= 0x90 && $c <= 0x9f) {
413
            return $c & 0xf;
414 13
        }
415
        if (0xdc === $c) {
416 11
            return $this->unpackUint16();
417 11
        }
418 10
        if (0xdd === $c) {
419
            return $this->unpackUint32();
420
        }
421 11
422
        throw UnpackingFailedException::unexpectedCode($c, 'array header');
423
    }
424 13
425
    public function unpackMap()
426 13
    {
427 1
        $size = $this->unpackMapHeader();
428
429
        $map = [];
430 12
        while ($size--) {
431 12
            $map[$this->unpack()] = $this->unpack();
432
        }
433 12
434 8
        return $map;
435
    }
436 4
437 2 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 2
        if (!isset($this->buffer[$this->offset])) {
440 1
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
441
        }
442
443 1
        $c = \ord($this->buffer[$this->offset]);
444
        ++$this->offset;
445
446 10
        if ($c >= 0x80 && $c <= 0x8f) {
447
            return $c & 0xf;
448 10
        }
449 1
        if (0xde === $c) {
450
            return $this->unpackUint16();
451
        }
452 9
        if (0xdf === $c) {
453 9
            return $this->unpackUint32();
454
        }
455 9
456 9
        throw UnpackingFailedException::unexpectedCode($c, 'map header');
457 8
    }
458 7
459 6
    public function unpackExt()
460 5
    {
461 4
        if (!isset($this->buffer[$this->offset])) {
462 3
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
463 2
        }
464
465
        $c = \ord($this->buffer[$this->offset]);
466 1
        ++$this->offset;
467
468
        switch ($c) {
469 34
            case 0xd4: return $this->unpackExtData(1);
470
            case 0xd5: return $this->unpackExtData(2);
471 34
            case 0xd6: return $this->unpackExtData(4);
472 2
            case 0xd7: return $this->unpackExtData(8);
473
            case 0xd8: return $this->unpackExtData(16);
474
            case 0xc7: return $this->unpackExtData($this->unpackUint8());
475 32
            case 0xc8: return $this->unpackExtData($this->unpackUint16());
476
            case 0xc9: return $this->unpackExtData($this->unpackUint32());
477
        }
478 28
479
        throw UnpackingFailedException::unexpectedCode($c, 'ext header');
480 28
    }
481 2
482
    private function unpackUint8()
483
    {
484 26
        if (!isset($this->buffer[$this->offset])) {
485 26
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
486 26
        }
487
488 26
        return \ord($this->buffer[$this->offset++]);
489
    }
490
491 20
    private function unpackUint16()
492
    {
493 20
        if (!isset($this->buffer[$this->offset + 1])) {
494 2
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 2);
495
        }
496
497 18
        $hi = \ord($this->buffer[$this->offset]);
498 18
        $lo = \ord($this->buffer[++$this->offset]);
499
        ++$this->offset;
500 18
501
        return $hi << 8 | $lo;
502
    }
503 16
504
    private function unpackUint32()
505 16
    {
506 1
        if (!isset($this->buffer[$this->offset + 3])) {
507
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
508
        }
509 15
510 15
        $num = \unpack('N', $this->buffer, $this->offset)[1];
511
        $this->offset += 4;
512 15
513
        return $num;
514
    }
515 9
516 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 9
    {
518 1
        if (!isset($this->buffer[$this->offset + 7])) {
519
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
520
        }
521 8
522 8
        $num = \unpack('J', $this->buffer, $this->offset)[1];
523
        $this->offset += 8;
524 8
525
        return $num < 0 ? $this->handleIntOverflow($num) : $num;
526
    }
527 9
528
    private function unpackInt8()
529 9
    {
530 1
        if (!isset($this->buffer[$this->offset])) {
531
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
532
        }
533 8
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
        ++$this->offset;
549 8
550
        return $hi > 0x7f ? $hi << 8 | $lo - 0x10000 : $hi << 8 | $lo;
551
    }
552 15
553 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 15
    {
555 1
        if (!isset($this->buffer[$this->offset + 3])) {
556
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
557
        }
558 14
559 14
        $num = \unpack('N', $this->buffer, $this->offset)[1];
560
        $this->offset += 4;
561 14
562
        return $num > 0x7fffffff ? $num - 0x100000000 : $num;
563
    }
564 5
565
    private function unpackInt64()
566 5
    {
567 1
        if (!isset($this->buffer[$this->offset + 7])) {
568
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
569
        }
570 4
571 4
        $num = \unpack('J', $this->buffer, $this->offset)[1];
572
        $this->offset += 8;
573 4
574
        return $num;
575
    }
576 7
577
    private function unpackFloat32()
578 7
    {
579 1
        if (!isset($this->buffer[$this->offset + 3])) {
580
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 4);
581
        }
582 6
583 6
        $num = \unpack('G', $this->buffer, $this->offset)[1];
584
        $this->offset += 4;
585 6
586
        return $num;
587
    }
588 47
589
    private function unpackFloat64()
590 47
    {
591 1
        if (!isset($this->buffer[$this->offset + 7])) {
592
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 8);
593
        }
594 47
595 47
        $num = \unpack('E', $this->buffer, $this->offset)[1];
596
        $this->offset += 8;
597 47
598
        return $num;
599
    }
600 4
601
    private function unpackStrData($length)
602 4
    {
603 4
        if (!isset($this->buffer[$this->offset + $length - 1])) {
604 4
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
605
        }
606
607 4
        $str = \substr($this->buffer, $this->offset, $length);
608
        $this->offset += $length;
609
610 5
        return $str;
611
    }
612 5
613 5
    private function unpackArrayData($size)
614 5
    {
615
        $array = [];
616
        while ($size--) {
617 5
            $array[] = $this->unpack();
618
        }
619
620 24
        return $array;
621
    }
622 24
623 5
    private function unpackMapData($size)
624
    {
625
        $map = [];
626
        while ($size--) {
627 19
            $map[$this->unpack()] = $this->unpack();
628 19
        }
629
630 19
        return $map;
631
    }
632
633
    private function unpackExtData($length)
634 19
    {
635 1
        if (!isset($this->buffer[$this->offset + $length - 1])) {
636
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, $length);
637
        }
638 18
639 18
        // int8
640
        $type = \ord($this->buffer[$this->offset]);
641 18
        ++$this->offset;
642
643
        if ($type > 0x7f) {
644 5
            $type -= 0x100;
645
        }
646 5
647 3
        if (isset($this->transformers[$type])) {
648
            return $this->transformers[$type]->unpackExt($this, $length);
649 2
        }
650 1
651
        $data = \substr($this->buffer, $this->offset, $length);
652
        $this->offset += $length;
653 1
654
        return new Ext($type, $data);
655
    }
656
657
    private function handleIntOverflow($value)
658
    {
659
        if ($this->isBigIntAsStr) {
660
            return \sprintf('%u', $value);
661
        }
662
        if ($this->isBigIntAsGmp) {
663
            return \gmp_init(\sprintf('%u', $value));
664
        }
665
666
        throw new IntegerOverflowException($value);
667
    }
668
}
669