|
@@ -1,9 +1,173 @@ |
|
|
using System; |
|
|
using System; |
|
|
|
|
|
using System.Collections.Concurrent; |
|
|
using System.IO; |
|
|
using System.IO; |
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
using System.Text; |
|
|
|
|
|
|
|
|
namespace Discord.ETF |
|
|
namespace Discord.ETF |
|
|
{ |
|
|
{ |
|
|
public class ETFReader |
|
|
public class ETFReader |
|
|
{ |
|
|
{ |
|
|
|
|
|
/* |
|
|
|
|
|
private readonly Stream _stream; |
|
|
|
|
|
private readonly byte[] _buffer; |
|
|
|
|
|
private readonly bool _leaveOpen; |
|
|
|
|
|
private readonly Encoding _encoding; |
|
|
|
|
|
private readonly ConcurrentDictionary<Type, Delegate> _serializers, _indirectSerializers; |
|
|
|
|
|
|
|
|
|
|
|
private void ReadNil(bool allow) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!allow) throw new InvalidDataException(); |
|
|
|
|
|
_stream.Read(_buffer, 0, 3); |
|
|
|
|
|
if (_buffer[0] != 'n' || _buffer[1] != 'i' || _buffer[2] != 'l') |
|
|
|
|
|
throw new InvalidDataException(); |
|
|
|
|
|
} |
|
|
|
|
|
private void ReadTrue() |
|
|
|
|
|
{ |
|
|
|
|
|
_stream.Read(_buffer, 0, 4); |
|
|
|
|
|
if (_buffer[0] != 't' || _buffer[1] != 'r' || _buffer[2] != 'u' || _buffer[3] != 'e') |
|
|
|
|
|
throw new InvalidDataException(); |
|
|
|
|
|
} |
|
|
|
|
|
private void ReadFalse() |
|
|
|
|
|
{ |
|
|
|
|
|
_stream.Read(_buffer, 0, 5); |
|
|
|
|
|
if (_buffer[0] != 'f' || _buffer[1] != 'a' || _buffer[2] != 'l' || _buffer[3] != 's' || _buffer[4] != 'e') |
|
|
|
|
|
throw new InvalidDataException(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool? ReadBool(bool allowNil) |
|
|
|
|
|
{ |
|
|
|
|
|
_stream.Read(_buffer, 0, 2); |
|
|
|
|
|
switch ((ETFType)_buffer[0]) |
|
|
|
|
|
{ |
|
|
|
|
|
case ETFType.SMALL_ATOM_EXT: |
|
|
|
|
|
switch (_buffer[1]) //Length |
|
|
|
|
|
{ |
|
|
|
|
|
case 3: |
|
|
|
|
|
ReadNil(allowNil); |
|
|
|
|
|
return null; |
|
|
|
|
|
case 4: |
|
|
|
|
|
ReadTrue(); |
|
|
|
|
|
return true; |
|
|
|
|
|
case 5: |
|
|
|
|
|
ReadFalse(); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
throw new InvalidDataException(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public long? ReadInteger(bool allowNil) |
|
|
|
|
|
{ |
|
|
|
|
|
_stream.Read(_buffer, 0, 1); |
|
|
|
|
|
ETFType type = (ETFType)reader.ReadByte(); |
|
|
|
|
|
switch (type) |
|
|
|
|
|
{ |
|
|
|
|
|
case ETFType.SMALL_ATOM_EXT: |
|
|
|
|
|
ReadNil(allowNil); |
|
|
|
|
|
return null; |
|
|
|
|
|
case ETFType.SMALL_INTEGER_EXT: |
|
|
|
|
|
_stream.Read(_buffer, 0, 1); |
|
|
|
|
|
return (_buffer[0] << 24) | (_buffer[1] << 16) | |
|
|
|
|
|
(_buffer[2] << 8) | (_buffer[3]); |
|
|
|
|
|
case ETFType.INTEGER_EXT: |
|
|
|
|
|
_stream.Read(_buffer, 0, 4); |
|
|
|
|
|
return ??; |
|
|
|
|
|
case ETFType.SMALL_BIG_EXT: |
|
|
|
|
|
return ??; |
|
|
|
|
|
} |
|
|
|
|
|
throw new InvalidDataException(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Write(sbyte value) => Write((long)value); |
|
|
|
|
|
public void Write(byte value) => Write((ulong)value); |
|
|
|
|
|
public void Write(short value) => Write((long)value); |
|
|
|
|
|
public void Write(ushort value) => Write((ulong)value); |
|
|
|
|
|
public void Write(int value) => Write((long)value); |
|
|
|
|
|
public void Write(uint value) => Write((ulong)value); |
|
|
|
|
|
public void Write(long value) |
|
|
|
|
|
{ |
|
|
|
|
|
if (value >= byte.MinValue && value <= byte.MaxValue) |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; |
|
|
|
|
|
_buffer[1] = (byte)value; |
|
|
|
|
|
_stream.Write(_buffer, 0, 2); |
|
|
|
|
|
} |
|
|
|
|
|
else if (value >= int.MinValue && value <= int.MaxValue) |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.INTEGER_EXT; |
|
|
|
|
|
_buffer[1] = (byte)(value >> 24); |
|
|
|
|
|
_buffer[2] = (byte)(value >> 16); |
|
|
|
|
|
_buffer[3] = (byte)(value >> 8); |
|
|
|
|
|
_buffer[4] = (byte)value; |
|
|
|
|
|
_stream.Write(_buffer, 0, 5); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.SMALL_BIG_EXT; |
|
|
|
|
|
if (value < 0) |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[2] = 1; //Is negative |
|
|
|
|
|
value = -value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
byte bytes = 0; |
|
|
|
|
|
while (value > 0) |
|
|
|
|
|
_buffer[3 + bytes++] = (byte)(value >>= 8); |
|
|
|
|
|
_buffer[1] = bytes; //Encoded bytes |
|
|
|
|
|
|
|
|
|
|
|
_stream.Write(_buffer, 0, 3 + bytes); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
public void Write(ulong value) |
|
|
|
|
|
{ |
|
|
|
|
|
if (value <= byte.MaxValue) |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.SMALL_INTEGER_EXT; |
|
|
|
|
|
_buffer[1] = (byte)value; |
|
|
|
|
|
_stream.Write(_buffer, 0, 2); |
|
|
|
|
|
} |
|
|
|
|
|
else if (value <= int.MaxValue) |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.INTEGER_EXT; |
|
|
|
|
|
_buffer[1] = (byte)(value >> 24); |
|
|
|
|
|
_buffer[2] = (byte)(value >> 16); |
|
|
|
|
|
_buffer[3] = (byte)(value >> 8); |
|
|
|
|
|
_buffer[4] = (byte)value; |
|
|
|
|
|
_stream.Write(_buffer, 0, 5); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
_buffer[0] = (byte)ETFType.SMALL_BIG_EXT; |
|
|
|
|
|
_buffer[2] = 0; //Always positive |
|
|
|
|
|
|
|
|
|
|
|
byte bytes = 0; |
|
|
|
|
|
while (value > 0) |
|
|
|
|
|
_buffer[3 + bytes++] = (byte)(value >>= 8); |
|
|
|
|
|
_buffer[1] = bytes; //Encoded bytes |
|
|
|
|
|
|
|
|
|
|
|
_stream.Write(_buffer, 0, 3 + bytes); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Write(float value) => Write((double)value); |
|
|
|
|
|
public unsafe void Write(double value) |
|
|
|
|
|
{ |
|
|
|
|
|
ulong value2 = *(ulong*)&value; |
|
|
|
|
|
_buffer[0] = (byte)ETFType.NEW_FLOAT_EXT; |
|
|
|
|
|
_buffer[1] = (byte)(value2 >> 56); |
|
|
|
|
|
_buffer[2] = (byte)(value2 >> 48); |
|
|
|
|
|
_buffer[3] = (byte)(value2 >> 40); |
|
|
|
|
|
_buffer[4] = (byte)(value2 >> 32); |
|
|
|
|
|
_buffer[5] = (byte)(value2 >> 24); |
|
|
|
|
|
_buffer[6] = (byte)(value2 >> 16); |
|
|
|
|
|
_buffer[7] = (byte)(value2 >> 8); |
|
|
|
|
|
_buffer[8] = (byte)value2; |
|
|
|
|
|
_stream.Write(_buffer, 0, 9); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Write(DateTime value) => Write((ulong)((value.Ticks - _epochTime.Ticks) / TimeSpan.TicksPerSecond)); |
|
|
|
|
|
*/ |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |