-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathParserV4.java
More file actions
132 lines (115 loc) · 4.54 KB
/
ParserV4.java
File metadata and controls
132 lines (115 loc) · 4.54 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
package io.socket.engineio.server.parser;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
@SuppressWarnings("unchecked")
public final class ParserV4 implements Parser {
public static final int PROTOCOL = 4;
private static final String SEPARATOR = "\u001E"; // (char) 30
@Override
public int getProtocolVersion() {
return PROTOCOL;
}
/**
* Encode a packet for transfer over transport.
*
* @param packet The packet to encode.
* @param supportsBinary Whether the transport supports binary encoding.
* @param callback The callback to be called with the encoded data.
*/
@Override
public void encodePacket(Packet<?> packet, boolean supportsBinary, EncodeCallback<Object> callback) {
if (packet.data instanceof byte[]) {
encodeByteArray((Packet<byte[]>) packet, supportsBinary, callback);
} else {
String encoded = String.valueOf(PACKETS.get(packet.type));
if (null != packet.data) {
encoded += String.valueOf(packet.data);
}
callback.call(encoded);
}
}
public static void encodeByteArray(Packet<byte[]> packet, boolean supportsBinary, EncodeCallback<Object> callback) {
if (supportsBinary) {
callback.call(packet.data);
} else {
final String resultBuilder = "b" +
Base64.getEncoder().encodeToString(packet.data);
callback.call(resultBuilder);
}
}
/**
* Encode an array of packets into a payload for transfer over transport.
*
* @param packets Array of packets to encode.
* @param callback The callback to be called with the encoded data.
*/
@Override
public void encodePayload(List<Packet<?>> packets, boolean supportsBinary, EncodeCallback<Object> callback) {
final String[] encodedPackets = new String[packets.size()];
for (int i = 0; i < encodedPackets.length; i++) {
final Packet<?> packet = packets.get(i);
final int packetIdx = i;
encodePacket(packet, false, data -> encodedPackets[packetIdx] = (String) data);
}
callback.call(String.join(SEPARATOR, encodedPackets));
}
/**
* Decode payload received from transport.
*
* @param data Data received from transport.
* @param callback The callback to be called with each decoded packet in payload.
*/
@Override
public void decodePayload(Object data, DecodePayloadCallback<Object> callback) {
assert callback != null;
final ArrayList<Packet<?>> packets = new ArrayList<>();
if(data instanceof String) {
final String[] encodedPackets = ((String) data).split(SEPARATOR);
for (String encodedPacket : encodedPackets) {
final Packet<?> packet = decodePacket(encodedPacket);
packets.add(packet);
if (packet.type.equals("error")) {
break;
}
}
} else {
throw new IllegalArgumentException("data must be a String");
}
for (int i = 0; i < packets.size(); i++) {
if(!callback.call((Packet<Object>) packets.get(i), i, packets.size())) {
return;
}
}
}
/**
* Decode a packet received from transport.
*
* @param data Data received from transport.
* @return Packet decoded from data.
*/
@Override
public Packet<?> decodePacket(Object data) {
if(data == null) {
return ERROR_PACKET;
}
if(data instanceof String) {
final String stringData = (String) data;
if(stringData.charAt(0) == 'b') {
final Packet<byte[]> packet = new Packet<>(Packet.MESSAGE);
// Ignore line breaks, added by engine.io-client-java during base64 encode
packet.data = java.util.Base64.getDecoder().decode(stringData.substring(1).replace("\n", ""));
return packet;
} else {
final Packet<String> packet = new Packet<>(PACKETS_REVERSE.get(
Integer.parseInt(String.valueOf(stringData.charAt(0)))));
packet.data = stringData.substring(1);
return packet;
}
} else if(data instanceof byte[]) {
return new Packet<>(Packet.MESSAGE, (byte[]) data);
} else {
throw new IllegalArgumentException("Invalid type for data: " + data.getClass().getSimpleName());
}
}
}