@@ -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