Skip to content

Commit 15ce268

Browse files
authored
Fix Endianness of AsInteger64 and add TreatAsLittleEndian and TreatAsBigEndian
Signed-off-by: Xen <lordofxen@deskasoft.com>
1 parent 38c9dd9 commit 15ce268

File tree

1 file changed

+72
-65
lines changed

1 file changed

+72
-65
lines changed

HashifyNet/Core/DataType/HashValue.cs

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ public static HashValue FromSpan(ValueEndianness endianness, ReadOnlySpan<byte>
133133
return new HashValue(endianness, hash.ToImmutableArray(), bitLength);
134134
}
135135

136+
/// <summary>
137+
/// Creates a new instance using the base class <see cref="HashValue"/>. Override this to create your own instance of <see cref="IHashValue"/> so all the functions of <see cref="HashValue"/> uses your class.
138+
/// </summary>
139+
/// <param name="endianness">The endianness of the hash value.</param>
140+
/// <param name="hash">The immutable hash value.</param>
141+
/// <param name="bitLength">The bit length of the hash value.</param>
142+
/// <returns>A new instance of <see cref="IHashValue"/>.</returns>
143+
protected virtual IHashValue CreateInstance(ValueEndianness endianness, ImmutableArray<byte> hash, int bitLength)
144+
{
145+
return new HashValue(endianness, hash, bitLength);
146+
}
147+
136148
/// <summary>
137149
/// <inheritdoc/>
138150
/// </summary>
@@ -296,12 +308,27 @@ private long AsNumber64()
296308
throw new NotSupportedException("Bit Length greater than 64 is not supported.");
297309
}
298310

299-
byte[] data = AsByteArray();
311+
if (Endianness == ValueEndianness.NotApplicable)
312+
{
313+
throw new NotSupportedException("Values with no endianness cannot be represented in a primitive, please first convert the value to big-endian or little-endian.");
314+
}
300315

316+
byte[] data = AsByteArray();
301317
long num = 0;
302-
for (int i = 0; i < data.Length; ++i)
318+
if (Endianness == ValueEndianness.LittleEndian)
303319
{
304-
num |= (long)data[i] << (8 * i);
320+
for (int i = 0; i < data.Length; ++i)
321+
{
322+
num |= (long)data[i] << (8 * i);
323+
}
324+
}
325+
else // ValueEndianness.BigEndian
326+
{
327+
for (int i = 0; i < data.Length; ++i)
328+
{
329+
int shift = (data.Length - 1 - i) * 8;
330+
num |= (long)data[i] << shift;
331+
}
305332
}
306333

307334
return num;
@@ -327,11 +354,8 @@ private short AsNumber16()
327354
return (short)AsNumber64();
328355
}
329356

330-
/// <summary>
331-
/// <inheritdoc/>
332-
/// </summary>
333-
/// <returns><inheritdoc/></returns>
334-
public DateTime AsDateTime()
357+
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
358+
private long GetTicks(long minTicks, long maxTicks)
335359
{
336360
long ticks = AsNumber64();
337361
if (ticks < 0)
@@ -342,51 +366,38 @@ public DateTime AsDateTime()
342366
if (BitLength < 64)
343367
{
344368
double maxHashValue = 1L << BitLength;
345-
ticks = (long)(ticks / maxHashValue * DateTime.MaxValue.Ticks);
369+
ticks = (long)(ticks / maxHashValue * maxTicks);
346370
}
347371

348-
if (ticks < DateTime.MinValue.Ticks)
372+
if (ticks < minTicks)
349373
{
350-
ticks = DateTime.MinValue.Ticks;
374+
ticks = minTicks;
351375
}
352376

353-
if (ticks > DateTime.MaxValue.Ticks)
377+
if (ticks > maxTicks)
354378
{
355-
ticks = DateTime.MaxValue.Ticks;
379+
ticks = maxTicks;
356380
}
357381

358-
return new DateTime(ticks);
382+
return ticks;
359383
}
360384

361385
/// <summary>
362386
/// <inheritdoc/>
363387
/// </summary>
364388
/// <returns><inheritdoc/></returns>
365-
public DateTimeOffset AsDateTimeOffset()
389+
public DateTime AsDateTime()
366390
{
367-
long ticks = AsNumber64();
368-
if (ticks < 0)
369-
{
370-
ticks &= long.MaxValue;
371-
}
372-
373-
if (BitLength < 64)
374-
{
375-
double maxHashValue = 1L << BitLength;
376-
ticks = (long)(ticks / maxHashValue * DateTimeOffset.MaxValue.Ticks);
377-
}
378-
379-
if (ticks < DateTimeOffset.MinValue.Ticks)
380-
{
381-
ticks = DateTimeOffset.MinValue.Ticks;
382-
}
383-
384-
if (ticks > DateTimeOffset.MaxValue.Ticks)
385-
{
386-
ticks = DateTimeOffset.MaxValue.Ticks;
387-
}
391+
return new DateTime(GetTicks(DateTime.MinValue.Ticks, DateTime.MaxValue.Ticks));
392+
}
388393

