Skip to content

Commit

Permalink
Merge pull request #107 from greymistcube/refactor/integer-equality
Browse files Browse the repository at this point in the history
Streamline `Integer` equality and comparison
  • Loading branch information
greymistcube authored Oct 19, 2023
2 parents e69a322 + b06117a commit 7a7c0c0
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 61 deletions.
112 changes: 112 additions & 0 deletions Bencodex.Tests/Types/IntegerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,118 @@ public void Constructors()
IntegerGeneric(i => new Integer(i.ToString(locale), locale));
}

[Fact]
public void Equality()
{
short s = 5;
int i = 5;
long l = 5;
BigInteger b = new BigInteger(5);
Integer x = new Integer(5);
object os = s;
object oi = i;
object ol = l;
object ob = b;
object ox = x;

#pragma warning disable CS1718 // Comparison made to same variable
Assert.True(x == x);
Assert.True(x.Equals(x));
Assert.True(x.Equals(ox));
Assert.True(ox.Equals(x));
Assert.True(ox.Equals(ox));
#pragma warning restore CS1718

Assert.True(s == x);
Assert.True(i == x);
Assert.True(l == x);
Assert.True(b == x);

Assert.True(x == s);
Assert.True(x == i);
Assert.True(x == l);
Assert.True(x == b);

Assert.True(s.Equals(x));
Assert.True(i.Equals(x));
Assert.True(l.Equals(x));
Assert.True(b.Equals(x));

Assert.True(x.Equals(s));
Assert.True(x.Equals(i));
Assert.True(x.Equals(l));
Assert.True(x.Equals(b));

Assert.False(s.Equals(ox));
Assert.False(i.Equals(ox));
Assert.False(l.Equals(ox));
Assert.False(b.Equals(ox));

Assert.False(x.Equals(os));
Assert.False(x.Equals(oi));
Assert.False(x.Equals(ol));
Assert.False(x.Equals(ob));

Assert.False(os.Equals(x));
Assert.False(oi.Equals(x));
Assert.False(ol.Equals(x));
Assert.False(ob.Equals(x));

Assert.False(os.Equals(ox));
Assert.False(oi.Equals(ox));
Assert.False(ol.Equals(ox));
Assert.False(ob.Equals(ox));

Assert.False(ox.Equals(os));
Assert.False(ox.Equals(oi));
Assert.False(ox.Equals(ol));
Assert.False(ox.Equals(ob));
}

[Fact]
public void Comparison()
{
short s = 5;
int i = 5;
long l = 5;
BigInteger b = new BigInteger(5);
Integer x = new Integer(5);
Integer? n = null;
object os = s;
object oi = i;
object ol = l;
object ob = b;
object ox = x;
object on = null;

Assert.Equal(0, x.CompareTo(x));
Assert.Equal(0, x.CompareTo(ox));
Assert.Equal(1, x.CompareTo(n));
Assert.Equal(1, x.CompareTo(on));

// NOTE: This behavior is different from comparing a primitive type
// to a BigInteger; this is due to implicit operators present for the Integer type
Assert.Equal(0, s.CompareTo(x));
Assert.Equal(0, i.CompareTo(x));
Assert.Equal(0, l.CompareTo(x));
Assert.Equal(0, b.CompareTo(x));

Assert.Equal(0, x.CompareTo(s));
Assert.Equal(0, x.CompareTo(i));
Assert.Equal(0, x.CompareTo(l));
Assert.Equal(0, x.CompareTo(b));

Assert.Throws<ArgumentException>(() => s.CompareTo(ox));
Assert.Throws<ArgumentException>(() => i.CompareTo(ox));
Assert.Throws<ArgumentException>(() => l.CompareTo(ox));
Assert.Throws<ArgumentException>(() => b.CompareTo(ox));

Assert.Throws<ArgumentException>(() => x.CompareTo(os));
Assert.Throws<ArgumentException>(() => x.CompareTo(oi));
Assert.Throws<ArgumentException>(() => x.CompareTo(ol));
Assert.Throws<ArgumentException>(() => x.CompareTo(ob));
}

