欢迎关注公众号:冒泡的肥皂
AMF0的数据类型是前两位。所以首先解析数据类型,然后根据数据类型的格式进行数据读取
部分类型解析
public static Object decode(final ByteBuf in) {
//读取数据类型
final Type type = Type.valueToEnum(in.readByte());
final Object value = decode(in, type);
log.info("<< " + toString(type, value));
return value;
}
private static Object decode(final ByteBuf in, final Type type) {
switch (type) {
case NUMBER://0x00
return Double.longBitsToDouble(in.readLong());
case BOOLEAN://0x01
return in.readByte() == BOOLEAN_TRUE;
case STRING://0x02
return decodeString(in);
case OBJECT://0x03
final int count=0;
final Map<String, Object> map=new Amf0Object();
int i = 0;
final byte[] endMarker = new byte[3];
while (in.isReadable()) {
in.getBytes(in.readerIndex(), endMarker);
if (Arrays.equals(endMarker, OBJECT_END_MARKER)) {
in.skipBytes(3);
log.debug("end MAP / OBJECT, found object end marker [000009]");
break;
}
if (count > 0 && i++ == count) {
log.debug("stopping map decode after reaching count: {}", count);
break;
}
map.put(decodeString(in), decode(in));
}
return map;
case NULL://0x05
return null;
case UNDEFINED://0x06
return null;
case MAP://0x08
final int count = in.readInt(); // should always be 0
final Map<String, Object> map = new LinkedHashMap<String, Object>();
int i = 0;
final byte[] endMarker = new byte[3];
while (in.isReadable()) {
in.getBytes(in.readerIndex(), endMarker);
if (Arrays.equals(endMarker, OBJECT_END_MARKER)) {
in.skipBytes(3);
log.debug("end MAP / OBJECT, found object end marker [000009]");
break;
}
if (count > 0 && i++ == count) {
log.debug("stopping map decode after reaching count: {}", count);
break;
}
map.put(decodeString(in), decode(in));
}
return map;
case ARRAY://0x0a
final int arraySize = in.readInt();
final Object[] array = new Object[arraySize];
for (int i = 0; i < arraySize; i++) {
array[i] = decode(in);
}
return array;
case DATE://0x0b
final long dateValue = in.readLong();
in.readShort(); // consume the timezone
return new Date((long) Double.longBitsToDouble(dateValue));
case LONG_STRING://0x0c 大小4字节
final int stringSize = in.readInt();
final byte[] bytes = new byte[stringSize];
in.readBytes(bytes);
return new String(bytes); // UTF-8 ?
case UNSUPPORTED://0x0d
return null;
case AMF_INVALID://0xff
return null;
default:
throw new RuntimeException("AMF0数据解码类型不支持: " + type);
}
}
//string类型解析 大小 2字节
private static String decodeString(final ByteBuf in) {
final short size = in.readShort();
final byte[] bytes = new byte[size];
in.readBytes(bytes);
return new String(bytes); // should we force encode to UTF-8 ?
}