1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-12-15 18:26:35 +00:00
This commit is contained in:
JKorf 2025-11-18 20:01:25 +01:00 committed by Jkorf
parent 2cf0afa353
commit 9975d47e28
6 changed files with 106 additions and 126 deletions

View File

@ -27,6 +27,6 @@ namespace CryptoExchange.Net.Protobuf.Converters.Protobuf
return result; return result;
} }
public abstract MessageInfo GetMessageInfo(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType); public abstract string GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
} }
} }

View File

@ -11,7 +11,7 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
/// <summary> /// <summary>
/// Get message info /// Get message info
/// </summary> /// </summary>
MessageInfo GetMessageInfo(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType); string? GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
/// <summary> /// <summary>
/// Deserialize to the provided type /// Deserialize to the provided type

View File

@ -10,73 +10,41 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
{ {
public int Priority { get; set; } public int Priority { get; set; }
public bool ForceIfFound { get; set; } public bool ForceIfFound { get; set; }
public MessageFieldReference[] Fields { get; set; } public MessageFieldReference[] Fields { get; set; }
public Func<SearchResult, string> MessageIdentifier { get; set; } public Func<Dictionary<string, string>, string> MessageIdentifier { get; set; }
public Func<SearchResult, Type?> TypeIdentifier { get; set; }
public bool Statisfied(SearchResult result) public bool Statisfied(Dictionary<string, string> result)
{ {
foreach(var field in Fields) foreach(var field in Fields)
{ {
if (!result.Contains(field.Name)) if (!result.ContainsKey(field.Name))
return false; return false;
} }
return true; return true;
} }
}
public MessageInfo ProduceMessageInfo(SearchResult result) public enum FieldType
{ {
return new MessageInfo ArrayIndex,
{ Property
DeserializationType = TypeIdentifier(result),
Identifier = MessageIdentifier(result)
};
}
} }
public class MessageFieldReference 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 Type Type { get; set; }
}
public class SearchResult // For FieldType.Property
{ public string Name { get; set; }
public Dictionary<string, string>? _stringValues; // For FieldType.ArrayIndex
public Dictionary<string, int>? _intValues; public int Index { get; set; }
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();
}
} }
public class MessageEvalutorFieldReference public class MessageEvalutorFieldReference

View File

@ -1,20 +1,20 @@
using System; //using System;
namespace CryptoExchange.Net.Converters.MessageParsing //namespace CryptoExchange.Net.Converters.MessageParsing
{ //{
/// <summary> // /// <summary>
/// Message info // /// Message info
/// </summary> // /// </summary>
public ref struct MessageInfo // public ref struct MessageInfo
{ // {
/// <summary> // /// <summary>
/// The deserialization type // /// The deserialization type
/// </summary> // /// </summary>
public Type? DeserializationType { get; set; } // public Type? DeserializationType { get; set; }
/// <summary> // /// <summary>
/// The listen identifier // /// The listen identifier
/// </summary> // /// </summary>
public string? Identifier { get; set; } // public string? Identifier { get; set; }
} // }
} //}

View File

@ -20,14 +20,14 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
protected abstract MessageEvaluator[] MessageEvaluators { get; } protected abstract MessageEvaluator[] MessageEvaluators { get; }
private readonly SearchResult _searchResult = new SearchResult(); private readonly Dictionary<string, string> _searchResult = new();
/// <inheritdoc /> /// <inheritdoc />
public virtual MessageInfo GetMessageInfo(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType) public virtual string? GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType)
{ {
InitializeSearch(); InitializeSearch();
_searchResult.Reset(); _searchResult.Clear();
var reader = new Utf8JsonReader(data); var reader = new Utf8JsonReader(data);
while (reader.Read()) while (reader.Read())
{ {
@ -45,44 +45,54 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
bool written = false; bool written = false;
foreach (var field in _searchFields) foreach (var field in _searchFields)
{ {
if (reader.CurrentDepth == field.Field.Level if (field.Field.Depth != null)
&& reader.ValueTextEquals(field.Field.Name))
{ {
reader.Read(); if (field.Field.Depth != reader.CurrentDepth)
continue;
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;
} }
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) if (!written)
continue; continue;
if (_topEvaluator.Statisfied(_searchResult)) 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; break;
} }
foreach (var evaluator in MessageEvaluators) foreach (var evaluator in MessageEvaluators)
{ {
if (evaluator.Statisfied(_searchResult)) if (evaluator.Statisfied(_searchResult))
return evaluator.ProduceMessageInfo(_searchResult); return evaluator.MessageIdentifier(_searchResult);
} }
return new MessageInfo(); return null;
} }
protected bool _initialized; protected bool _initialized;
@ -102,7 +112,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
_topEvaluator ??= evaluator; _topEvaluator ??= evaluator;
foreach (var field in evaluator.Fields) 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 (existing != null)
{ {
if (evaluator.ForceIfFound) if (evaluator.ForceIfFound)
@ -122,8 +132,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
}); });
} }
if (field.Level > _maxSearchDepth) if (field.Depth > _maxSearchDepth)
_maxSearchDepth = field.Level; _maxSearchDepth = field.Depth.Value;
if (field.MaxDepth > _maxSearchDepth)
_maxSearchDepth = field.MaxDepth.Value;
} }
} }

View File

@ -533,43 +533,42 @@ namespace CryptoExchange.Net.Sockets
_logger.ReceivedData(SocketId, originalData); _logger.ReceivedData(SocketId, originalData);
} }
var messageInfo = messageConverter.GetMessageInfo(data, type); var messageIdentifier = messageConverter.GetMessageIdentifier(data, type);
if (messageInfo.DeserializationType == null) 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()));
// Both deserialization type and identifier null, can't process return;
_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 Type? deserializationType = null;
lock (_listenersLock) // 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(messageIdentifier)?.FirstOrDefault();
{ if (handler == null)
var handler = subscription.MessageMatcher.GetHandlerLinks(messageInfo.Identifier)?.FirstOrDefault(); continue;
if (handler == null)
continue;
_logger.LogTrace("Message type determined based on identifier"); _logger.LogTrace("Message type determined based on identifier");
messageInfo.DeserializationType = handler.DeserializationType; deserializationType = handler.DeserializationType;
break; 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;
} }
} }
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; object result;
try try
{ {
if (messageInfo.DeserializationType == typeof(string)) if (deserializationType == typeof(string))
{ {
#if NETSTANDARD2_0 #if NETSTANDARD2_0
result = Encoding.UTF8.GetString(data.ToArray()); result = Encoding.UTF8.GetString(data.ToArray());
@ -579,7 +578,7 @@ namespace CryptoExchange.Net.Sockets
} }
else else
{ {
result = messageConverter.Deserialize(data, messageInfo.DeserializationType!); result = messageConverter.Deserialize(data, deserializationType);
} }
} }
catch(Exception ex) catch(Exception ex)
@ -601,7 +600,7 @@ namespace CryptoExchange.Net.Sockets
{ {
foreach (var subscription in _listeners) foreach (var subscription in _listeners)
{ {
var links = subscription.MessageMatcher.GetHandlerLinks(messageInfo.Identifier!); var links = subscription.MessageMatcher.GetHandlerLinks(messageIdentifier!);
foreach (var link in links) foreach (var link in links)
{ {
processed = true; processed = true;
@ -612,7 +611,7 @@ namespace CryptoExchange.Net.Sockets
if (!processed) 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()))));
} }
} }