diff --git a/Dashboard/CommandMachine/CommandEngine.cs b/Dashboard/CommandMachine/CommandEngine.cs index bf9efb7..7ef2a9c 100644 --- a/Dashboard/CommandMachine/CommandEngine.cs +++ b/Dashboard/CommandMachine/CommandEngine.cs @@ -170,5 +170,63 @@ namespace Dashboard.CommandMachine iterator.Dequeue(); } } + + private static readonly Dictionary s_serializers = new Dictionary(); + + /// + /// Add a custom serializer to the command engine. + /// + /// Type object type. + /// The serializer. + /// True to allow overwriting. + public static void AddSerializer(ICommandListSerializer serializer, bool overwrite = false) + { + if (overwrite) + { + s_serializers[typeof(T)] = serializer; + } + else + { + s_serializers.Add(typeof(T), serializer); + } + } + + /// + /// Add a custom serializer to the command engine. + /// + /// Type object type. + /// The serializer. + /// True to allow overwriting. + public static void AddSerializer(ICommandListSerializer serializer, bool overwrite = false) + => AddSerializer((ICommandListSerializer)serializer, overwrite); + + /// + /// Get a serializer for the given object. + /// + /// The object type. + /// Required parameter for the C# type inference to work. + /// The serializer. + public static ICommandListSerializer GetSerializer(ICommandListSerializable? value) + where T : ICommandListSerializable, new() + { + if (!s_serializers.TryGetValue(typeof(T), out var serializer)) + { + serializer = new CommandListSerializableSerializer(); + AddSerializer(serializer); + } + + return (ICommandListSerializer)serializer; + } + + /// + /// Get a serializer for the given object. + /// + /// The object type. + /// Required parameter for the C# type inference to work. + /// The serializer. + public static ICommandListSerializer GetSerializer(T? value) + { + return (ICommandListSerializer)s_serializers[typeof(T)]; + } } } \ No newline at end of file diff --git a/Dashboard/CommandMachine/CommandList.cs b/Dashboard/CommandMachine/CommandList.cs index 0f251b5..5464953 100644 --- a/Dashboard/CommandMachine/CommandList.cs +++ b/Dashboard/CommandMachine/CommandList.cs @@ -3,7 +3,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; namespace Dashboard.CommandMachine { @@ -316,6 +315,27 @@ namespace Dashboard.CommandMachine } } + /// + /// Serialize an object into the command list. + /// + /// The type of the value to serialize. + /// What to write into the command list. + public void Write(T value) + { + CommandEngine.GetSerializer(value).Serialize(value, this); + } + + /// + /// Serialize an object into the command list. + /// + /// The type of the value to serialize. + /// What to write into the command list. + public void Write(ICommandListSerializable value) + where T : ICommandListSerializable, new() + { + CommandEngine.GetSerializer(value).Serialize((T)value, this); + } + public CommandQueue GetEnumerator() => new CommandQueue(_frames); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); @@ -372,6 +392,28 @@ namespace Dashboard.CommandMachine public Frame Peek() => TryPeek(out Frame frame) ? frame : throw new Exception("No more frames left."); + /// + /// Deserialize an object from the command queue. + /// + /// Type of the object to deserialize. + /// The deserialized value. + public void Read([NotNull] out T? value) + { + value = CommandEngine.GetSerializer(default(T)).Deserialize(this); + } + + /// + /// Deserialize an object from the command queue. + /// + /// Type of the object to deserialize. + /// The deserialized value. + public void Read([NotNull] out ICommandListSerializable? value) + where T : ICommandListSerializable, new() + { + value = CommandEngine.GetSerializer(value = null).Deserialize(this); + } + + /// public bool MoveNext() { if (_current + 1 < _frames.Count) @@ -382,6 +424,7 @@ namespace Dashboard.CommandMachine return false; } + /// public void Reset() { _current = -1; diff --git a/Dashboard/CommandMachine/FrameType.cs b/Dashboard/CommandMachine/FrameType.cs index e909b8d..fd93131 100644 --- a/Dashboard/CommandMachine/FrameType.cs +++ b/Dashboard/CommandMachine/FrameType.cs @@ -1,17 +1,68 @@ namespace Dashboard.CommandMachine { + /// + /// Enumeration of command types in the Dashboard command lists. + /// public enum FrameType { + /// + /// A null value. + /// None, + + /// + /// A command frame. + /// Command, + + /// + /// An integer frame. + /// IVec1, + + /// + /// A two dimensional integer vector frame. + /// IVec2, + + /// + /// A three dimensional integer vector frame. + /// IVec3, + + /// + /// A four dimensional integer vector frame. + /// IVec4, + + /// + /// A floating point frame. + /// Vec1, + + /// + /// A two dimensional floating point vector frame. + /// Vec2, + + /// + /// A three dimensional floating point vector frame. + /// Vec3, + + /// + /// A four dimensional floating point vector frame. + /// Vec4, + + /// + /// A serialized object frame. + /// + Serialized, + + /// + /// A .Net object frame. + /// Object, } } \ No newline at end of file diff --git a/Dashboard/CommandMachine/Serializers.cs b/Dashboard/CommandMachine/Serializers.cs new file mode 100644 index 0000000..4b4e9ec --- /dev/null +++ b/Dashboard/CommandMachine/Serializers.cs @@ -0,0 +1,69 @@ + +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace Dashboard.CommandMachine +{ + public interface ICommandListSerializable { } + + /// + /// Interface for objects that can be serialized into the Dashboard command stream. + /// + public interface ICommandListSerializable : ICommandListSerializable + { + /// + /// Seralize object. + /// + /// The object to serialize into. + void Serialize(CommandList list); + + /// + /// Deserialize object. + /// + /// The command queue to deserialize from. + void Deserialize(CommandQueue queue); + } + + /// + /// Base interface for all Command List serializers. + /// + public interface ICommandListSerializer { } + + public interface ICommandListSerializer : ICommandListSerializer + { + /// + /// Serialize an object into the command list. + /// + /// The object to serialize. + /// The command list to serialize into. + void Serialize(T value, CommandList list); + + /// + /// Deserialize an object from the command queue. + /// + /// The command queue. + /// The object deserialized from the command queue. + [return: NotNull] + T Deserialize(CommandQueue queue); + } + + /// + /// Class for automatic serialization of objects. + /// + /// The object type to convert. + internal class CommandListSerializableSerializer : ICommandListSerializer + where T : ICommandListSerializable, new() + { + public T Deserialize(CommandQueue queue) + { + T value = new T(); + value.Deserialize(queue); + return value; + } + + public void Serialize(T value, CommandList list) + { + value.Serialize(list); + } + } +} \ No newline at end of file