/**
* Copyright 2012 Ronen Hamias, Anton Kharenko
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package io.scalecube.socketio.serialization;
import io.netty.buffer.ByteBuf;
import io.netty.util.ByteProcessor;
import io.netty.util.CharsetUtil;
import io.scalecube.socketio.packets.Packet;
import io.scalecube.socketio.packets.PacketType;
import java.io.IOException;
public final class PacketDecoder {
private static final byte DELIMITER = (byte) ':';
private static final ByteProcessor packetDelimiterFinder = new ByteProcessor() {
@Override
public boolean process(byte value) throws Exception {
return value != DELIMITER;
}
};
/**
* Don't let anyone instantiate this class.
*/
private PacketDecoder() {
}
public static Packet decodePacket(final ByteBuf payload) throws IOException {
int payloadSize = payload.readableBytes();
// Decode packet type
int typeDelimiterIndex = payload.forEachByte(packetDelimiterFinder);
if (typeDelimiterIndex == -1) {
return Packet.NULL_INSTANCE;
}
ByteBuf typeBytes = payload.slice(0, typeDelimiterIndex);
String typeString = typeBytes.toString(CharsetUtil.UTF_8);
int typeId = Integer.valueOf(typeString);
PacketType type = PacketType.valueOf(typeId);
// Skip message id
int messageIdDelimiterIndex = payload.forEachByte(typeDelimiterIndex + 1, payloadSize - typeDelimiterIndex - 1, packetDelimiterFinder);
if (messageIdDelimiterIndex == -1) {
return Packet.NULL_INSTANCE;
}
// Skip endpoint
int endpointDelimiterIndex = payload.forEachByte(messageIdDelimiterIndex + 1, payloadSize - messageIdDelimiterIndex - 1, packetDelimiterFinder);
// Create instance of packet
Packet packet = new Packet(type);
// Decode data
boolean messagingType = type == PacketType.MESSAGE || type == PacketType.JSON;
if (endpointDelimiterIndex != -1 && messagingType) {
int dataLength = payloadSize - endpointDelimiterIndex - 1;
if (dataLength > 0) {
ByteBuf data = payload.copy(endpointDelimiterIndex + 1, dataLength);
packet.setData(data);
}
}
return packet;
}
}