Skip to content

Commit 0c02523

Browse files
committed
polishing
1 parent fbf6da3 commit 0c02523

2 files changed

Lines changed: 33 additions & 12 deletions

File tree

src/StackExchange.Redis/RedisValue.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -369,19 +369,20 @@ internal string RawString()
369369
return false;
370370
}
371371

372-
if (xType == StorageType.Sequence &&
373-
(yType == StorageType.ByteArray || yType == StorageType.MemoryManager))
374-
return x.RawSequence().SequenceEqual(y.RawSpan());
375-
376-
if (yType == StorageType.Sequence &&
377-
(xType == StorageType.ByteArray || xType == StorageType.MemoryManager))
378-
return y.RawSequence().SequenceEqual(x.RawSpan());
379-
380-
if ((xType == StorageType.ByteArray && yType == StorageType.MemoryManager) ||
381-
(xType == StorageType.MemoryManager && yType == StorageType.ByteArray))
382-
return x.RawSpan().SequenceEqual(y.RawSpan());
372+
// both are non-null, non-numeric, and of different kinds; the blob kinds (byte[] / memory /
373+
// sequence) compare by bytes in any combination - and we keep the span-vs-span path for the
374+
// case where neither side is a multi-segment sequence
375+
switch (xType)
376+
{
377+
case StorageType.Sequence when yType is StorageType.ByteArray or StorageType.MemoryManager:
378+
return x.RawSequence().SequenceEqual(y.RawSpan());
379+
case StorageType.ByteArray or StorageType.MemoryManager when yType == StorageType.Sequence:
380+
return y.RawSequence().SequenceEqual(x.RawSpan());
381+
case StorageType.ByteArray or StorageType.MemoryManager when yType is StorageType.ByteArray or StorageType.MemoryManager:
382+
return x.RawSpan().SequenceEqual(y.RawSpan());
383+
}
383384

384-
// otherwise, compare as strings
385+
// otherwise (anything involving a string), compare as strings
385386
return (string?)x == (string?)y;
386387
}
387388

@@ -870,6 +871,7 @@ public static explicit operator double(RedisValue value)
870871
// special values like NaN/Inf are deliberately not handled by Simplify, but need to be considered for casting
871872
StorageType.String when Format.TryParseDouble(value.RawString(), out var d) => d,
872873
StorageType.MemoryManager or StorageType.ByteArray when TryParseDouble(value.RawSpan(), out var d) => d,
874+
StorageType.Sequence when value.TryParse(out double d) => d, // linearizes + handles inf/nan, like the span case above
873875
// anything else: fail
874876
_ => throw new InvalidCastException($"Unable to cast from {value.Type} to double: '{value}'"),
875877
};

tests/StackExchange.Redis.Tests/RedisValueSequenceTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,25 @@ public void MultiSegmentSequence_CompareTo_DifferenceAcrossBoundaries()
206206
Assert.Equal(-expected, Math.Sign(sy.CompareTo(sx))); // antisymmetry
207207
}
208208

209+
[Theory]
210+
[InlineData("123")] // integer-valued
211+
[InlineData("-123")]
212+
[InlineData("123.5")] // fractional
213+
[InlineData("inf")] // special doubles: deliberately not simplified, so they exercise the cast's text fallback
214+
[InlineData("+inf")]
215+
[InlineData("-inf")]
216+
[InlineData("nan")]
217+
public void MultiSegmentSequence_DoubleCast_MatchesByteArray(string text)
218+
{
219+
var bytes = Encoding.UTF8.GetBytes(text);
220+
RedisValue asBytes = bytes; // single-buffer (ByteArray)
221+
RedisValue asSequence = SplitEveryByte(bytes); // multi-buffer (Sequence)
222+
Assert.Equal(RedisValue.StorageType.Sequence, asSequence.Type);
223+
224+
// the (double) cast must behave the same for a sequence as for the equivalent byte[]
225+
Assert.Equal((double)asBytes, (double)asSequence);
226+
}
227+
209228
[Fact]
210229
public void MultiSegmentBytes_RoundTripToArray()
211230
{

0 commit comments

Comments
 (0)