Completed
Branch master (a46014)
by Eugene
02:13
created

BufferUnpacker::unpackMapHeader()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 21

Duplication

Lines 21
Ratio 100 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 21
loc 21
ccs 12
cts 12
cp 1
rs 8.9617
cc 6
nc 5
nop 0
crap 6
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 Decimal\Decimal;
15
use MessagePack\Exception\InsufficientDataException;
16
use MessagePack\Exception\InvalidOptionException;
17
use MessagePack\Exception\UnpackingFailedException;
18
use MessagePack\TypeTransformer\Extension;
19
20
class BufferUnpacker
21
{
22
    private $buffer;
23
    private $offset = 0;
24
    private $isBigIntAsDec;
25
    private $isBigIntAsGmp;
26
27
    /**
28
     * @var Extension[]
29
     */
30
    private $extensions = [];
31
32
    /**
33
     * @param UnpackOptions|int|null $options
34
     * @param Extension[] $extensions
35
     *
36
     * @throws InvalidOptionException
37
     */
38 320
    public function __construct(string $buffer = '', $options = null, array $extensions = [])
39
    {
40 320
        if (\is_null($options)) {
41 319
            $options = UnpackOptions::fromDefaults();
42 8
        } elseif (!$options instanceof UnpackOptions) {
43 8
            $options = UnpackOptions::fromBitmask($options);
44
        }
45
46 320
        $this->isBigIntAsDec = $options->isBigIntAsDecMode();
47 320
        $this->isBigIntAsGmp = $options->isBigIntAsGmpMode();
48
49 320
        $this->buffer = $buffer;
50
51 320
        if ($extensions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extensions of type MessagePack\TypeTransformer\Extension[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
52 1
            foreach ($extensions as $extension) {
53 1
                $this->extensions[$extension->getType()] = $extension;
54
            }
55
        }
56 320
    }
57
58 1
    public function extendWith(Extension $extension, Extension ...$extensions) : self
59
    {
60 1
        $new = clone $this;
61 1
        $new->extensions[$extension->getType()] = $extension;
62
63 1
        if ($extensions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extensions of type MessagePack\TypeTransformer\Extension[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

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