Completed
Push — master ( f0b993...1c5ae3 )
by Eugene
07:01
created

BufferUnpacker   F

Complexity

Total Complexity 186

Size/Duplication

Total Lines 637
Duplicated Lines 15.07 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 99.71%

Importance

Changes 0
Metric Value
wmc 186
lcom 1
cbo 4
dl 96
loc 637
ccs 341
cts 342
cp 0.9971
rs 1.963
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 3
A registerTransformer() 0 6 1
A append() 0 6 1
A reset() 0 7 1
A seek() 14 14 3
A skip() 12 12 2
A withBuffer() 0 8 1
A tryUnpack() 0 21 5
F unpack() 3 110 70
A unpackNil() 0 14 3
A unpackBool() 0 18 4
C unpackInt() 0 34 12
A unpackFloat() 0 18 4
B unpackStr() 3 24 8
A unpackBin() 0 21 5
A unpackArray() 0 11 2
B unpackArrayHeader() 21 21 6
A unpackMap() 0 11 2
B unpackMapHeader() 21 21 6
B unpackExt() 0 22 10
A unpackUint8() 0 8 2
A unpackUint16() 0 12 2
A unpackUint32() 0 11 2
A unpackUint64() 11 11 3
A unpackInt8() 0 11 3
A unpackInt16() 0 12 3
A unpackInt32() 11 11 3
A unpackInt64() 0 11 2
A unpackFloat32() 0 11 2
A unpackFloat64() 0 11 2
A unpackStrData() 0 11 2
A unpackArrayData() 0 9 2
A unpackMapData() 0 9 2
A unpackExtData() 0 23 4
A handleIntOverflow() 0 11 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like BufferUnpacker often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BufferUnpacker, and based on these observations, apply Extract Interface, too.

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 242
    public function __construct(string $buffer = '', $options = null)
38
    {
39 242
        if (null === $options) {
40 241
            $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 242
        $this->isBigIntAsStr = $options->isBigIntAsStrMode();
46 242
        $this->isBigIntAsGmp = $options->isBigIntAsGmpMode();
47
48 242
        $this->buffer = $buffer;
49 242
    }
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 215
    public function reset(string $buffer = '') : self
66
    {
67 215
        $this->buffer = $buffer;
68 215
        $this->offset = 0;
69
70 215
        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 2
    public function withBuffer(string $buffer) : self
102
    {
103 2
        $new = clone $this;
104 2
        $new->buffer = $buffer;
105 2
        $new->offset = 0;
106
107 2
        return $new;
108
    }
109
110 3
    public function tryUnpack() : array
111
    {
112 3
        $data = [];
113 3
        $offset = $this->offset;
114
115
        try {
116
            do {
117 3
                $data[] = $this->unpack();
118 3
                $offset = $this->offset;
119 3
            } while (isset($this->buffer[$this->offset]));
120 1
        } catch (InsufficientDataException $e) {
121 1
            $this->offset = $offset;
122
        }
123
124 3
        if ($this->offset) {
125 3
            $this->buffer = isset($this->buffer[$this->offset]) ? \substr($this->buffer, $this->offset) : '';
126 3
            $this->offset = 0;
127
        }
128
129 3
        return $data;
130
    }
131
132 147
    public function unpack()
133
    {
134 147
        if (!isset($this->buffer[$this->offset])) {
135 5
            throw InsufficientDataException::unexpectedLength($this->buffer, $this->offset, 1);
136
        }
137
138 144
        $c = \ord($this->buffer[$this->offset]);
139 144
        ++$this->offset;
140
141
        // fixint
142 144
        if ($c <= 0x7f) {
143 31
            return $c;
144
        }
145
        // fixstr
146 137 View Code Duplication
        if ($c >= 0xa0 && $c <= 0xbf) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

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