Completed
Pull Request — master (#286)
by
unknown
03:20
created

Table   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 161
Duplicated Lines 21.12 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 34
loc 161
rs 10
c 0
b 0
f 0
wmc 26
lcom 1
cbo 2

6 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 6 1
A parseTable() 12 12 2
C parseField() 0 44 15
B parseDecimal() 0 29 5
A parseArray() 12 12 2
A parseByteArray() 10 10 1

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace PHPDaemon\Clients\AMQP\Driver\Protocol\v091\Parser;
4
5
use PHPDaemon\Clients\AMQP\Driver\Protocol\Exception\AMQPProtocolException;
6
7
/**
8
 * Parse an AMQP table from a string buffer.
9
 *
10
 * This implementation uses the field types as discussed in the AMQP 0.9.1 SIG,
11
 * (*NOT* the specification) along with Qpid's extensions. This parser is suitable
12
 * for use with RabbitMQ and Qpid.
13
 *
14
 * @see https://www.rabbitmq.com/amqp-0-9-1-errata.html#section_3
15
 *
16
 * @see SpecTableParser for an implementation based on the AMQP 0.9.1 specification.
17
 *
18
 * Class Table
19
 * @author Aleksey I. Kuleshov YOU GLOBAL LIMITED
20
 * @package PHPDaemon\Clients\AMQP\Driver\Protocol\v091\Parser
21
 */
22
class Table implements TableInterface
23
{
24
    use ScalarParserTrait;
25
26
    /**
27
     * @var string A buffer containing the table data.
28
     */
29
    private $buffer = '';
30
31
    /**
32
     * Retrieve the next frame from the internal buffer.
33
     *
34
     * @param string &$buffer Binary data containing the table.
35
     *
36
     * @throws AMQPProtocolException if the incoming data does not conform to the
37
     *                               AMQP specification.
38
     * @return array
39
     */
40
    public function parse(&$buffer)
41
    {
42
        $this->buffer = &$buffer;
43
44
        return $this->parseTable();
45
    }
46
47
    /**
48
     * Parse an AMQP table from the head of the buffer.
49
     * @return array
50
     * @throws \PHPDaemon\Clients\AMQP\Driver\Protocol\Exception\AMQPProtocolException
51
     */
52 View Code Duplication
    private function parseTable()
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...
53
    {
54
        $length = $this->parseUnsignedInt32();
55
        $stopAt = strlen($this->buffer) - $length;
56
        $table = [];
57
58
        while (strlen($this->buffer) > $stopAt) {
59
            $table[$this->parseShortString()] = $this->parseField();
60
        }
61
62
        return $table;
63
    }
64
65
    /**
66
     * Parse a table or array field.
67
     *
68
     * @return integer|array|boolean|double|string|null
69
     * @throws AMQPProtocolException
70
     */
71
    private function parseField()
72
    {
73
        $type = $this->buffer[0];
74
        $this->buffer = substr($this->buffer, 1);
75
76
        // @todo bench switch vs if vs method map
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
77
        switch ($type) {
78
            case 's':
79
                return $this->parseSignedInt16();
80
            case 'l':
81
                return $this->parseSignedInt64();
82
            case 'x':
83
                return $this->parseByteArray();
84
            case 't':
85
                return $this->parseUnsignedInt8() !== 0;
86
            case 'b':
87
                return $this->parseSignedInt8();
88
            case 'I':
89
                return $this->parseSignedInt32();
90
            case 'f':
91
                return $this->parseFloat();
92
            case 'd':
93
                return $this->parseDouble();
94
            case 'D':
95
                return $this->parseDecimal();
96
            case 'S':
97
                return $this->parseLongString();
98
            case 'A':
99
                return $this->parseArray();
100
            case 'T':
101
                return $this->parseUnsignedInt64();
102
            case 'F':
103
                return $this->parseTable();
104
            case 'V':
105
                return null;
106
        }
107
108
        throw new AMQPProtocolException(
109
            sprintf(
110
                'table value type (0x%02x) is invalid or unrecognised.',
111
                ord($type)
112
            )
113
        );
114
    }
115
116
    /**
117
     * Parse an AMQP decimal from the head of the buffer.
118
     * @return string
119
     */
120
    public function parseDecimal()
121
    {
122
        $scale = $this->parseUnsignedInt8();
123
        $value = $this->parseSignedInt32();
124
125
        if (0 === $scale) {
126
            return (string)$value;
127
        }
128
129
        if ($value >= 0) {
130
            $sign = '';
131
            $value = (string)$value;
132
        } else {
133
            $sign = '-';
134
            $value = (string)-$value;
135
        }
136
137
        $length = strlen($value);
138
139
        if ($length === $scale) {
140
            return $sign . '0.' . $value;
141
        }
142
143
        if ($length < $scale) {
144
            return $sign . '0.' . str_repeat('0', $scale - $length) . $value;
145
        }
146
147
        return $sign . substr($value, 0, -$scale) . '.' . substr($value, -$scale);
148
    }
149
150
    /**
151
     * Parse an AMQP field-array value.
152
     * @return array
153
     * @throws \PHPDaemon\Clients\AMQP\Driver\Protocol\Exception\AMQPProtocolException
154
     */
155 View Code Duplication
    private function parseArray()
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...
156
    {
157
        $length = $this->parseUnsignedInt32();
158
        $stopAt = strlen($this->buffer) - $length;
159
        $array = [];
160
161
        while (strlen($this->buffer) > $stopAt) {
162
            $array[] = $this->parseField();
163
        }
164
165
        return $array;
166
    }
167
168
    /**
169
     * Parse an AMQP byte-array value.
170
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
171
     */
172 View Code Duplication
    private function parseByteArray()
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...
173
    {
174
        list(, $length) = unpack('N', $this->buffer);
175
176
        try {
177
            return substr($this->buffer, 4, $length);
178
        } finally {
179
            $this->buffer = substr($this->buffer, $length + 4);
180
        }
181
    }
182
}
183