Hi,
I'm getting some invalid results with the library when decoding large numbers. I discovered this whilst I was adding some unit tests to stress test my implementation.
It occurs when I have a custom alphabet. I've not tried other alphabets.
For the purposes of setting the salt, I've used a guid and I've also set the min hash length to 15, and all tests use the same values.
I'm hoping it's just a range thing caused by this particular alphabet, but perhaps other custom alphabets can error like this.
Of course, doubt I'd ever see ids that big, but it did concern me a bit when the unit test on long.MaxValue
failed, and spurred me on to find what the highest number I could decode correctly is ( it's 9549259626800016 , see below).
The hash for long.MaxValue
in this case is 5jEpN7mlkn0BRvq
Passing Example
As a control on my salt and min hash length, here is a basic example where I do not customise the alphabet, and the test passes as expected:
[Fact]
public void DefaultAlphabet()
{
var longToTest = long.MaxValue;
string SALT = "0741cbe4-2140-4615-8b5b-93294aa52c9f";
int MIN_HASH_LENGTH = 15;
var hashids = new HashidsNet.Hashids(SALT, MIN_HASH_LENGTH);
var hashed = hashids.EncodeLong(longToTest);
var decoded = hashids.DecodeLong(hashed);
if (decoded.Length == 0)
{
throw new Exception("No result returned");
}
Assert.Equal(longToTest, decoded[0]);
}
Failing Examples
Here is an example where I customise the alphabet, by removing all instances of i (lower and upper) as well as the number 1. In this case, no result is returned and the exception "No result returned" is thrown.
I found that the highest number I can get to pass is 9549259626800016
. If I try to run the custom alphabet test with 9549259626800017
, it fails with the same exception as long.MaxValue
.
long.MaxValue fails ๐
[Fact]
public void HashIdsCustomSanityTest()
{
var longToTest = long.MaxValue;
string SALT = "0741cbe4-2140-4615-8b5b-93294aa52c9f";
int MIN_HASH_LENGTH = 15;
string ALPHABET = "abcdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ234567890";
var hashids = new HashidsNet.Hashids(
SALT, MIN_HASH_LENGTH, ALPHABET
);
var hashed = hashids.EncodeLong(longToTest);
var decoded = hashids.DecodeLong(hashed);
if (decoded.Length == 0)
{
throw new Exception("No result returned");
}
Assert.Equal(longToTest, decoded[0]);
}
9549259626800016 passes ๐
[Fact]
public void HashIdsCustomSanityTest()
{
var longToTest = 9549259626800016;
string SALT = "0741cbe4-2140-4615-8b5b-93294aa52c9f";
int MIN_HASH_LENGTH = 15;
string ALPHABET = "abcdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ234567890";
var hashids = new HashidsNet.Hashids(
SALT, MIN_HASH_LENGTH, ALPHABET
);
var hashed = hashids.EncodeLong(longToTest);
var decoded = hashids.DecodeLong(hashed);
if (decoded.Length == 0)
{
throw new Exception("No result returned");
}
Assert.Equal(longToTest, decoded[0]);
}
9549259626800017 fails ๐
Same exception thrown as above.
[Fact]
public void HashIdsCustomSanityTest()
{
var longToTest = 9549259626800017;
string SALT = "0741cbe4-2140-4615-8b5b-93294aa52c9f";
int MIN_HASH_LENGTH = 15;
string ALPHABET = "abcdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ234567890";
var hashids = new HashidsNet.Hashids(
SALT, MIN_HASH_LENGTH, ALPHABET
);
var hashed = hashids.EncodeLong(longToTest);
var decoded = hashids.DecodeLong(hashed);
if (decoded.Length == 0)
{
throw new Exception("No result returned");
}
Assert.Equal(longToTest, decoded[0]);
}