Completed
Push — master ( 6bd7ca...3d6f9a )
by Eugene
05:16
created

BufferUnpacker::read()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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