Implementing IComparable<MessageId>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index be9ea7d..a9141a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@
## [Unreleased]
+### Added
+
+- MessageId implements IComparable\<MessageId\>
+
### Fixed
- Do not throw exceptions when disposing consumers, readers or producers
diff --git a/src/DotPulsar/MessageId.cs b/src/DotPulsar/MessageId.cs
index 27efc62..53bbaa9 100644
--- a/src/DotPulsar/MessageId.cs
+++ b/src/DotPulsar/MessageId.cs
@@ -20,7 +20,7 @@
/// <summary>
/// Unique identifier of a single message.
/// </summary>
- public sealed class MessageId : IEquatable<MessageId>
+ public sealed class MessageId : IEquatable<MessageId>, IComparable<MessageId>
{
static MessageId()
{
@@ -72,6 +72,38 @@
/// </summary>
public int BatchIndex => Data.BatchIndex;
+ public int CompareTo(MessageId? other)
+ {
+ if (other is null)
+ return 1;
+
+ var result = LedgerId.CompareTo(other.LedgerId);
+ if (result != 0)
+ return result;
+
+ result = EntryId.CompareTo(other.EntryId);
+ if (result != 0)
+ return result;
+
+ result = Partition.CompareTo(other.Partition);
+ if (result != 0)
+ return result;
+
+ return BatchIndex.CompareTo(other.BatchIndex);
+ }
+
+ public static bool operator >(MessageId x, MessageId y)
+ => x is not null && x.CompareTo(y) >= 1;
+
+ public static bool operator <(MessageId x, MessageId y)
+ => x is not null ? x.CompareTo(y) <= -1 : y is not null;
+
+ public static bool operator >=(MessageId x, MessageId y)
+ => x is not null ? x.CompareTo(y) >= 0 : y is null;
+
+ public static bool operator <=(MessageId x, MessageId y)
+ => x is not null ? x.CompareTo(y) <= 0 : true;
+
public override bool Equals(object? o)
=> o is MessageId id && Equals(id);
diff --git a/tests/DotPulsar.Tests/MessageIdTests.cs b/tests/DotPulsar.Tests/MessageIdTests.cs
index b3d1077..1b87744 100644
--- a/tests/DotPulsar.Tests/MessageIdTests.cs
+++ b/tests/DotPulsar.Tests/MessageIdTests.cs
@@ -12,7 +12,6 @@
* limitations under the License.
*/
-// We cannot assume consumers of this library will obey the nullability guarantees
#nullable disable
namespace DotPulsar.Tests
@@ -24,9 +23,82 @@
public class MessageIdTests
{
[Fact]
+ public void CompareTo_GivenTheSameValues_ShouldBeEqual()
+ {
+ var m1 = new MessageId(1, 2, 3, 4);
+ var m2 = new MessageId(1, 2, 3, 4);
+
+ m1.CompareTo(m2).Should().Be(0);
+ (m1 < m2).Should().BeFalse();
+ (m1 > m2).Should().BeFalse();
+ (m1 >= m2).Should().BeTrue();
+ (m1 <= m2).Should().BeTrue();
+ }
+
+ [Fact]
+ public void CompareTo_GivenAllNull_ShouldBeEqual()
+ {
+ MessageId m1 = null;
+ MessageId m2 = null;
+
+ (m1 < m2).Should().BeFalse();
+ (m1 > m2).Should().BeFalse();
+ (m1 <= m2).Should().BeTrue();
+ (m1 >= m2).Should().BeTrue();
+ }
+
+ [Fact]
+ public void CompareTo_GivenOneNull_ShouldFollowNull()
+ {
+ var m1 = new MessageId(1, 2, 3, 4);
+ MessageId m2 = null;
+
+ m1.CompareTo(m2).Should().BePositive();
+ (m1 < m2).Should().BeFalse();
+ (m1 > m2).Should().BeTrue();
+ (m1 <= m2).Should().BeFalse();
+ (m1 >= m2).Should().BeTrue();
+
+ (m2 < m1).Should().BeTrue();
+ (m2 > m1).Should().BeFalse();
+ (m2 <= m1).Should().BeTrue();
+ (m2 >= m1).Should().BeFalse();
+ }
+
+ [Theory]
+ [InlineData(2, 2, 3, 4)] // LegderId is greater
+ [InlineData(1, 3, 3, 4)] // EntryId is greater
+ [InlineData(1, 2, 4, 4)] // Partition is greater
+ [InlineData(1, 2, 3, 5)] // BatchIndex is greater
+ public void CompareTo_GivenCurrentFollowsArgument_ShouldReturnPositive(ulong ledgerId, ulong entryId, int partition, int batchIndex)
+ {
+ var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
+ var m2 = new MessageId(1, 2, 3, 4);
+
+ m1.CompareTo(m2).Should().BePositive();
+ (m1 > m2).Should().BeTrue();
+ (m1 < m2).Should().BeFalse();
+ }
+
+ [Theory]
+ [InlineData(0, 2, 3, 4)] // LegderId is less
+ [InlineData(1, 1, 3, 4)] // EntryId is less
+ [InlineData(1, 2, 2, 4)] // Partition is less
+ [InlineData(1, 2, 3, 3)] // BatchIndex is less
+ public void CompareTo_GivenCurrentPrecedesArgument_ShouldReturnNegative(ulong ledgerId, ulong entryId, int partition, int batchIndex)
+ {
+ var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
+ var m2 = new MessageId(1, 2, 3, 4);
+
+ m1.CompareTo(m2).Should().BeNegative();
+ (m1 < m2).Should().BeTrue();
+ (m1 > m2).Should().BeFalse();
+ }
+
+ [Fact]
public void Equals_GivenTheSameObject_ShouldBeEqual()
{
- var m1 = new MessageId(1234, 5678, 9876, 5432);
+ var m1 = new MessageId(1, 2, 3, 4);
var m2 = m1;
m1.Equals(m2).Should().BeTrue();
@@ -37,19 +109,23 @@
[Fact]
public void Equals_GivenTheSameValues_ShouldBeEqual()
{
- var m1 = new MessageId(1234, 5678, 9876, 5432);
- var m2 = new MessageId(1234, 5678, 9876, 5432);
+ var m1 = new MessageId(1, 2, 3, 4);
+ var m2 = new MessageId(1, 2, 3, 4);
m1.Equals(m2).Should().BeTrue();
(m1 == m2).Should().BeTrue();
(m1 != m2).Should().BeFalse();
}
- [Fact]
- public void Equals_GivenDifferentValues_ShouldNotBeEqual()
+ [Theory]
+ [InlineData(0, 2, 3, 4)] // LegerId not the same
+ [InlineData(1, 0, 3, 4)] // EntryId not the same
+ [InlineData(1, 2, 0, 4)] // Partition not the same
+ [InlineData(1, 2, 3, 0)] // BatchIndex not the same
+ public void Equals_GivenDifferentValues_ShouldNotBeEqual(ulong ledgerId, ulong entryId, int partition, int batchIndex)
{
- var m1 = new MessageId(1234, 5678, 9876, 5432);
- var m2 = new MessageId(9876, 6432, 1234, 6678);
+ var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
+ var m2 = new MessageId(1, 2, 3, 4);
m1.Equals(m2).Should().BeFalse();
(m1 == m2).Should().BeFalse();
@@ -70,7 +146,7 @@
[Fact]
public void Equals_GivenOneNull_ShouldNotBeEqual()
{
- var m1 = new MessageId(1234, 5678, 9876, 5432);
+ var m1 = new MessageId(1, 2, 3, 4);
MessageId m2 = null;
(m1 == null).Should().BeFalse();
@@ -80,3 +156,5 @@
}
}
}
+
+#nullable enable