Completed
Push — master ( 49a33e...99c0bb )
by Eugene
04:31
created

BufferUnpacker::unpack()   F

Complexity

Conditions 70
Paths 69

Size

Total Lines 110

Duplication

Lines 3
Ratio 2.73 %

Code Coverage

Tests 76
CRAP Score 70

Importance

Changes 0
Metric Value
dl 3
loc 110
ccs 76
cts 76
cp 1
rs 3.3333
c 0
b 0
f 0
cc 70
nc 69
nop 0
crap 70

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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