-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBufferPayloadReader.php
More file actions
144 lines (115 loc) · 3.48 KB
/
Copy pathBufferPayloadReader.php
File metadata and controls
144 lines (115 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?php
/**
* Copyright © EcomDev B.V. All rights reserved.
* See LICENSE for license details.
*/
declare(strict_types=1);
namespace EcomDev\MySQLBinaryProtocol;
class BufferPayloadReader implements PayloadReader
{
private const LENGTH_MARKERS = [
0xfc => 2,
0xfd => 3,
0xfe => 8
];
private const NULL_MARKER = 0xfb;
/** @var ReadBuffer */
private $buffer;
/**
* @var BinaryIntegerReader
*/
private $integerReader;
/** @var int[] */
private $unreadPacketLength;
public function __construct(ReadBuffer $buffer, array $unreadPacketLength, BinaryIntegerReader $integerReader)
{
$this->buffer = $buffer;
$this->integerReader = $integerReader;
$this->unreadPacketLength = $unreadPacketLength;
}
/**
* {@inheritDoc}
*/
public function readFixedInteger(int $bytes)
{
return $this->integerReader->readFixed(
$this->buffer->read($bytes),
$bytes
);
}
/**
* {@inheritDoc}
*/
public function readLengthEncodedIntegerOrNull()
{
$firstByte = $this->readFixedInteger(1);
if ($firstByte < 251) {
return $firstByte;
}
if ($firstByte === self::NULL_MARKER) {
return null;
}
if (isset(self::LENGTH_MARKERS[$firstByte])) {
return $this->readFixedInteger(self::LENGTH_MARKERS[$firstByte]);
}
throw new InvalidBinaryDataException();
}
/**
* Reads string of specified length from buffer
*
* @see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_strings.html
*/
public function readFixedString(int $length): string
{
return $this->buffer->read($length);
}
/**
* Reads string that is has length as the first part of the fragment
*
* @see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_strings.html
*/
public function readLengthEncodedStringOrNull(): ?string
{
$length = $this->readLengthEncodedIntegerOrNull();
if ($length === null) {
return null;
}
return $this->buffer->read($length);
}
/**
* Reads string till x00 character
*
* @see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_strings.html
*/
public function readNullTerminatedString(): string
{
$nullPosition = $this->buffer->scan("\x00");
if ($nullPosition === -1) {
throw new IncompleteBufferException();
}
$string = $this->buffer->read($nullPosition - 1);
$this->buffer->read(1);
return $string;
}
/**
* Reads string that is rest of payload
*
* @see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_strings.html
*/
public function readRestOfPacketString(): string
{
return $this->buffer->read(
$this->remainingPacketLengthToRead()
);
}
private function remainingPacketLengthToRead(): int
{
$currentBufferPosition = $this->buffer->currentPosition();
$currentPacketIndex = 0;
while ($this->unreadPacketLength[$currentPacketIndex] <= $currentBufferPosition) {
$currentBufferPosition -= $this->unreadPacketLength[$currentPacketIndex];
$currentPacketIndex++;
}
return $this->unreadPacketLength[$currentPacketIndex] - $currentBufferPosition;
}
}