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