From 9975d47e287169681da83ba0fc7733d710610182 Mon Sep 17 00:00:00 2001 From: JKorf Date: Tue, 18 Nov 2025 20:01:25 +0100 Subject: [PATCH] wip --- .../Protobuf/DynamicProtobufConverter.cs | 2 +- .../DynamicConverters/IMessageConverter.cs | 2 +- .../MessageConverterTypes.cs | 66 +++++------------- .../DynamicConverters/MessageInfo.cs | 36 +++++----- .../SystemTextJson/DynamicJsonConverter.cs | 67 +++++++++++-------- .../Sockets/SocketConnection.cs | 59 ++++++++-------- 6 files changed, 106 insertions(+), 126 deletions(-) diff --git a/CryptoExchange.Net.Protobuf/Converters/Protobuf/DynamicProtobufConverter.cs b/CryptoExchange.Net.Protobuf/Converters/Protobuf/DynamicProtobufConverter.cs index 39529df..59a8bfc 100644 --- a/CryptoExchange.Net.Protobuf/Converters/Protobuf/DynamicProtobufConverter.cs +++ b/CryptoExchange.Net.Protobuf/Converters/Protobuf/DynamicProtobufConverter.cs @@ -27,6 +27,6 @@ namespace CryptoExchange.Net.Protobuf.Converters.Protobuf return result; } - public abstract MessageInfo GetMessageInfo(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType); + public abstract string GetMessageIdentifier(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType); } } diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IMessageConverter.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IMessageConverter.cs index 6030002..87f5a59 100644 --- a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IMessageConverter.cs +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IMessageConverter.cs @@ -11,7 +11,7 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters /// /// Get message info /// - MessageInfo GetMessageInfo(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType); + string? GetMessageIdentifier(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType); /// /// Deserialize to the provided type diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs index bc13af0..3eec591 100644 --- a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs @@ -10,73 +10,41 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters { public int Priority { get; set; } public bool ForceIfFound { get; set; } + public MessageFieldReference[] Fields { get; set; } - public Func MessageIdentifier { get; set; } - public Func TypeIdentifier { get; set; } + public Func, string> MessageIdentifier { get; set; } - public bool Statisfied(SearchResult result) + public bool Statisfied(Dictionary result) { foreach(var field in Fields) { - if (!result.Contains(field.Name)) + if (!result.ContainsKey(field.Name)) return false; } return true; } + } - public MessageInfo ProduceMessageInfo(SearchResult result) - { - return new MessageInfo - { - DeserializationType = TypeIdentifier(result), - Identifier = MessageIdentifier(result) - }; - } + public enum FieldType + { + ArrayIndex, + Property } public class MessageFieldReference { - public int Level { get; set; } - public string Name { get; set; } + + public FieldType FieldType { get; set; } + public int? Depth { get; set; } + public int? MaxDepth { get; set; } public Type Type { get; set; } - } - public class SearchResult - { - public Dictionary? _stringValues; - public Dictionary? _intValues; - - public int GetInt(string name) => _intValues[name]; - public string GetString(string name) => _stringValues[name]; - - public void WriteInt(string name, int value) - { - _intValues ??= new(); - _intValues[name] = value; - } - public void WriteString(string name, string value) - { - _stringValues ??= new(); - _stringValues[name] = value; - } - - public bool Contains(string name) - { - if (_intValues?.ContainsKey(name) == true) - return true; - if (_stringValues?.ContainsKey(name) == true) - return true; - - return false; - } - - public void Reset() - { - _intValues?.Clear(); - _stringValues?.Clear(); - } + // For FieldType.Property + public string Name { get; set; } + // For FieldType.ArrayIndex + public int Index { get; set; } } public class MessageEvalutorFieldReference diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageInfo.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageInfo.cs index fa6c859..1cb3c09 100644 --- a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageInfo.cs +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageInfo.cs @@ -1,20 +1,20 @@ -using System; +//using System; -namespace CryptoExchange.Net.Converters.MessageParsing -{ - /// - /// Message info - /// - public ref struct MessageInfo - { - /// - /// The deserialization type - /// - public Type? DeserializationType { get; set; } - /// - /// The listen identifier - /// - public string? Identifier { get; set; } - } +//namespace CryptoExchange.Net.Converters.MessageParsing +//{ +// /// +// /// Message info +// /// +// public ref struct MessageInfo +// { +// /// +// /// The deserialization type +// /// +// public Type? DeserializationType { get; set; } +// /// +// /// The listen identifier +// /// +// public string? Identifier { get; set; } +// } -} +//} diff --git a/CryptoExchange.Net/Converters/SystemTextJson/DynamicJsonConverter.cs b/CryptoExchange.Net/Converters/SystemTextJson/DynamicJsonConverter.cs index d9b63da..cd06fc5 100644 --- a/CryptoExchange.Net/Converters/SystemTextJson/DynamicJsonConverter.cs +++ b/CryptoExchange.Net/Converters/SystemTextJson/DynamicJsonConverter.cs @@ -20,14 +20,14 @@ namespace CryptoExchange.Net.Converters.SystemTextJson protected abstract MessageEvaluator[] MessageEvaluators { get; } - private readonly SearchResult _searchResult = new SearchResult(); + private readonly Dictionary _searchResult = new(); /// - public virtual MessageInfo GetMessageInfo(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType) + public virtual string? GetMessageIdentifier(ReadOnlySpan data, WebSocketMessageType? webSocketMessageType) { InitializeSearch(); - _searchResult.Reset(); + _searchResult.Clear(); var reader = new Utf8JsonReader(data); while (reader.Read()) { @@ -45,44 +45,54 @@ namespace CryptoExchange.Net.Converters.SystemTextJson bool written = false; foreach (var field in _searchFields) { - if (reader.CurrentDepth == field.Field.Level - && reader.ValueTextEquals(field.Field.Name)) + if (field.Field.Depth != null) { - reader.Read(); - - if (field.Field.Type == typeof(int)) - _searchResult.WriteInt(field.Field.Name, reader.GetInt32()); - else - _searchResult.WriteString(field.Field.Name, reader.GetString()!); - - if (field.ForceEvaluator != null) - { - // Force the immediate return upon encountering this field - return field.ForceEvaluator.ProduceMessageInfo(_searchResult); - } - - written = true; - break; + if (field.Field.Depth != reader.CurrentDepth) + continue; } + else + { + if (reader.CurrentDepth > field.Field.MaxDepth!.Value) + continue; + } + + if (!reader.ValueTextEquals(field.Field.Name)) + continue; + + reader.Read(); + + if (field.Field.Type == typeof(int)) + _searchResult[field.Field.Name] = reader.GetInt32().ToString(); + else + _searchResult[field.Field.Name] = reader.GetString()!; + + if (field.ForceEvaluator != null) + { + // Force the immediate return upon encountering this field + return field.ForceEvaluator.MessageIdentifier(_searchResult); + } + + written = true; + break; } if (!written) continue; if (_topEvaluator.Statisfied(_searchResult)) - return _topEvaluator.ProduceMessageInfo(_searchResult); + return _topEvaluator.MessageIdentifier(_searchResult); - if (_searchFields.All(x => _searchResult.Contains(x.Field.Name))) + if (_searchFields.All(x => _searchResult.ContainsKey(x.Field.Name))) break; } foreach (var evaluator in MessageEvaluators) { if (evaluator.Statisfied(_searchResult)) - return evaluator.ProduceMessageInfo(_searchResult); + return evaluator.MessageIdentifier(_searchResult); } - return new MessageInfo(); + return null; } protected bool _initialized; @@ -102,7 +112,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson _topEvaluator ??= evaluator; foreach (var field in evaluator.Fields) { - var existing = _searchFields.SingleOrDefault(x => x.Field.Name == field.Name && x.Field.Level == field.Level); + var existing = _searchFields.SingleOrDefault(x => x.Field.Name == field.Name /*&& x.Field.Level == field.Level*/); if (existing != null) { if (evaluator.ForceIfFound) @@ -122,8 +132,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson }); } - if (field.Level > _maxSearchDepth) - _maxSearchDepth = field.Level; + if (field.Depth > _maxSearchDepth) + _maxSearchDepth = field.Depth.Value; + + if (field.MaxDepth > _maxSearchDepth) + _maxSearchDepth = field.MaxDepth.Value; } } diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs index 19fa029..3b2b18d 100644 --- a/CryptoExchange.Net/Sockets/SocketConnection.cs +++ b/CryptoExchange.Net/Sockets/SocketConnection.cs @@ -533,43 +533,42 @@ namespace CryptoExchange.Net.Sockets _logger.ReceivedData(SocketId, originalData); } - var messageInfo = messageConverter.GetMessageInfo(data, type); - if (messageInfo.DeserializationType == null) + var messageIdentifier = messageConverter.GetMessageIdentifier(data, type); + if (messageIdentifier == null) { - if (messageInfo.Identifier == null) - { - // Both deserialization type and identifier null, can't process - _logger.LogWarning("Failed to evaluate message. Data: {Message}", Encoding.UTF8.GetString(data.ToArray())); - return; - } + // Both deserialization type and identifier null, can't process + _logger.LogWarning("Failed to evaluate message. Data: {Message}", Encoding.UTF8.GetString(data.ToArray())); + return; + } - // Couldn't determine deserialization type, try determine the type based on identifier - lock (_listenersLock) + Type? deserializationType = null; + // Couldn't determine deserialization type, try determine the type based on identifier + lock (_listenersLock) + { + foreach (var subscription in _listeners) { - foreach (var subscription in _listeners) - { - var handler = subscription.MessageMatcher.GetHandlerLinks(messageInfo.Identifier)?.FirstOrDefault(); - if (handler == null) - continue; + var handler = subscription.MessageMatcher.GetHandlerLinks(messageIdentifier)?.FirstOrDefault(); + if (handler == null) + continue; - _logger.LogTrace("Message type determined based on identifier"); - messageInfo.DeserializationType = handler.DeserializationType; - break; - } - } - - if (messageInfo.DeserializationType == null) - { - // No handler found for identifier either, can't process - _logger.LogWarning("Failed to determine message type. Data: {Message}", Encoding.UTF8.GetString(data.ToArray())); - return; + _logger.LogTrace("Message type determined based on identifier"); + deserializationType = handler.DeserializationType; + break; } } + if (deserializationType == null) + { + // No handler found for identifier either, can't process + _logger.LogWarning("Failed to determine message type. Data: {Message}", Encoding.UTF8.GetString(data.ToArray())); + return; + } + + object result; try { - if (messageInfo.DeserializationType == typeof(string)) + if (deserializationType == typeof(string)) { #if NETSTANDARD2_0 result = Encoding.UTF8.GetString(data.ToArray()); @@ -579,7 +578,7 @@ namespace CryptoExchange.Net.Sockets } else { - result = messageConverter.Deserialize(data, messageInfo.DeserializationType!); + result = messageConverter.Deserialize(data, deserializationType); } } catch(Exception ex) @@ -601,7 +600,7 @@ namespace CryptoExchange.Net.Sockets { foreach (var subscription in _listeners) { - var links = subscription.MessageMatcher.GetHandlerLinks(messageInfo.Identifier!); + var links = subscription.MessageMatcher.GetHandlerLinks(messageIdentifier!); foreach (var link in links) { processed = true; @@ -612,7 +611,7 @@ namespace CryptoExchange.Net.Sockets if (!processed) { - _logger.ReceivedMessageNotMatchedToAnyListener(SocketId, messageInfo.Identifier!, string.Join(",", _listeners.Select(x => x.MessageMatcher.HandlerLinks.Select(x => x.ToString())))); + _logger.ReceivedMessageNotMatchedToAnyListener(SocketId, messageIdentifier!, string.Join(",", _listeners.Select(x => x.MessageMatcher.HandlerLinks.Select(x => x.ToString())))); } }