Completed
Push — master ( 6a9327...c27a0c )
by Eugene
04:54
created

Packer::getTransformers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
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 Collection
21
     */
22
    private $transformers;
23
24
    /**
25
     * @param Collection|null $transformers
26
     */
27 2
    public function setTransformers(Collection $transformers = null)
28
    {
29 2
        $this->transformers = $transformers;
30 2
    }
31
32
    /**
33
     * @return Collection
34
     */
35 1
    public function getTransformers()
36
    {
37 1
        return $this->transformers;
38
    }
39
40 76
    public function pack($value)
41
    {
42 76
        $type = gettype($value);
43
44
        switch ($type) {
45 76
            case 'array':
46 13
                return array_values($value) === $value ? $this->packArr($value) : $this->packMap($value);
47 75
            case 'string':
48 23
                return preg_match('//u', $value) ? $this->packStr($value) : $this->packBin($value);
49 58
            case 'integer':
50 42
                return $this->packInt($value);
51 21
            case 'NULL':
52 3
                return $this->packNil();
53 20
            case 'boolean':
54 6
                return $this->packBool($value);
55 15
            case 'double':
56 3
                return $this->packDouble($value);
57
        }
58
59 12
        if ($value instanceof Ext) {
60 9
            return $this->packExt($value);
61
        }
62
63 3
        if ($this->transformers && $transformer = $this->transformers->match($value)) {
64 1
            $ext = new Ext($transformer->getId(), $this->pack($transformer->transform($value)));
65
66 1
            return $this->packExt($ext);
67
        }
68
69 2
        throw new PackingFailedException($value, 'Unsupported type.');
70
    }
71
72 7
    public function packArr(array $array)
73
    {
74 7
        $size = count($array);
75 7
        $data = self::packArrHeader($size);
76
77 7
        foreach ($array as $val) {
78 6
            $data .= $this->pack($val);
79 7
        }
80
81 7
        return $data;
82
    }
83
84 7 View Code Duplication
    private static function packArrHeader($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...
85
    {
86 7
        if ($size <= 0xf) {
87 4
            return chr(0x90 | $size);
88
        }
89 3
        if ($size <= 0xffff) {
90 2
            return pack('Cn', 0xdc, $size);
91
        }
92
93 1
        return pack('CN', 0xdd, $size);
94
    }
95
96 8
    public function packMap(array $map)
97
    {
98 8
        $size = count($map);
99 8
        $data = self::packMapHeader($size);
100
101 8
        foreach ($map as $key => $val) {
102 8
            $data .= $this->pack($key);
103 8
            $data .= $this->pack($val);
104 8
        }
105
106 8
        return $data;
107
    }
108
109 8 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...
110
    {
111 8
        if ($size <= 0xf) {
112 5
            return chr(0x80 | $size);
113
        }
114 3
        if ($size <= 0xffff) {
115 2
            return pack('Cn', 0xde, $size);
116
        }
117
118 1
        return pack('CN', 0xdf, $size);
119
    }
120
121 17
    public function packStr($str)
122
    {
123 17
        $len = strlen($str);
124
125 17
        if ($len < 32) {
126 10
            return chr(0xa0 | $len).$str;
127
        }
128 7
        if ($len <= 0xff) {
129 4
            return pack('CC', 0xd9, $len).$str;
130
        }
131 3
        if ($len <= 0xffff) {
132 2
            return pack('Cn', 0xda, $len).$str;
133
        }
134
135 1
        return pack('CN', 0xdb, $len).$str;
136
    }
137
138 8
    public function packBin($str)
139
    {
140 8
        $len = strlen($str);
141
142 8
        if ($len <= 0xff) {
143 6
            return pack('CC', 0xc4, $len).$str;
144
        }
145 2
        if ($len <= 0xffff) {
146 1
            return pack('Cn', 0xc5, $len).$str;
147
        }
148
149 1
        return pack('CN', 0xc6, $len).$str;
150
    }
151
152 10
    public function packExt(Ext $ext)
153
    {
154 10
        $type = $ext->getType();
155 10
        $data = $ext->getData();
156 10
        $len = strlen($data);
157
158
        switch ($len) {
159 10
            case 1: return pack('CC', 0xd4, $type).$data;
160 8
            case 2: return pack('CC', 0xd5, $type).$data;
161 7
            case 4: return pack('CC', 0xd6, $type).$data;
162 6
            case 8: return pack('CC', 0xd7, $type).$data;
163 5
            case 16: return pack('CC', 0xd8, $type).$data;
164
        }
165
166 4
        if ($len <= 0xff) {
167 2
            return pack('CCC', 0xc7, $len, $type).$data;
168
        }
169 2
        if ($len <= 0xffff) {
170 1
            return pack('CnC', 0xc8, $len, $type).$data;
171
        }
172
173 1
        return pack('CNC', 0xc9, $len, $type).$data;
174
    }
175
176 3
    public function packNil()
177
    {
178 3
        return "\xc0";
179
    }
180
181 6
    public function packBool($val)
182
    {
183 6
        return $val ? "\xc3" : "\xc2";
184
    }
185
186 3
    public function packDouble($num)
187
    {
188 3
        return "\xcb".strrev(pack('d', $num));
189
    }
190
191 42
    public function packInt($num)
192
    {
193 42
        if ($num >= 0) {
194 27
            if ($num <= 0x7f) {
195 15
                return chr($num);
196
            }
197 16
            if ($num <= 0xff) {
198 6
                return pack('CC', 0xcc, $num);
199
            }
200 12
            if ($num <= 0xffff) {
201 6
                return pack('Cn', 0xcd, $num);
202
            }
203 7
            if ($num <= 0xffffffff) {
204 5
                return pack('CN', 0xce, $num);
205
            }
206
207 3
            return self::packU64(0xcf, $num);
208
        }
209
210 15
        if ($num >= -0x20) {
211 3
            return chr(0xe0 | $num);
212
        }
213 12
        if ($num >= -0x80) {
214 3
            return pack('CC', 0xd0, $num);
215
        }
216 9
        if ($num >= -0x8000) {
217 3
            return pack('Cn', 0xd1, $num);
218
        }
219 6
        if ($num >= -0x80000000) {
220 3
            return pack('CN', 0xd2, $num);
221
        }
222
223 3
        return self::packU64(0xd3, $num);
224
    }
225
226 6
    private static function packU64($code, $num)
227
    {
228 6
        $hi = ($num & 0xffffffff00000000) >> 32;
229 6
        $lo = $num & 0x00000000ffffffff;
230
231 6
        return pack('CNN', $code, $hi, $lo);
232
    }
233
}
234