1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-12-14 01:33:26 +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;
}
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>
/// Get message info
/// </summary>
MessageInfo GetMessageInfo(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
string? GetMessageIdentifier(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType);
/// <summary>
/// Deserialize to the provided type

View File

@ -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<SearchResult, string> MessageIdentifier { get; set; }
public Func<SearchResult, Type?> TypeIdentifier { get; set; }
public Func<Dictionary<string, string>, string> MessageIdentifier { get; set; }
public bool Statisfied(SearchResult result)
public bool Statisfied(Dictionary<string, string> 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<string, string>? _stringValues;
public Dictionary<string, int>? _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

View File

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

View File

@ -20,14 +20,14 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
protected abstract MessageEvaluator[] MessageEvaluators { get; }
private readonly SearchResult _searchResult = new SearchResult();
private readonly Dictionary<string, string> _searchResult = new();
/// <inheritdoc />
public virtual MessageInfo GetMessageInfo(ReadOnlySpan<byte> data, WebSocketMessageType? webSocketMessageType)
public virtual string? GetMessageIdentifier(ReadOnlySpan<byte> 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;
}
}

View File

@ -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()))));
}
}