Completed
Push — master ( c14602...9e703a )
by thomas
24:57 queued 10:12
created

Parser   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 21
c 2
b 0
f 0
lcom 1
cbo 6
dl 0
loc 172
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 3
A getPosition() 0 4 1
A readBytes() 0 19 4
A writeBytes() 0 21 4
A writeRawBinary() 0 4 1
A writeBuffer() 0 14 3
A writeArray() 0 19 4
A getBuffer() 0 4 1
1
<?php
2
3
namespace BitWasp\Buffertools;
4
5
use BitWasp\Buffertools\Exceptions\ParserOutOfRange;
6
use Mdanter\Ecc\EccFactory;
7
use Mdanter\Ecc\Math\GmpMathInterface;
8
9
class Parser
10
{
11
    /**
12
     * @var string
13
     */
14
    private $string;
15
16
    /**
17
     * @var \Mdanter\Ecc\Math\GmpMathInterface
18
     */
19
    private $math;
20
21
    /**
22
     * @var int
23
     */
24
    private $position = 0;
25
26
    /**
27
     * Instantiate class, optionally taking Buffer or HEX.
28
     *
29
     * @param null|string|BufferInterface $input
30
     * @param GmpMathInterface|null $math
31
     */
32
    public function __construct($input = null, GmpMathInterface $math = null)
33
    {
34
        $this->math = $math ?: EccFactory::getAdapter();
35
36
        if (!$input instanceof BufferInterface) {
37
            $input = Buffer::hex($input, null, $this->math);
38
        }
39
40
        $this->string = $input->getBinary();
41
        $this->position = 0;
42
    }
43
44
    /**
45
     * Get the position pointer of the parser - ie, how many bytes from 0
46
     *
47
     * @return int
48
     */
49
    public function getPosition()
50
    {
51
        return $this->position;
52
    }
53
54
    /**
55
     * Parse $bytes bytes from the string, and return the obtained buffer
56
     *
57
     * @param  integer $bytes
58
     * @param  bool $flipBytes
59
     * @return Buffer
60
     * @throws \Exception
61
     */
62
    public function readBytes($bytes, $flipBytes = false)
63
    {
64
        $string = substr($this->string, $this->getPosition(), $bytes);
65
        $length = strlen($string);
66
67
        if ($length == 0) {
68
            throw new ParserOutOfRange('Could not parse string of required length (empty)');
69
        } elseif ($length < $bytes) {
70
            throw new ParserOutOfRange('Could not parse string of required length (too short)');
71
        }
72
73
        $this->position += $bytes;
74
75
        if ($flipBytes) {
76
            $string = Buffertools::flipBytes($string);
77
        }
78
79
        return new Buffer($string, $length, $this->math);
0 ignored issues
show
Bug introduced by
It seems like $string defined by \BitWasp\Buffertools\Buf...ols::flipBytes($string) on line 76 can also be of type object<BitWasp\Buffertools\Buffer>; however, BitWasp\Buffertools\Buffer::__construct() does only seem to accept string, 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...
80
    }
81
82
    /**
83
     * Write $data as $bytes bytes. Can be flipped if needed.
84
     *
85
     * @param  integer $bytes
86
     * @param  $data
87
     * @param  bool $flipBytes
88
     * @return $this
89
     */
90
    public function writeBytes($bytes, $data, $flipBytes = false)
91
    {
92
        // Treat $data to ensure it's a buffer, with the correct size
93
        if ($data instanceof SerializableInterface) {
94
            $data = $data->getBuffer();
95
        }
96
97
        if ($data instanceof BufferInterface) {
98
            // only create a new buffer if the size does not match
99
            if ($data->getSize() != $bytes) {
100
                $data = new Buffer($data->getBinary(), $bytes, $this->math);
101
            }
102
        } else {
103
            // Convert to a buffer
104
            $data = Buffer::hex($data, $bytes, $this->math);
105
        }
106
107
        $this->writeBuffer($bytes, $data, $flipBytes);
108
109
        return $this;
110
    }
111
112
    /**
113
     * Write $data as $bytes bytes. Can be flipped if needed.
114
     *
115
     * @param  integer $bytes
116
     * @param  string $data
117
     * @param  bool $flipBytes
118
     * @return $this
119
     */
120
    public function writeRawBinary($bytes, $data, $flipBytes = false)
121
    {
122
        return $this->writeBuffer($bytes, new Buffer($data, $bytes), $flipBytes);
123
    }
124
125
    /**
126
     * @param BufferInterface $buffer
127
     * @param bool $flipBytes
128
     * @param int $bytes
129
     * @return $this
130
     */
131
    public function writeBuffer($bytes, BufferInterface $buffer, $flipBytes = false)
132
    {
133
        $size = $buffer->getSize();
134
        if ($bytes > $size) {
135
            throw new \RuntimeException('Bytes is greater than Buffer size');
136
        }
137
138
        if ($flipBytes) {
139
            $buffer = $buffer->flip();
140
        }
141
142
        $this->string .= $buffer->getBinary();
143
        return $this;
144
    }
145
146
    /**
147
     * Take an array containing serializable objects.
148
     * @param SerializableInterface[]|Buffer[]
149
     * @return $this
150
     */
151
    public function writeArray($serializable)
152
    {
153
        $parser = new Parser(Buffertools::numToVarInt(count($serializable)), $this->math);
154
        foreach ($serializable as $object) {
155
            if ($object instanceof SerializableInterface) {
156
                $object = $object->getBuffer();
157
            }
158
159
            if ($object instanceof BufferInterface) {
160
                $parser->writeBytes($object->getSize(), $object);
161
            } else {
162
                throw new \RuntimeException('Input to writeArray must be Buffer[], or SerializableInterface[]');
163
            }
164
        }
165
166
        $this->string .= $parser->getBuffer()->getBinary();
167
168
        return $this;
169
    }
170
171
    /**
172
     * Return the string as a buffer
173
     *
174
     * @return BufferInterface
175
     */
176
    public function getBuffer()
177
    {
178
        return new Buffer($this->string, null, $this->math);
179
    }
180
}
181