[Fact]
public void Kind()
{
Expand Down
128 changes: 67 additions & 61 deletions Bencodex/Types/Integer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ namespace Bencodex.Types
{
public struct Integer :
IValue,
IEquatable<BigInteger>,
IEquatable<Integer>,
IComparable<BigInteger>,
IComparable<Integer>,
IComparable
{
Expand Down Expand Up @@ -155,83 +153,91 @@ public static implicit operator Integer(ulong i)
return new Integer(i);
}

public static bool operator ==(Integer a, Integer b)
{
return a.Equals(b);
}
public static bool operator ==(Integer a, Integer b) => a.Equals(b);

public static bool operator !=(Integer a, Integer b)
{
return !(a == b);
}
public static bool operator !=(Integer a, Integer b) => !(a == b);

public static bool operator ==(Integer a, BigInteger b)
{
return a.Value.Equals(b);
}
public static bool operator ==(Integer a, short b) => a.Equals(b);

public static bool operator !=(Integer a, BigInteger b)
{
return !(a == b);
}
public static bool operator !=(Integer a, short b) => !(a == b);

public static bool operator ==(BigInteger a, Integer b)
{
return a.Equals(b.Value);
}
public static bool operator ==(Integer a, ushort b) => a.Equals(b);

public static bool operator !=(BigInteger a, Integer b)
{
return !(a == b);
}
public static bool operator !=(Integer a, ushort b) => !(a == b);

public static bool operator ==(Integer a, int b) => a.Equals(b);

public static bool operator !=(Integer a, int b) => !(a == b);

public static bool operator ==(Integer a, uint b) => a.Equals(b);

public static bool operator !=(Integer a, uint b) => !(a == b);

public static bool operator ==(Integer a, long b) => a.Equals(b);

public static bool operator !=(Integer a, long b) => !(a == b);

public static bool operator ==(Integer a, ulong b) => a.Equals(b);

public static bool operator !=(Integer a, ulong b) => !(a == b);

public static bool operator ==(Integer a, BigInteger b) => a.Equals(b);

public static bool operator !=(Integer a, BigInteger b) => !(a == b);

public static bool operator ==(short a, Integer b) => a.Equals(b);

public static bool operator !=(short a, Integer b) => !(a == b);

public static bool operator ==(ushort a, Integer b) => a.Equals(b);

public static bool operator !=(ushort a, Integer b) => !(a == b);

int IComparable.CompareTo(object obj)
public static bool operator ==(int a, Integer b) => a.Equals(b);

public static bool operator !=(int a, Integer b) => !(a == b);

public static bool operator ==(uint a, Integer b) => a.Equals(b);

public static bool operator !=(uint a, Integer b) => !(a == b);

public static bool operator ==(long a, Integer b) => a.Equals(b);

public static bool operator !=(long a, Integer b) => !(a == b);

public static bool operator ==(ulong a, Integer b) => a.Equals(b);

public static bool operator !=(ulong a, Integer b) => !(a == b);

public static bool operator ==(BigInteger a, Integer b) => a.Equals(b);

public static bool operator !=(BigInteger a, Integer b) => !(a == b);

public int CompareTo(object? obj)
{
if (obj is Integer i)
if (obj is null)
{
return ((IComparable<Integer>)this).CompareTo(i);
return 1;
}

return Value.CompareTo(obj);
}

int IComparable<BigInteger>.CompareTo(BigInteger other)
{
return Value.CompareTo(other);
}
if (obj is Integer i)
{
return CompareTo(i);
}

int IComparable<Integer>.CompareTo(Integer other)
{
return ((IComparable<BigInteger>)this).CompareTo(other.Value);
throw new ArgumentException($"Object must be of type {nameof(Integer)}");
}

bool IEquatable<BigInteger>.Equals(BigInteger other)
public int CompareTo(Integer other)
{
return Value.Equals(other);
return Value.CompareTo(other.Value);
}

bool IEquatable<Integer>.Equals(Integer other)
{
return Value.Equals(other.Value);
}
public override bool Equals(object obj) => obj is Integer other && Equals(other);

bool IEquatable<IValue>.Equals(IValue other) =>
other is Integer o && ((IEquatable<Integer>)this).Equals(o);
public bool Equals(IValue other) => other is Integer i && Equals(i);

public override bool Equals(object obj)
{
switch (obj)
{
case null:
return false;
case Integer other:
return ((IEquatable<Integer>)this).Equals(other);
case BigInteger other:
return ((IEquatable<BigInteger>)this).Equals(other);
default:
return false;
}
}
public bool Equals(Integer other) => Value.Equals(other.Value);

public override int GetHashCode()
{
Expand Down
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ Version 0.15.0

To be released.

- Removed `IEquatable<BigInteger>` and `IComparable<BigInteger>` from
`Integer`. [[#104], [#107]]
- Changed the behaviors of `Integer.Equals()` and `Integer.CompareTo()`
to be more consistent. [[#106], [#107]]
- Removed `CompositeComparer<TA, TB>` struct. [[#109]]

[#104]: https://github.com/planetarium/bencodex.net/issues/104
[#106]: https://github.com/planetarium/bencodex.net/issues/106
[#107]: https://github.com/planetarium/bencodex.net/pull/107
[#109]: https://github.com/planetarium/bencodex.net/pull/109


Expand Down

0 comments on commit 7a7c0c0

Please sign in to comment.