Files
MicrosoftIris/UIX/Microsoft/Iris/Debug/Data/DebuggerMessageFrame.cs
T

144 lines
3.9 KiB
C#
Raw Normal View History

2023-06-01 20:18:53 -05:00
using System;
using System.IO;
using System.Runtime.Serialization;
2023-06-01 20:18:53 -05:00
namespace Microsoft.Iris.Debug.Data;
public class DebuggerMessageFrame
{
2024-01-20 20:32:30 -06:00
private readonly IFormatter _formatter;
private object _value;
private byte[] _data;
2023-06-01 20:18:53 -05:00
2024-01-20 20:32:30 -06:00
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, IFormatter formatter)
2023-06-01 20:18:53 -05:00
{
2024-01-20 20:32:30 -06:00
_formatter = formatter;
2023-06-01 20:18:53 -05:00
TransactionId = transactionId;
Type = type;
2024-01-20 20:32:30 -06:00
}
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, object value, IFormatter formatter)
: this(transactionId, type, formatter)
{
Value = value;
}
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, byte[] data, IFormatter formatter)
: this(transactionId, type, formatter)
{
2023-06-01 20:18:53 -05:00
Data = data;
}
2024-01-20 20:32:30 -06:00
public DebuggerMessageFrame(byte[] bytes, IFormatter formatter)
2023-06-01 20:18:53 -05:00
{
2024-01-20 20:32:30 -06:00
_formatter = formatter;
2023-06-01 20:18:53 -05:00
TransactionId = BitConverter.ToInt64(bytes, 0);
Type = (DebuggerMessageType)BitConverter.ToInt32(bytes, sizeof(long));
2023-06-03 20:34:49 -05:00
int dataOffset = sizeof(long) + sizeof(DebuggerMessageType);
#if NETCOREAPP2_1_OR_GREATER
Data = bytes.AsSpan(dataOffset).ToArray();
#else
Data = new byte[bytes.Length - dataOffset];
bytes.CopyTo(Data, dataOffset);
#endif
2023-06-01 20:18:53 -05:00
}
public long TransactionId { get; set; }
public DebuggerMessageType Type { get; set; }
2024-01-20 20:32:30 -06:00
public object Value
{
get
{
if (_value is null)
{
if (_data is null) throw new ArgumentException("Either a value or data must be specified.");
using MemoryStream stream = new(_data);
_value = _formatter.Deserialize(stream);
}
return _value;
}
set
{
_value = value;
_data = null;
}
}
public byte[] Data
{
get
{
if (_data is null)
{
if (_value is null) throw new ArgumentException("Either a value or data must be specified.");
_data = _value.Serialize(_formatter);
}
return _data;
}
set
{
_data = value;
_value = default;
}
}
2023-06-01 20:18:53 -05:00
public byte[] ToBytes()
{
byte[] bytes = new byte[Data.Length + sizeof(DebuggerMessageType) + sizeof(long)];
#if NET5_0_OR_GREATER
var span = bytes.AsSpan();
BitConverter.TryWriteBytes(span, TransactionId);
BitConverter.TryWriteBytes(span[sizeof(long)..], (int)Type);
#else
var idBytes = BitConverter.GetBytes(TransactionId);
idBytes.CopyTo(bytes, 0);
var typeBytes = BitConverter.GetBytes((int)Type);
typeBytes.CopyTo(bytes, sizeof(long));
#endif
Data.CopyTo(bytes, sizeof(long) + sizeof(DebuggerMessageType));
return bytes;
}
2024-01-20 20:32:30 -06:00
public virtual T GetValue<T>(IFormatter formatter = null)
{
using MemoryStream stream = new(Data);
2024-01-20 20:32:30 -06:00
return (T)(formatter ?? _formatter).Deserialize(stream);
}
2024-01-20 20:32:30 -06:00
public DebuggerMessageFrame<T> Deserialize<T>(IFormatter formatter = null)
=> new(TransactionId, Type, GetValue<T>(formatter), formatter ?? _formatter);
}
public class DebuggerMessageFrame<T> : DebuggerMessageFrame
{
public DebuggerMessageFrame(byte[] bytes, IFormatter formatter) : base(bytes, formatter)
{
}
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, IFormatter formatter) : base(transactionId, type, formatter)
{
}
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, T value, IFormatter formatter) : base(transactionId, type, value, formatter)
{
}
public DebuggerMessageFrame(long transactionId, DebuggerMessageType type, byte[] data, IFormatter formatter) : base(transactionId, type, data, formatter)
{
}
public T GetValue() => (T)Value;
2023-06-01 20:18:53 -05:00
}