qamp/Qrakhen.Qamp.Core/Execution/Segment.cs

74 lines
2.6 KiB
C#

using Qrakhen.Qamp.Core.Collections;
using Qrakhen.Qamp.Core.Values;
namespace Qrakhen.Qamp.Core.Execution;
using Unsigned = ulong;
using Signed = long;
using Char = char;
using Byte = byte;
using Bool = bool;
using Decimal = double;
public class Segment(
IEnumerable<Instruction> instructions,
IEnumerable<Value> constants) : ISerialize<Segment>
{
public readonly FixedArray<Instruction> Instructions = new(instructions);
public readonly FixedArray<Value> Constants = new(constants);
public byte Read(long offset) => Instructions[offset];
public byte[] Read(long offset, int length)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(offset + length, Instructions.Length);
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++)
bytes[i] = Instructions[offset + i];
return bytes;
}
/// <summary>
/// Although this always returns a long, the actually stored data in the instruction set has a dynamic width (anything between 1 and 8 bytes)
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public long ReadDynamic(long offset, out byte length)
{
length = Read(offset, 1)[0];
byte[] bytes = new byte[8];
for (int i = 0; i < length; i++) {
bytes[i] = Instructions[offset + 1 + i];
}
return bytes.ToInt64();
}
public short ReadShort(long offset) => BitConverter.ToInt16(Read(offset, 2));
public int ReadInt(long offset) => BitConverter.ToInt32(Read(offset, 4));
public long ReadLong(long offset) => BitConverter.ToInt64(Read(offset, 8));
public byte[] Serialize()
{
var opCodes = Instructions.Select(i => (byte)i).ToArray();
var constants = Constants.Select(c => c.Unsigned.GetBytes()).ToArray();
byte[] bytes = new byte[sizeof(long) * 2 + opCodes.Length + constants.Length * 8];
Array.Copy(opCodes.LongLength.GetBytes(), 0, bytes, 0, sizeof(long));
Array.Copy((constants.LongLength * sizeof(long)).GetBytes(), 0, bytes, sizeof(long), sizeof(long));
int offset = sizeof(long) * 2;
for (long i = 0; i < opCodes.LongLength; i++) {
bytes[offset++] = opCodes[i];
}
for (long i = 0; i < constants.LongLength; i++) {
for (int j = 0; j < sizeof(long); j++) {
bytes[offset++] = constants[i][j];
}
}
return bytes;
}
public static Segment Deserialize(byte[] data)
{
return null;
}
}