mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2026-04-13 00:22:22 +00:00
Added check to EnumConverter for large enums to prevent optimistic checking
This commit is contained in:
parent
4e2dc564dd
commit
a955ccbc5c
@ -100,6 +100,8 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
private static ConcurrentBag<string> _unknownValuesWarned = new ConcurrentBag<string>();
|
private static ConcurrentBag<string> _unknownValuesWarned = new ConcurrentBag<string>();
|
||||||
private static ConcurrentBag<string> _notOptimalValuesWarned = new ConcurrentBag<string>();
|
private static ConcurrentBag<string> _notOptimalValuesWarned = new ConcurrentBag<string>();
|
||||||
|
|
||||||
|
private const int _optimisticValueCountThreshold = 6;
|
||||||
|
|
||||||
internal class NullableEnumConverter : JsonConverter<T?>
|
internal class NullableEnumConverter : JsonConverter<T?>
|
||||||
{
|
{
|
||||||
private readonly EnumConverter<T> _enumConverter;
|
private readonly EnumConverter<T> _enumConverter;
|
||||||
@ -165,9 +167,10 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
if (_mappingToEnum == null)
|
if (_mappingToEnum == null)
|
||||||
CreateMapping();
|
CreateMapping();
|
||||||
|
|
||||||
|
bool optimisticCheckDone = false;
|
||||||
if (RunOptimistic)
|
if (RunOptimistic)
|
||||||
{
|
{
|
||||||
var resultOptimistic = GetValueOptimistic(ref reader);
|
var resultOptimistic = GetValueOptimistic(ref reader, ref optimisticCheckDone);
|
||||||
if (resultOptimistic != null)
|
if (resultOptimistic != null)
|
||||||
return resultOptimistic.Value;
|
return resultOptimistic.Value;
|
||||||
}
|
}
|
||||||
@ -189,7 +192,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetValue(stringValue, out var result))
|
if (!GetValue(stringValue, optimisticCheckDone, out var result))
|
||||||
{
|
{
|
||||||
// Note: checking this here and before the GetValue seems redundant but it allows enum mapping for empty strings
|
// Note: checking this here and before the GetValue seems redundant but it allows enum mapping for empty strings
|
||||||
if (string.IsNullOrWhiteSpace(stringValue))
|
if (string.IsNullOrWhiteSpace(stringValue))
|
||||||
@ -209,7 +212,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunOptimistic && !isNumber)
|
if (optimisticCheckDone)
|
||||||
{
|
{
|
||||||
if (!_notOptimalValuesWarned.Contains(stringValue))
|
if (!_notOptimalValuesWarned.Contains(stringValue))
|
||||||
{
|
{
|
||||||
@ -232,11 +235,21 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
/// Try to get the enum value based on the string value using the Utf8JsonReader's ValueTextEquals method.
|
/// Try to get the enum value based on the string value using the Utf8JsonReader's ValueTextEquals method.
|
||||||
/// This is an optimization to avoid string allocations when possible, but can only match case sensitively
|
/// This is an optimization to avoid string allocations when possible, but can only match case sensitively
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static T? GetValueOptimistic(ref Utf8JsonReader reader)
|
private static T? GetValueOptimistic(ref Utf8JsonReader reader, ref bool optimisticCheckDone)
|
||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
|
{
|
||||||
|
optimisticCheckDone = false;
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mappingToEnum!.Count >= _optimisticValueCountThreshold)
|
||||||
|
{
|
||||||
|
optimisticCheckDone = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
optimisticCheckDone = true;
|
||||||
foreach (var item in _mappingToEnum!)
|
foreach (var item in _mappingToEnum!)
|
||||||
{
|
{
|
||||||
if (reader.ValueTextEquals(item.StringValue))
|
if (reader.ValueTextEquals(item.StringValue))
|
||||||
@ -246,13 +259,13 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool GetValue(string value, out T? result)
|
private static bool GetValue(string value, bool optimisticCheckDone, out T? result)
|
||||||
{
|
{
|
||||||
if (_mappingToEnum != null)
|
if (_mappingToEnum != null)
|
||||||
{
|
{
|
||||||
EnumMapping? mapping = null;
|
EnumMapping? mapping = null;
|
||||||
// If we tried the optimistic path first we already know its not case match
|
// If we tried the optimistic path first we already know its not case match
|
||||||
if (!RunOptimistic)
|
if (!optimisticCheckDone)
|
||||||
{
|
{
|
||||||
// Try match on full equals
|
// Try match on full equals
|
||||||
foreach (var item in _mappingToEnum)
|
foreach (var item in _mappingToEnum)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user