Доработки и внедрение cbor сериализации

This commit is contained in:
2025-02-27 00:12:52 +03:00
parent b4ccfdd51c
commit 46732da780
12 changed files with 213 additions and 64 deletions
+3 -1
View File
@@ -1,6 +1,7 @@
using System.Net; using System.Net;
using Example.Backend; using Example.Backend;
using mROA.Abstract; using mROA.Abstract;
using mROA.Cbor;
using mROA.Codegen; using mROA.Codegen;
using mROA.Implementation; using mROA.Implementation;
using mROA.Implementation.Backend; using mROA.Implementation.Backend;
@@ -12,7 +13,8 @@ class Program
public static void Main(string[] args) public static void Main(string[] args)
{ {
var builder = new FullMixBuilder(); var builder = new FullMixBuilder();
builder.UseJsonSerialisation(); // builder.UseJsonSerialisation();
builder.Modules.Add(new CborSerializationToolkit());
builder.Modules.Add(new BackendIdentityGenerator()); builder.Modules.Add(new BackendIdentityGenerator());
builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule), builder.UseNetworkGateway(new IPEndPoint(IPAddress.Loopback, 4567), typeof(NextGenerationInteractionModule),
builder.GetModule<IIdentityGenerator>()!); builder.GetModule<IIdentityGenerator>()!);
+4 -1
View File
@@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Example.Frontend; using Example.Frontend;
using Example.Shared; using Example.Shared;
using mROA.Cbor;
using mROA.Codegen; using mROA.Codegen;
using mROA.Implementation; using mROA.Implementation;
using mROA.Implementation.Backend; using mROA.Implementation.Backend;
@@ -17,7 +18,9 @@ class Program
{ {
var builder = new FullMixBuilder(); var builder = new FullMixBuilder();
new RemoteTypeBinder(); new RemoteTypeBinder();
builder.Modules.Add(new JsonSerializationToolkit()); // builder.Modules.Add(new JsonSerializationToolkit());
builder.Modules.Add(new CborSerializationToolkit());
builder.Modules.Add(new RemoteContextRepository()); builder.Modules.Add(new RemoteContextRepository());
builder.Modules.Add(new NextGenerationInteractionModule()); builder.Modules.Add(new NextGenerationInteractionModule());
builder.Modules.Add(new RepresentationModule()); builder.Modules.Add(new RepresentationModule());
+1
View File
@@ -9,6 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj" />
<ProjectReference Include="..\mROA\mROA.csproj"/> <ProjectReference Include="..\mROA\mROA.csproj"/>
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/> <ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
+140 -45
View File
@@ -26,38 +26,43 @@ namespace mROA.Cbor
writer.Encode(destination); writer.Encode(destination);
} }
public T Deserialize<T>(byte[] rawData, IEndPointContext context) public T Deserialize<T>(byte[] rawData, IEndPointContext? context)
{ {
return (T)Deserialize(rawData, typeof(T), context); return (T)Deserialize(rawData, typeof(T), context) ?? default;
} }
public object Deserialize(byte[] rawData, Type type, IEndPointContext context) public object? Deserialize(byte[] rawData, Type type, IEndPointContext? context)
{ {
return Deserialize(rawData.AsMemory(), type, context); return Deserialize(rawData.AsMemory(), type, context);
} }
public T Deserialize<T>(ReadOnlyMemory<byte> rawData, IEndPointContext context) public T Deserialize<T>(ReadOnlyMemory<byte> rawMemory, IEndPointContext? context)
{ {
return (T)Deserialize(rawData, typeof(T), context); return (T)Deserialize(rawMemory, typeof(T), context);
} }
public object Deserialize(ReadOnlyMemory<byte> rawData, Type type, IEndPointContext context) public object? Deserialize(ReadOnlyMemory<byte> rawMemory, Type type, IEndPointContext? context)
{ {
var reader = new CborReader(rawData); var reader = new CborReader(rawMemory);
return ReadData(reader, type, context); return ReadData(reader, type, context);
} }
public T Cast<T>(object nonCasted, IEndPointContext context) public T Cast<T>(object nonCasted, IEndPointContext? context)
{ {
return (T)Cast(nonCasted, typeof(T), context); return (T)Cast(nonCasted, typeof(T), context);
} }
public object Cast(object nonCasted, Type type, IEndPointContext context) public object Cast(object nonCasted, Type type, IEndPointContext? context)
{ {
if (nonCasted.GetType() == type)
return nonCasted;
if (nonCasted is PreParsedValue preParsed)
return preParsed.ToObject(type, context);
return null; return null;
} }
private void WriteData(object? obj, CborWriter writer, IEndPointContext context) private void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
{ {
switch (obj) switch (obj)
{ {
@@ -94,6 +99,9 @@ namespace mROA.Cbor
case DateTimeOffset dto: case DateTimeOffset dto:
writer.WriteDateTimeOffset(dto); writer.WriteDateTimeOffset(dto);
break; break;
case Guid g:
writer.WriteByteString(g.ToByteArray());
break;
case byte[] bytes: case byte[] bytes:
writer.WriteByteString(bytes); writer.WriteByteString(bytes);
break; break;
@@ -104,13 +112,14 @@ namespace mROA.Cbor
WriteList(enumerable, writer, context); WriteList(enumerable, writer, context);
break; break;
case ISharedObject sharedObject: case ISharedObject sharedObject:
sharedObject.EndPointContext = context; if (context != null)
sharedObject.EndPointContext = context;
WriteObject(sharedObject, writer, context); WriteObject(sharedObject, writer, context);
break; break;
default: default:
if (obj.GetType().IsEnum) if (obj.GetType().IsEnum)
{ {
writer.WriteUInt32((uint)obj); writer.WriteInt32((int)obj);
break; break;
} }
@@ -119,7 +128,7 @@ namespace mROA.Cbor
} }
} }
private void WriteList(IList list, CborWriter writer, IEndPointContext context) private void WriteList(IList list, CborWriter writer, IEndPointContext? context)
{ {
writer.WriteStartArray(list.Count); writer.WriteStartArray(list.Count);
@@ -129,7 +138,7 @@ namespace mROA.Cbor
writer.WriteEndArray(); writer.WriteEndArray();
} }
private void WriteDictionary(IDictionary dictionary, CborWriter writer, IEndPointContext context) private void WriteDictionary(IDictionary dictionary, CborWriter writer, IEndPointContext? context)
{ {
writer.WriteStartMap(dictionary.Count); writer.WriteStartMap(dictionary.Count);
var keysEnumerator = dictionary.Keys.GetEnumerator(); var keysEnumerator = dictionary.Keys.GetEnumerator();
@@ -147,7 +156,7 @@ namespace mROA.Cbor
(valuesEnumerator as IDisposable)?.Dispose(); (valuesEnumerator as IDisposable)?.Dispose();
} }
private void WriteObject(object obj, CborWriter writer, IEndPointContext context) private void WriteObject(object obj, CborWriter writer, IEndPointContext? context)
{ {
var type = obj.GetType(); var type = obj.GetType();
var properties = FilterProperties(type.GetProperties()); var properties = FilterProperties(type.GetProperties());
@@ -155,7 +164,7 @@ namespace mROA.Cbor
WriteList(values, writer, context); WriteList(values, writer, context);
} }
private object ReadData(CborReader reader, Type? type, IEndPointContext context) private object? ReadData(CborReader reader, Type? type, IEndPointContext? context)
{ {
var state = reader.PeekState(); var state = reader.PeekState();
switch (state) switch (state)
@@ -164,20 +173,24 @@ namespace mROA.Cbor
return reader.ReadBoolean(); return reader.ReadBoolean();
case CborReaderState.UnsignedInteger: case CborReaderState.UnsignedInteger:
case CborReaderState.NegativeInteger: case CborReaderState.NegativeInteger:
if (type == typeof(int)) if (type == typeof(int) || type is { IsEnum: true })
return reader.ReadInt32(); return reader.ReadInt32();
if (type == typeof(long)) if (type == typeof(long))
return reader.ReadInt64(); return reader.ReadInt64();
if (type == typeof(uint) || type.IsEnum) if (type == typeof(uint))
return reader.ReadUInt32(); return reader.ReadUInt32();
if (type == typeof(ulong)) if (type == typeof(ulong))
return reader.ReadUInt64(); return reader.ReadUInt64();
break;
return reader.ReadInt32();
case CborReaderState.ByteString: case CborReaderState.ByteString:
if (type == typeof(Guid))
return new Guid(reader.ReadByteString());
return reader.ReadByteString(); return reader.ReadByteString();
case CborReaderState.TextString: case CborReaderState.TextString:
return reader.ReadTextString(); return reader.ReadTextString();
case CborReaderState.Null: case CborReaderState.Null:
reader.ReadNull();
return null; return null;
case CborReaderState.DoublePrecisionFloat: case CborReaderState.DoublePrecisionFloat:
return reader.ReadDouble(); return reader.ReadDouble();
@@ -207,36 +220,51 @@ namespace mROA.Cbor
} }
private Array ReadList(CborReader reader, Type? type, IEndPointContext context) private IList ReadList(CborReader reader, Type? type, IEndPointContext? context)
{ {
var length = reader.ReadStartArray(); var length = reader.ReadStartArray();
if (length != null) if (length != null)
{ {
var elementType = typeof(object); var elementType = typeof(object);
if (type is { IsArray: true }) if (type is { IsArray: true })
{
elementType = type.GetElementType(); elementType = type.GetElementType();
else if (typeof(IList).IsAssignableFrom(type)) Array values = Array.CreateInstance(elementType, length.Value);
for (int i = 0; i < length; i++)
{
values.SetValue(ReadData(reader, elementType, context), i);
}
reader.ReadEndArray();
return values;
}
if (typeof(IList).IsAssignableFrom(type))
elementType = type.GetGenericArguments()[0]; elementType = type.GetGenericArguments()[0];
else elementType = typeof(object);
Array values = Array.CreateInstance(elementType, length.Value); Type genericListType = typeof(List<>).MakeGenericType(elementType);
var list = (IList)Activator.CreateInstance(genericListType, length);
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
values.SetValue(ReadData(reader, elementType, context), i); list.Add(ReadData(reader, elementType, context));
} }
reader.ReadEndArray(); reader.ReadEndArray();
return values;
return list;
return null;
} }
reader.ReadEndArray(); return null;
return Array.Empty<object>();
} }
private IDictionary ReadDictionary(CborReader reader, Type type, IEndPointContext context) private IDictionary ReadDictionary(CborReader reader, Type type, IEndPointContext? context)
{ {
var dictionaryInstance = (Activator.CreateInstance(type) as IDictionary)!; var dictionaryInstance = (Activator.CreateInstance(type) as IDictionary)!;
var length = reader.ReadStartArray(); var length = reader.ReadStartArray();
@@ -253,8 +281,13 @@ namespace mROA.Cbor
return dictionaryInstance; return dictionaryInstance;
} }
private object ReadObject(CborReader reader, Type type, IEndPointContext context) private object ReadObject(CborReader reader, Type type, IEndPointContext? context)
{ {
if (type == typeof(object))
{
return new PreParsedValue(ReadList(reader, null, context) as List<object>);
}
var instance = Activator.CreateInstance(type)!; var instance = Activator.CreateInstance(type)!;
FillObject(instance, type, reader, context); FillObject(instance, type, reader, context);
@@ -262,32 +295,50 @@ namespace mROA.Cbor
return instance; return instance;
} }
private ISharedObject ReadSharedObject(CborReader reader, Type type, IEndPointContext context) private ISharedObject ReadSharedObject(CborReader reader, Type type, IEndPointContext? context)
{ {
var sharedObject = (Activator.CreateInstance(type) as ISharedObject)!; var sharedObject = (Activator.CreateInstance(type) as ISharedObject)!;
sharedObject.EndPointContext = context; if (context != null)
{
sharedObject.EndPointContext = context;
}
FillObject(sharedObject, type, reader, context); FillObject(sharedObject, type, reader, context);
return sharedObject; return sharedObject;
} }
private void FillObject(object obj, Type type, CborReader reader, IEndPointContext context) private void FillObject(object obj, Type type, CborReader reader, IEndPointContext? context)
{ {
var properties = FilterProperties(type.GetProperties()); try
_ = reader.ReadStartArray();
foreach (var property in properties)
{ {
var value = ReadData(reader, property.PropertyType, context); var propertyInfos = type.GetProperties();
property.SetValue(obj, value); var properties = FilterProperties(propertyInfos);
}
reader.ReadEndArray(); var length = reader.ReadStartArray();
#if TRACE
Console.WriteLine($"Reading list of {length} objects, {properties.Count} properties found");
#endif
for (var index = 0; index < length; index++)
{
var property = properties[index];
var value = ReadData(reader, property.PropertyType, context);
property.SetValue(obj, value);
}
reader.ReadEndArray();
}
catch (Exception e)
{
Console.WriteLine(e);
reader.ReadEndArray();
throw;
}
} }
private List<PropertyInfo> FilterProperties(PropertyInfo[] properties) public static List<PropertyInfo> FilterProperties(PropertyInfo[] properties)
{ {
var finalProperties = new List<PropertyInfo>(properties.Length); var finalProperties = new List<PropertyInfo>(properties.Length);
foreach (var property in properties) foreach (var property in properties)
@@ -298,5 +349,49 @@ namespace mROA.Cbor
return finalProperties; return finalProperties;
} }
public void Inject<T>(T dependency)
{
}
public byte[] Serialize<T>(T objectToSerialize)
{
return Serialize(objectToSerialize, typeof(T));
}
public byte[] Serialize(object objectToSerialize, Type type)
{
return Serialize(objectToSerialize, context: null);
}
public T Deserialize<T>(byte[] rawData)
{
return Deserialize<T>(rawData: rawData, context: null);
}
public object? Deserialize(byte[] rawData, Type type)
{
return Deserialize(rawData: rawData, type, context: null);
}
public T Deserialize<T>(Span<byte> rawData)
{
return Deserialize<T>(rawData.ToArray().AsMemory(), context: null);
}
public object? Deserialize(Span<byte> rawData, Type type)
{
return Deserialize(rawData: rawData.ToArray(), type: type);
}
public T Cast<T>(object nonCasted)
{
return Cast<T>(nonCasted: nonCasted, context: null);
}
public object Cast(object nonCasted, Type type)
{
return Cast(nonCasted: nonCasted, type: type, context: null);
}
} }
} }
+9 -9
View File
@@ -3,15 +3,15 @@ using mROA.Abstract;
namespace mROA.Cbor namespace mROA.Cbor
{ {
public interface IContextualSerializationToolKit public interface IContextualSerializationToolKit : ISerializationToolkit
{ {
byte[] Serialize(object objectToSerialize, IEndPointContext context); byte[] Serialize(object objectToSerialize, IEndPointContext? context);
void Serialize(object objectToSerialize, Span<byte> destination, IEndPointContext context); void Serialize(object objectToSerialize, Span<byte> destination, IEndPointContext? context);
T Deserialize<T>(byte[] rawData, IEndPointContext context); T Deserialize<T>(byte[] rawData, IEndPointContext? context);
object Deserialize(byte[] rawData, Type type, IEndPointContext context); object? Deserialize(byte[] rawData, Type type, IEndPointContext? context);
T Deserialize<T>(ReadOnlyMemory<byte> rawData, IEndPointContext context); T Deserialize<T>(ReadOnlyMemory<byte> rawMemory, IEndPointContext? context);
object Deserialize(ReadOnlyMemory<byte> rawData, Type type, IEndPointContext context); object? Deserialize(ReadOnlyMemory<byte> rawMemory, Type type, IEndPointContext? context);
T Cast<T>(object nonCasted, IEndPointContext context); T Cast<T>(object nonCasted, IEndPointContext? context);
object Cast(object nonCasted, Type type, IEndPointContext context); object? Cast(object nonCasted, Type type, IEndPointContext? context);
} }
} }
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using mROA.Abstract;
using mROA.Implementation;
namespace mROA.Cbor
{
public class PreParsedValue
{
public List<object> Properties { get; set; }
public PreParsedValue(List<object> properties)
{
Properties = properties;
}
public object? ToObject(Type type, IEndPointContext? context)
{
var instance = Activator.CreateInstance(type);
if (instance == null)
return null;
if (instance is ISharedObject sharedObject && context != null)
{
sharedObject.EndPointContext = context;
}
var properties = CborSerializationToolkit.FilterProperties(type.GetProperties());
for (var index = 0; index < properties.Count; index++)
{
var property = properties[index];
property.SetValue(instance, Properties[index]);
}
return instance;
}
}
}
+7
View File
@@ -21,6 +21,7 @@ public class CborTest
IntValue = 123, IntValue = 123,
DoubleValue = 3.14159, DoubleValue = 3.14159,
StringValue = "abc", StringValue = "abc",
EnumValue = TestEnum.X,
CollectionElements = CollectionElements =
[ [
_basicCollectionElement, _basicCollectionElement,
@@ -69,6 +70,7 @@ public class CborTest
public int IntValue { get; set; } public int IntValue { get; set; }
public double DoubleValue { get; set; } public double DoubleValue { get; set; }
public string StringValue { get; set; } public string StringValue { get; set; }
public TestEnum EnumValue { get; set; }
public int[] IntArray { get; set; } public int[] IntArray { get; set; }
public List<BasicCollectionElement> CollectionElements { get; set; } public List<BasicCollectionElement> CollectionElements { get; set; }
@@ -115,4 +117,9 @@ public class CborTest
return HashCode.Combine(A, B, C); return HashCode.Combine(A, B, C);
} }
} }
public enum TestEnum
{
X = -5, Y, Z
}
} }
+2 -2
View File
@@ -10,8 +10,8 @@ namespace mROA.Abstract
object? Deserialize(byte[] rawData, Type type); object? Deserialize(byte[] rawData, Type type);
T? Deserialize<T>(Span<byte> rawData); T? Deserialize<T>(Span<byte> rawData);
object? Deserialize(Span<byte> rawData, Type type); object? Deserialize(Span<byte> rawData, Type type);
T Cast<T>(object nonCasted); T? Cast<T>(object nonCasted);
object Cast(object nonCasted, Type type); object? Cast(object nonCasted, Type type);
} }
} }
+2 -1
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using mROA.Implementation.Attributes;
// ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
@@ -20,7 +21,7 @@ namespace mROA.Implementation
public int CommandId { get; set; } public int CommandId { get; set; }
public int ObjectId { get; set; } = -1; public int ObjectId { get; set; } = -1;
[JsonIgnore] [SerializationIgnore]
public Type? ParameterType { get; set; } public Type? ParameterType { get; set; }
public object? Parameter { get; set; } public object? Parameter { get; set; }
@@ -1,6 +1,7 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.Attributes;
// ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedAutoPropertyAccessor.Global
@@ -9,9 +10,9 @@ namespace mROA.Implementation.CommandExecution
public class FinalCommandExecution : ICommandExecution public class FinalCommandExecution : ICommandExecution
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
[JsonIgnore] [SerializationIgnore]
public int ClientId { get; set; } public int ClientId { get; set; }
[JsonIgnore] [SerializationIgnore]
public int CommandId { get; set; } public int CommandId { get; set; }
} }
@@ -1,11 +1,12 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using mROA.Implementation.Attributes;
namespace mROA.Implementation.CommandExecution namespace mROA.Implementation.CommandExecution
{ {
public class TypedFinalCommandExecution : FinalCommandExecution<object> public class TypedFinalCommandExecution : FinalCommandExecution<object>
{ {
[JsonIgnore] [SerializationIgnore]
// ReSharper disable once UnusedAutoPropertyAccessor.Global // ReSharper disable once UnusedAutoPropertyAccessor.Global
public Type? Type { get; set; } public Type? Type { get; set; }
} }
+3 -2
View File
@@ -2,6 +2,7 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.Attributes;
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
#pragma warning disable CS8618, CS9264 #pragma warning disable CS8618, CS9264
@@ -41,7 +42,7 @@ namespace mROA.Implementation
public class SharedObject<T> : ISharedObject where T : notnull public class SharedObject<T> : ISharedObject where T : notnull
{ {
[JsonIgnore] [SerializationIgnore]
public IEndPointContext EndPointContext { get; set; } = new EndPointContext public IEndPointContext EndPointContext { get; set; } = new EndPointContext
{ {
RealRepository = TransmissionConfig.RealContextRepository, RealRepository = TransmissionConfig.RealContextRepository,
@@ -88,7 +89,7 @@ namespace mROA.Implementation
} }
} }
[JsonIgnore] [SerializationIgnore]
public T Value { get; private set; } public T Value { get; private set; }
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global