Completed
Push — master ( 67bbd7...c9eca9 )
by Eugene
06:35
created

Packer::packU64()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
crap 1
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\PackingFailedException;
15
use MessagePack\TypeTransformer\Collection;
16
17
class Packer
18
{
19
    /**
20
     * @var string
21
     */
22
    private static $invalidUtf8Regex = '/(
23
        [\xC0-\xC1] # Invalid UTF-8 Bytes
24
        | [\xF5-\xFF] # Invalid UTF-8 Bytes
25
        | \xE0[\x80-\x9F] # Overlong encoding of prior code point
26
        | \xF0[\x80-\x8F] # Overlong encoding of prior code point
27
        | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start
28
        | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start
29
        | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start
30
        | (?<=[\x0-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle
31
        | (?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2})[\x80-\xBF] # Overlong Sequence
32
        | (?<=[\xE0-\xEF])[\x80-\xBF](?![\x80-\xBF]) # Short 3 byte sequence
33
        | (?<=[\xF0-\xF4])[\x80-\xBF](?![\x80-\xBF]{2}) # Short 4 byte sequence
34
        | (?<=[\xF0-\xF4][\x80-\xBF])[\x80-\xBF](?![\x80-\xBF]) # Short 4 byte sequence (2)
35
    )/x';
36
37
    /**
38
     * @var Collection
39
     */
40
    private $transformers;
41
42
    /**
43
     * @param Collection|null $transformers
44
     */
45 2
    public function setTransformers(Collection $transformers = null)
46
    {
47 2
        $this->transformers = $transformers;
48 2
    }
49
50
    /**
51
     * @return Collection|null
52
     */
53 1
    public function getTransformers()
54
    {
55 1
        return $this->transformers;
56
    }
57
58 77
    public function pack($value)
59
    {
60 77
        $type = \gettype($value);
61
62
        switch ($type) {
63 77
            case 'array': return \array_values($value) === $value
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
64 14
                ? $this->packArray($value)
65 14
                : $this->packMap($value);
66
67 76
            case 'string': return \preg_match(self::$invalidUtf8Regex, $value)
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
68 23
                ? $this->packBin($value)
69 23
                : $this->packStr($value);
70
71 59
            case 'integer': return $this->packInt($value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
72 21
            case 'NULL': return $this->packNil();
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
73 20
            case 'boolean': return $this->packBool($value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
74 15
            case 'double': return $this->packDouble($value);
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
75
        }
76
77 12
        if ($value instanceof Ext) {
78 9
            return $this->packExt($value);
79
        }
80
81 3
        if ($this->transformers && $transformer = $this->transformers->match($value)) {
82 1
            $ext = new Ext($transformer->getId(), $this->pack($transformer->transform($value)));
83
84 1
            return $this->packExt($ext);
85
        }
86
87 2
        throw new PackingFailedException($value, 'Unsupported type.');
88
    }
89
90 7
    public function packArray(array $array)
91
    {
92 7
        $size = \count($array);
93 7
        $data = self::packArrayHeader($size);
94
95 7
        foreach ($array as $val) {
96 6
            $data .= $this->pack($val);
97 7
        }
98
99 7
        return $data;
100
    }
101
102 7 View Code Duplication
    private static function packArrayHeader($size)
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...
103
    {
104 7
        if ($size <= 0xf) {
105 4
            return \chr(0x90 | $size);
106
        }
107 3
        if ($size <= 0xffff) {
108 2
            return \pack('Cn', 0xdc, $size);
109
        }
110
111 1
        return \pack('CN', 0xdd, $size);
112
    }
113
114 9
    public function packMap(array $map)
115
    {
116 9
        $size = \count($map);
117 9
        $data = self::packMapHeader($size);
118
119 9
        foreach ($map as $key => $val) {
120 9
            $data .= $this->pack($key);
121 9
            $data .= $this->pack($val);
122 9
        }
123
124 9
        return $data;
125
    }
126
127 9 View Code Duplication
    private static function packMapHeader($size)
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...
128
    {
129 9
        if ($size <= 0xf) {
130 6
            return \chr(0x80 | $size);
131
        }
132 3
        if ($size <= 0xffff) {
133 2
            return \pack('Cn', 0xde, $size);
134
        }
135
136 1
        return \pack('CN', 0xdf, $size);
137
    }
138
139 17
    public function packStr($str)
140
    {
141 17
        $len = \strlen($str);
142
143 17
        if ($len < 32) {
144 10
            return \chr(0xa0 | $len).$str;
145
        }
146 7
        if ($len <= 0xff) {
147 4
            return \pack('CC', 0xd9, $len).$str;
148
        }
149 3
        if ($len <= 0xffff) {
150 2
            return \pack('Cn', 0xda, $len).$str;
151
        }
152
153 1
        return \pack('CN', 0xdb, $len).$str;
154
    }
155
156 8
    public function packBin($str)
157
    {
158 8
        $len = \strlen($str);
159
160 8
        if ($len <= 0xff) {
161 6
            return \pack('CC', 0xc4, $len).$str;
162
        }
163 2
        if ($len <= 0xffff) {
164 1
            return \pack('Cn', 0xc5, $len).$str;
165
        }
166
167 1
        return \pack('CN', 0xc6, $len).$str;
168
    }
169
170 10
    public function packExt(Ext $ext)
171
    {
172 10
        $type = $ext->getType();
173 10
        $data = $ext->getData();
174 10
        $len = \strlen($data);
175
176
        switch ($len) {
177 10
            case 1: return \pack('CC', 0xd4, $type).$data;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
178 8
            case 2: return \pack('CC', 0xd5, $type).$data;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
179 7
            case 4: return \pack('CC', 0xd6, $type).$data;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
180 6
            case 8: return \pack('CC', 0xd7, $type).$data;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
181 5
            case 16: return \pack('CC', 0xd8, $type).$data;
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
182
        }
183
184 4
        if ($len <= 0xff) {
185 2
            return \pack('CCC', 0xc7, $len, $type).$data;
186
        }
187 2
        if ($len <= 0xffff) {
188 1
            return \pack('CnC', 0xc8, $len, $type).$data;
189
        }
190
191 1
        return \pack('CNC', 0xc9, $len, $type).$data;
192
    }
193
194 3
    public function packNil()
195
    {
196 3
        return "\xc0";
197
    }
198
199 6
    public function packBool($val)
200
    {
201 6
        return $val ? "\xc3" : "\xc2";
202
    }
203
204 3
    public function packDouble($num)
205
    {
206 3
        return "\xcb".strrev(pack('d', $num));
207
    }
208
209 43
    public function packInt($num)
210
    {
211 43
        if ($num >= 0) {
212 28
            if ($num <= 0x7f) {
213 16
                return \chr($num);
214
            }
215 16
            if ($num <= 0xff) {
216 6
                return \pack('CC', 0xcc, $num);
217
            }
218 12
            if ($num <= 0xffff) {
219 6
                return \pack('Cn', 0xcd, $num);
220
            }
221 7
            if ($num <= 0xffffffff) {
222 5
                return \pack('CN', 0xce, $num);
223
            }
224
225 3
            return self::packU64(0xcf, $num);
226
        }
227
228 16
        if ($num >= -0x20) {
229 4
            return \chr(0xe0 | $num);
230
        }
231 12
        if ($num >= -0x80) {
232 3
            return \pack('CC', 0xd0, $num);
233
        }
234 9
        if ($num >= -0x8000) {
235 3
            return \pack('Cn', 0xd1, $num);
236
        }
237 6
        if ($num >= -0x80000000) {
238 3
            return \pack('CN', 0xd2, $num);
239
        }
240
241 3
        return self::packU64(0xd3, $num);
242
    }
243
244 6
    private static function packU64($code, $num)
245
    {
246 6
        $hi = ($num & 0xffffffff00000000) >> 32;
247 6
        $lo = $num & 0x00000000ffffffff;
248
249 6
        return \pack('CNN', $code, $hi, $lo);
250
    }
251
}
252