using System.Collections.Generic;
using System;
using System.Text;
namespace NeonTea.Quakeball.TeaNet.Packets {
/// Contains a stream of bytes for sending or receiving over the internet.
public class ByteBuffer {
public int Size => Bytes.Count;
private List Bytes;
private int pos = 0;
/// Creates a new empty ByteBuffer
public ByteBuffer() {
Bytes = new List();
}
/// Creates a new ByteBuffer from the given byte[]
public ByteBuffer(byte[] bytes) {
Bytes = new List(bytes);
}
/// Packs the byte buffer in to a byte[] array.
public byte[] Pack() {
return Bytes.ToArray();
}
/// is there a byte to read next?
public bool CanRead() {
return pos < Bytes.Count;
}
/// Reads a given object with Serializable implemented. Assumes there is one next.
public void ReadSerializable(Serializable s) {
s.Read(this);
}
/// Read a char on the buffer. Assumes there is one next.
public char ReadChar() {
return BitConverter.ToChar(Read(2), 0);
}
/// Read a boolean on the buffer. Assumes there is one next.
public bool ReadBool() {
return Read() == 1;
}
/// Read a double on the buffer. Assumes there is one next.
public double ReadDouble() {
return BitConverter.ToDouble(Read(8), 0);
}
/// Read a float on the buffer. Assumes there is one next.
public float ReadFloat() {
return BitConverter.ToSingle(Read(4), 0);
}
/// Read an unsigned long on the buffer. Assumes there is one next.
public ulong ReadULong() {
return BitConverter.ToUInt64(Read(8), 0);
}
/// Read an unsigned integer on the buffer. Assumes there is one next.
public uint ReadUInt() {
return BitConverter.ToUInt32(Read(4), 0);
}
/// Read an unsigned short on the buffer. Assumes there is one next.
public ushort ReadUShort() {
return BitConverter.ToUInt16(Read(2), 0);
}
/// Read a long on the buffer. Assumes there is one next.
public long ReadLong() {
return BitConverter.ToInt64(Read(8), 0);
}
/// Read an integer on the buffer. Assumes there is one next.
public int ReadInt() {
return BitConverter.ToInt32(Read(4), 0);
}
/// Read a short on the buffer. Assumes there is one next.
public short ReadShort() {
return BitConverter.ToInt16(Read(2), 0);
}
/// Read a string on the buffer. Assumes there is one next.
public string ReadString() {
int length = ReadInt();
string s = Encoding.UTF8.GetString(Read(length));
return s;
}
/// Read an integer on the buffer. Assumes there is one next.
public byte[] Read(int amount) {
byte[] bytes = Bytes.GetRange(pos, amount).ToArray();
pos += amount;
return bytes;
}
/// Read the next byte on the buffer. Assumes there is one next.
public byte Read() {
return Bytes[pos++];
}
/// Write something that implements Serializable.
public void Write(Serializable s) {
s.Write(this);
}
/// Write a char to the buffer.
public void Write(char c) {
Bytes.AddRange(BitConverter.GetBytes(c));
}
/// Write a boolean to the buffer.
public void Write(bool b) {
Write(b ? (byte)0b1 : (byte)0b0);
}
/// Write a double to the buffer.
public void Write(double d) {
Bytes.AddRange(BitConverter.GetBytes(d));
}
/// Write a float to the buffer.
public void Write(float f) {
Bytes.AddRange(BitConverter.GetBytes(f));
}
/// Write an unsigned long to the buffer.
public void Write(ulong l) {
Bytes.AddRange(BitConverter.GetBytes(l));
}
/// Write an unsigned integer to the buffer.
public void Write(uint i) {
Bytes.AddRange(BitConverter.GetBytes(i));
}
/// Write an unsigned short to the buffer.
public void Write(ushort s) {
Bytes.AddRange(BitConverter.GetBytes(s));
}
/// Write a long to the buffer.
public void Write(long l) {
Bytes.AddRange(BitConverter.GetBytes(l));
}
/// Write an integer to the buffer.
public void Write(int i) {
Bytes.AddRange(BitConverter.GetBytes(i));
}
/// Write a short to the buffer.
public void Write(short s) {
Bytes.AddRange(BitConverter.GetBytes(s));
}
/// Write a string to the buffer.
public void Write(string s) {
byte[] bytes = Encoding.UTF8.GetBytes(s);
Write(bytes.Length);
Bytes.AddRange(bytes);
}
/// Write a byte to the buffer.
public void Write(byte b) {
Bytes.Add(b);
}
/// Read weather the given fingerprint is next on the buffer.
public bool ReadFingerprint(byte[] fingerprint) {
foreach (byte b in fingerprint) {
if (!(CanRead() && Read() == b)) {
return false;
}
}
return true;
}
public PacketStage ReadStage() {
PacketStage stage = PacketStage.Closed;
switch (Read()) {
case 0:
stage = PacketStage.Establishing;
break;
case 1:
stage = PacketStage.Rejected;
break;
case 2:
stage = PacketStage.Closed;
break;
case 3:
stage = PacketStage.Ready;
break;
}
return stage;
}
public ClosingReason ReadClosingReason() {
ClosingReason reason = ClosingReason.Unknown;
switch (Read()) {
case 0:
reason = ClosingReason.Unknown;
break;
case 1:
reason = ClosingReason.IncorrectVersion;
break;
}
return reason;
}
/// Write an entire packet using the protocol to the buffer.
public void WritePacket(Protocol protocol, Packet p) {
int old = Bytes.Count;
Write(protocol.GetPacketTypeID(p));
p.Write(this);
p.Size = Bytes.Count - old;
}
/// Read an entire packet using the given protocol from the buffer.
public Packet ReadPacket(Protocol protocol) {
int old = pos;
int packetType = ReadInt();
Type t = protocol.GetPacketType(packetType);
Packet p = (Packet)Activator.CreateInstance(t);
p.Read(this);
p.Size = pos - old;
return p;
}
}
}