Proper generic read/write/sizeOf functions

This commit is contained in:
roblabla 2014-04-01 15:43:57 +02:00
parent 7b9f170fb2
commit c0ba7f8127
2 changed files with 68 additions and 55 deletions

View File

@ -633,20 +633,21 @@ var packetStates = {toClient: {}, toServer: {}};
var types = {
'int': [readInt, writeInt, 4],
'short': [readShort, writeShort, 2],
'ushort': [readUShort, writeUShort, 2],
'byte': [readByte, writeByte, 1],
'ubyte': [readUByte, writeUByte, 1],
'string': [readString, writeString, sizeOfString],
'ustring': [readString, writeString, sizeOfUString],
'byteArray16': [readByteArray16, writeByteArray16, sizeOfByteArray16],
'bool': [readBool, writeBool, 1],
'double': [readDouble, writeDouble, 8],
'float': [readFloat, writeFloat, 4],
'slot': [readSlot, writeSlot, sizeOfSlot],
'short': [readShort, writeShort, 2],
'ushort': [readUShort, writeUShort, 2],
'int': [readInt, writeInt, 4],
'long': [readLong, writeLong, 8],
'varint': [readVarInt, writeVarInt, sizeOfVarInt],
'float': [readFloat, writeFloat, 4],
'double': [readDouble, writeDouble, 8],
'bool': [readBool, writeBool, 1],
'string': [readString, writeString, sizeOfString],
'ustring': [readString, writeString, sizeOfUString], // TODO : remove ustring
// TODO : remove type-specific, replace with generic containers and arrays.
'slot': [readSlot, writeSlot, sizeOfSlot],
'byteArray16': [readByteArray16, writeByteArray16, sizeOfByteArray16],
'ascii': [readAscii, writeAscii, sizeOfAscii],
'entityMetadata': [readEntityMetadata, writeEntityMetadata, sizeOfEntityMetadata],
'byteArray32': [readByteArray32, writeByteArray32, sizeOfByteArray32],
@ -728,7 +729,7 @@ function sizeOfEntityMetadata(value) {
var item;
for (var i = 0; i < value.length; ++i) {
item = value[i];
size += sizeOf(item.type, item.value);
size += sizeOf(item.value, { type: item.type }, {});
}
return size;
}
@ -1599,6 +1600,50 @@ function writeMatchArray(value, buffer, offset) {
return offset;
}
function read(buffer, cursor, fieldInfo, rootNodes) {
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
return null;
}
var type = types[fieldInfo.type];
if (!type) {
return {
error: new Error("missing data type: " + fieldInfo.type)
};
}
var readResults = type[0](buffer, cursor, fieldInfo.typeArgs, rootNodes);
if (readResults.error) return { error: readResults.error };
return readResults;
}
function write(value, buffer, offset, fieldInfo, rootNodes) {
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
return null;
}
var type = types[fieldInfo.type];
if (!type) {
return {
error: new Error("missing data type: " + fieldInfo.type)
};
}
return type[1](value, buffer, offset, fieldInfo.typeArgs);
}
function sizeOf(value, fieldInfo, rootNodes) {
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
return 0;
}
var type = types[fieldInfo.type];
if (!type) {
throw new Error("missing data type: " + fieldInfo.type);
}
if (typeof type[2] === 'function') {
return type[2](value, fieldInfo.typeArgs);
} else {
return type[2];
}
}
function get(packetId, state, toServer) {
var direction = toServer ? "toServer" : "toClient";
var packetInfo = packetFields[state][direction][packetId];
@ -1608,17 +1653,6 @@ function get(packetId, state, toServer) {
return packetInfo;
}
function sizeOf(type, value) {
var dataType = types[type];
assert.ok(dataType, "unknown data type " + type);
var size = dataType[2];
if (typeof size === "function") {
return size(value);
} else {
return size;
}
}
function createPacketBuffer(packetId, state, params, isServer) {
var length = 0;
if (typeof packetId === 'string' && typeof state !== 'string' && !params) {
@ -1632,10 +1666,7 @@ function createPacketBuffer(packetId, state, params, isServer) {
var packet = get(packetId, state, !isServer);
assert.notEqual(packet, null);
packet.forEach(function(fieldInfo) {
var condition = fieldInfo.condition;
if (typeof condition != "undefined" && !condition(params))
return;
length += sizeOf(fieldInfo.type, params[fieldInfo.name]);
length += sizeOf(params[fieldInfo.name], fieldInfo, params);
});
length += sizeOfVarInt(packetId);
var size = length + sizeOfVarInt(length);
@ -1643,32 +1674,14 @@ function createPacketBuffer(packetId, state, params, isServer) {
var offset = writeVarInt(length, buffer, 0);
offset = writeVarInt(packetId, buffer, offset);
packet.forEach(function(fieldInfo) {
var condition = fieldInfo.condition;
if (typeof condition != "undefined" && !condition(params))
return;
var write = types[fieldInfo.type][1];
var value = params[fieldInfo.name];
if(typeof value === "undefined") value = 0;
offset = write(value, buffer, offset);
if(typeof value === "undefined") value = 0; // TODO : Why ?
offset = write(value, buffer, offset, fieldInfo, params);
});
return buffer;
}
function parsePacket(buffer, state, isServer) {
function readPacketField(fieldInfo) {
var read = types[fieldInfo.type][0];
if (!read) {
return {
error: new Error("missing reader for data type: " + fieldInfo.type)
}
}
var readResults = read(buffer, cursor);
if (! readResults) return null; // buffer needs to be more full
if (readResults.error) return { error: readResults.error };
return readResults;
}
if (state == null) state == states.PLAY;
var cursor = 0;
var lengthField = readVarInt(buffer, 0);
@ -1697,12 +1710,9 @@ function parsePacket(buffer, state, isServer) {
var i, fieldInfo, readResults;
for (i = 0; i < packetInfo.length; ++i) {
fieldInfo = packetInfo[i];
var condition = fieldInfo.condition;
if (typeof condition != "undefined" && !condition(results)) {
results[fieldInfo.name] = null;
continue;
}
readResults = readPacketField(fieldInfo);
readResults = read(buffer, cursor, fieldInfo, results);
/* A deserializer cannot return null anymore. Besides, read() returns
* null when the condition is not fulfilled.
if (!!!readResults) {
var error = new Error("A deserializer returned null");
error.packetId = packetId;
@ -1712,7 +1722,8 @@ function parsePacket(buffer, state, isServer) {
error: error,
results: results
};
}
}*/
if (readResults === null) continue;
if (readResults.error) {
return readResults;
}

View File

@ -164,7 +164,9 @@ describe("packets", function() {
// empty object uses default values
var packet = {};
packetInfo.forEach(function(field) {
if (!field.hasOwnProperty("condition") || field.condition(packet)) {
packet[field.name] = values[field.type];
}
});
if (toServer) {
serverClient.once([state, packetId], function(receivedPacket) {