Skip to content

Instantly share code, notes, and snippets.

@thenameless314159
Created August 29, 2019 06:41
Show Gist options
  • Save thenameless314159/8e0acd28c63b0085b417f69a77942bbd to your computer and use it in GitHub Desktop.
Save thenameless314159/8e0acd28c63b0085b417f69a77942bbd to your computer and use it in GitHub Desktop.
public class DofusFrameDecoder : HeaderFrameDecoder<DofusMetadata>
{
protected override bool TryParseHeader(ref SequenceReader<byte> input, out DofusMetadata frame, out int length)
{
frame = default;
length = 0;
if (!input.TryReadBigEndian(out short header)) return false;
if (!input.TryReadBigEndian(out int instanceId)) return false;
var messageId = header >> 2;
var lengthByteCount = header & 0x3;
if (messageId <= 0) return false;
if (input.Remaining < lengthByteCount) return false;
Span<byte> lengthBuffer = stackalloc byte[lengthByteCount];
input.Sequence.Slice(2 + 4, lengthByteCount).CopyTo(lengthBuffer);
for (int i = lengthByteCount - 1, j = 0; i >= 0; i--, j++)
length |= lengthBuffer[j] << (i * 8);
frame = new DofusMetadata(messageId, (uint)instanceId, lengthByteCount);
return true;
}
}
public class DofusFrameEncoder : HeaderFrameEncoder<DofusMetadata>
{
protected override int GetHeaderLength(DofusMetadata frame) => sizeof(short) + frame.LengthByteCount;
protected override void WriteHeader(Span<byte> buffer, OutputFrame<DofusMetadata> frame)
{
var metadata = frame.Frame;
var header = (short)(metadata.MessageId << 2 | (byte)metadata.LengthByteCount);
BinaryPrimitives.WriteInt16BigEndian(buffer, header);
if (metadata.LengthByteCount == 0) return;
var span = buffer.Slice(2);
switch (metadata.LengthByteCount)
{
case 1:
span[0] = (byte)frame.Payload.Length;
break;
case 2:
BinaryPrimitives.WriteInt16BigEndian(span, (short)frame.Payload.Length);
break;
case 3:
span[0] = (byte)(frame.Payload.Length >> 16 & byte.MaxValue);
BinaryPrimitives.WriteInt16BigEndian(span.Slice(1), (short)(frame.Payload.Length & ushort.MaxValue));
break;
default:
throw new ArgumentOutOfRangeException(nameof(metadata.LengthByteCount));
}
}
}
public class DofusMetadata
{
public int LengthByteCount { get; set; }
public uint InstanceId { get; set; }
public int MessageId { get; set; }
public DofusMetadata(int messageId, uint instanceId, int lengthByteCount) // from client
{
LengthByteCount = lengthByteCount;
MessageId = messageId;
InstanceId = instanceId;
}
public DofusMetadata(int messageId, int lengthByteCount) // from server
{
LengthByteCount = lengthByteCount;
MessageId = messageId;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment