mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-12-14 01:33:26 +00:00
wip
This commit is contained in:
parent
2cf0afa353
commit
9975d47e28
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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; }
|
||||
// }
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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()))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user