Implement command iterator.
This commit is contained in:
parent
1b6bf09f95
commit
1067d3e188
@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
namespace Dashboard.Drawing
|
||||||
{
|
{
|
||||||
public class DrawQueue : IDisposable
|
public class DrawQueue : IEnumerable<ICommandFrame>, IDisposable
|
||||||
{
|
{
|
||||||
private readonly HashList<IDrawExtension> _extensions = new HashList<IDrawExtension>();
|
private readonly HashList<IDrawExtension> _extensions = new HashList<IDrawExtension>();
|
||||||
private readonly HashList<IDrawCommand> _commands = new HashList<IDrawCommand>();
|
private readonly HashList<IDrawCommand> _commands = new HashList<IDrawCommand>();
|
||||||
@ -118,6 +121,10 @@ namespace Dashboard.Drawing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Enumerator GetEnumerator() => new Enumerator(this);
|
||||||
|
IEnumerator<ICommandFrame> IEnumerable<ICommandFrame>.GetEnumerator() => GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
private static int ToVlq(int value, Span<byte> bytes)
|
private static int ToVlq(int value, Span<byte> bytes)
|
||||||
{
|
{
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
@ -125,8 +132,13 @@ namespace Dashboard.Drawing
|
|||||||
else if (bytes.Length < 5)
|
else if (bytes.Length < 5)
|
||||||
throw new ArgumentOutOfRangeException(nameof(bytes), "Must at least be five bytes long.");
|
throw new ArgumentOutOfRangeException(nameof(bytes), "Must at least be five bytes long.");
|
||||||
|
|
||||||
int i;
|
if (value == 0)
|
||||||
|
{
|
||||||
|
bytes[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
for (i = 0; i < 5 && value != 0; i++, value >>= 7)
|
for (i = 0; i < 5 && value != 0; i++, value >>= 7)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
@ -138,21 +150,25 @@ namespace Dashboard.Drawing
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FromVlq(ReadOnlySpan<byte> bytes)
|
private static int FromVlq(ReadOnlySpan<byte> bytes, out int value)
|
||||||
{
|
{
|
||||||
int value = 0;
|
value = 0;
|
||||||
|
|
||||||
for (int i = 0; i < bytes.Length; i++)
|
int i;
|
||||||
|
for (i = 0; i < bytes.Length; i++)
|
||||||
{
|
{
|
||||||
byte b = bytes[i];
|
byte b = bytes[i];
|
||||||
|
|
||||||
value = (value << 7) | b;
|
value = (value << 7) | b;
|
||||||
|
|
||||||
if ((b & (1 << 7)) == 0)
|
if ((b & (1 << 7)) == 0)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -195,8 +211,125 @@ namespace Dashboard.Drawing
|
|||||||
Write(command, bytes);
|
Write(command, bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Enumerator : ICommandFrame, IEnumerator<ICommandFrame>
|
||||||
|
{
|
||||||
|
private readonly DrawQueue _queue;
|
||||||
|
private readonly byte[] _stream;
|
||||||
|
private int _length;
|
||||||
|
private int _index = -1;
|
||||||
|
private int _paramsIndex = -1;
|
||||||
|
private int _paramLength = 0;
|
||||||
|
private IDrawCommand? _current = null;
|
||||||
|
|
||||||
|
public ICommandFrame Current => this;
|
||||||
|
|
||||||
|
object? IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
public IDrawCommand Command => _current ?? throw new InvalidOperationException();
|
||||||
|
|
||||||
|
public bool HasParameters { get; private set; }
|
||||||
|
|
||||||
|
public Enumerator(DrawQueue queue)
|
||||||
|
{
|
||||||
|
_queue = queue;
|
||||||
|
_stream = queue._commandStream.GetBuffer();
|
||||||
|
_length = (int)queue._commandStream.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (_index >= _length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_index == -1)
|
||||||
|
_index = 0;
|
||||||
|
|
||||||
|
_index += FromVlq(_stream[_index .. (_index + 5)], out int command);
|
||||||
|
_current = _queue.Command[command];
|
||||||
|
|
||||||
|
HasParameters = _current.Length != 0;
|
||||||
|
|
||||||
|
if (!HasParameters)
|
||||||
|
{
|
||||||
|
_paramsIndex = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
if (_current.Length < 0)
|
||||||
|
{
|
||||||
|
_index += FromVlq(_stream[_index .. (_index + 5)], out length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
length = _current.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paramsIndex = _index;
|
||||||
|
_paramLength = length;
|
||||||
|
_index += length;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_index = -1;
|
||||||
|
_current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? GetParameter()
|
||||||
|
{
|
||||||
|
return _current?.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetParameter<T>()
|
||||||
|
{
|
||||||
|
if (_current is IDrawCommand<T> command)
|
||||||
|
{
|
||||||
|
return command.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength))!;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetParameter<T>([NotNullWhen(true)] out T? parameter)
|
||||||
|
{
|
||||||
|
if (_current is IDrawCommand<T> command)
|
||||||
|
{
|
||||||
|
parameter = command.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength))!;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parameter = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ICommandFrame
|
||||||
|
{
|
||||||
|
public IDrawCommand Command { get; }
|
||||||
|
|
||||||
|
public bool HasParameters { get; }
|
||||||
|
|
||||||
|
public object? GetParameter();
|
||||||
|
|
||||||
|
public T GetParameter<T>();
|
||||||
|
|
||||||
|
public bool TryGetParameter<T>([NotNullWhen(true)] out T? parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface IDrawController
|
public interface IDrawController
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -12,4 +12,12 @@ queue.Point(Vector3.Zero, 2f, fg);
|
|||||||
queue.Line(Vector3.Zero, Vector3.One * 2, 2f, bg);
|
queue.Line(Vector3.Zero, Vector3.One * 2, 2f, bg);
|
||||||
queue.Rect(Vector3.UnitX, 2 * Vector3.UnitX + Vector3.UnitY, fg, bg, 2f);
|
queue.Rect(Vector3.UnitX, 2 * Vector3.UnitX + Vector3.UnitY, fg, bg, 2f);
|
||||||
|
|
||||||
|
foreach (ICommandFrame frame in queue)
|
||||||
|
{
|
||||||
|
Console.WriteLine("{0}", frame.Command.Name);
|
||||||
|
|
||||||
|
if (frame.HasParameters)
|
||||||
|
Console.WriteLine("Param: {0}", frame.GetParameter());
|
||||||
|
}
|
||||||
|
|
||||||
Debugger.Break();
|
Debugger.Break();
|
||||||
|
Loading…
Reference in New Issue
Block a user