389-
return new DateTimeOffset(ticks, TimeSpan.Zero);
394+
/// <summary>
395+
/// <inheritdoc/>
396+
/// </summary>
397+
/// <returns><inheritdoc/></returns>
398+
public DateTimeOffset AsDateTimeOffset()
399+
{
400+
return new DateTimeOffset(GetTicks(DateTimeOffset.MinValue.Ticks, DateTimeOffset.MaxValue.Ticks), TimeSpan.Zero);
390401
}
391402

392403
/// <summary>
@@ -395,29 +406,7 @@ public DateTimeOffset AsDateTimeOffset()
395406
/// <returns><inheritdoc/></returns>
396407
public TimeSpan AsTimeSpan()
397408
{
398-
long ticks = AsNumber64();
399-
if (ticks < 0)
400-
{
401-
ticks &= long.MaxValue;
402-
}
403-
404-
if (BitLength < 64)
405-
{
406-
double maxHashValue = 1L << BitLength;
407-
ticks = (long)(ticks / maxHashValue * TimeSpan.MaxValue.Ticks);
408-
}
409-
410-
if (ticks < TimeSpan.MinValue.Ticks)
411-
{
412-
ticks = TimeSpan.MinValue.Ticks;
413-
}
414-
415-
if (ticks > TimeSpan.MaxValue.Ticks)
416-
{
417-
ticks = TimeSpan.MaxValue.Ticks;
418-
}
419-
420-
return new TimeSpan(ticks);
409+
return new TimeSpan(GetTicks(TimeSpan.MinValue.Ticks, TimeSpan.MaxValue.Ticks));
421410
}
422411

423412
/// <summary>
@@ -580,7 +569,7 @@ public ReadOnlySpan<byte> AsSpan()
580569
/// <returns><inheritdoc/></returns>
581570
public IHashValue Slice(int start, int length)
582571
{
583-
return new HashValue(Endianness, AsSpan(start, length).ToImmutableArray(), length * 8);
572+
return CreateInstance(Endianness, AsSpan(start, length).ToImmutableArray(), length * 8);
584573
}
585574

586575
/// <summary>
@@ -604,7 +593,7 @@ public virtual IHashValue Coerce(int bitLength)
604593
if (BitLength == bitLength)
605594
return this;
606595

607-
return new HashValue(Endianness, ArrayHelpers.CoerceToArray(Hash.ToArray(), bitLength), bitLength);
596+
return CreateInstance(Endianness, ArrayHelpers.CoerceToArray(Hash, bitLength).ToImmutableArray(), bitLength);
608597
}
609598

610599
/// <summary>
@@ -616,7 +605,7 @@ public IHashValue AsLittleEndian()
616605
if (Endianness != ValueEndianness.BigEndian)
617606
return this;
618607

619-
return new HashValue(ValueEndianness.LittleEndian, Hash.Reverse().ToImmutableArray(), BitLength);
608+
return CreateInstance(ValueEndianness.LittleEndian, Hash.Reverse().ToImmutableArray(), BitLength);
620609
}
621610

622611
/// <summary>
@@ -628,7 +617,7 @@ public IHashValue AsBigEndian()
628617
if (Endianness != ValueEndianness.LittleEndian)
629618
return this;
630619

631-
return new HashValue(ValueEndianness.BigEndian, Hash.Reverse().ToImmutableArray(), BitLength);
620+
return CreateInstance(ValueEndianness.BigEndian, Hash.Reverse().ToImmutableArray(), BitLength);
632621
}
633622

634623
/// <summary>
@@ -653,7 +642,7 @@ public IHashValue ReverseEndianness()
653642
if (Endianness == ValueEndianness.NotApplicable)
654643
return this;
655644

656-
return new HashValue(Endianness == ValueEndianness.BigEndian ? ValueEndianness.LittleEndian : ValueEndianness.BigEndian, Hash.Reverse().ToImmutableArray(), BitLength);
645+
return CreateInstance(Endianness == ValueEndianness.BigEndian ? ValueEndianness.LittleEndian : ValueEndianness.BigEndian, Hash.Reverse().ToImmutableArray(), BitLength);
657646
}
658647

659648
/// <summary>
@@ -838,6 +827,24 @@ public double CalculateEntropyPercentage()
838827
return (actualEntropy / maxPossibleEntropy) * 100.0;
839828
}
840829

830+
/// <summary>
831+
/// <inheritdoc/>
832+
/// </summary>
833+
/// <returns><inheritdoc/></returns>
834+
public virtual IHashValue TreatAsLittleEndian()
835+
{
836+
return CreateInstance(ValueEndianness.LittleEndian, Hash, BitLength);
837+
}
838+
839+
/// <summary>
840+
/// <inheritdoc/>
841+
/// </summary>
842+
/// <returns><inheritdoc/></returns>
843+
public virtual IHashValue TreatAsBigEndian()
844+
{
845+
return CreateInstance(ValueEndianness.BigEndian, Hash, BitLength);
846+
}
847+
841848
/// <summary>
842849
/// <inheritdoc/>
843850
/// </summary>

0 commit comments

Comments
 (0)