Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Current package versions:

## Unreleased

- Fix `RedisValue` special-value (NaN, Inf, etc) handling when casting from raw/string values to `double` ([#2950 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2950))

## 2.9.11

- Add `HGETDEL`, `HGETEX` and `HSETEX` support ([#2863 by atakavci](https://github.com/StackExchange/StackExchange.Redis/pull/2863))
Expand Down
4 changes: 4 additions & 0 deletions src/StackExchange.Redis/RedisValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,10 @@ public static explicit operator double(RedisValue value)
StorageType.Int64 => value.OverlappedValueInt64,
StorageType.UInt64 => value.OverlappedValueUInt64,
StorageType.Double => value.OverlappedValueDouble,
// special values like NaN/Inf are deliberately not handled by Simplify, but need to be considered for casting
StorageType.String when Format.TryParseDouble((string)value._objectOrSentinel!, out var d) => d,
StorageType.Raw when TryParseDouble(value._memory.Span, out var d) => d,
// anything else: fail
_ => throw new InvalidCastException($"Unable to cast from {value.Type} to double: '{value}'"),
};
}
Expand Down
44 changes: 44 additions & 0 deletions tests/StackExchange.Redis.Tests/RedisResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,48 @@ public void SingleResultConvertibleDirectViaChangeType_TypeCode()
Assert.StrictEqual(123f, Convert.ChangeType(value, TypeCode.Single));
Assert.StrictEqual(123d, Convert.ChangeType(value, TypeCode.Double));
}

[Theory]
[InlineData(ResultType.Double)]
[InlineData(ResultType.BulkString)]
[InlineData(ResultType.SimpleString)]
public void RedisResultParseNaN(ResultType resultType)
{
// https://github.com/redis/NRedisStack/issues/439
var value = RedisResult.Create("NaN", resultType);
Assert.True(double.IsNaN(value.AsDouble()));
}

[Theory]
[InlineData(ResultType.Double)]
[InlineData(ResultType.BulkString)]
[InlineData(ResultType.SimpleString)]
public void RedisResultParseInf(ResultType resultType)
{
// https://github.com/redis/NRedisStack/issues/439
var value = RedisResult.Create("inf", resultType);
Assert.True(double.IsPositiveInfinity(value.AsDouble()));
}

[Theory]
[InlineData(ResultType.Double)]
[InlineData(ResultType.BulkString)]
[InlineData(ResultType.SimpleString)]
public void RedisResultParsePlusInf(ResultType resultType)
{
// https://github.com/redis/NRedisStack/issues/439
var value = RedisResult.Create("+inf", resultType);
Assert.True(double.IsPositiveInfinity(value.AsDouble()));
}

[Theory]
[InlineData(ResultType.Double)]
[InlineData(ResultType.BulkString)]
[InlineData(ResultType.SimpleString)]
public void RedisResultParseMinusInf(ResultType resultType)
{
// https://github.com/redis/NRedisStack/issues/439
var value = RedisResult.Create("-inf", resultType);
Assert.True(double.IsNegativeInfinity(value.AsDouble()));
}
}
Loading