Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions src/Base58Encoding/Base58.Encode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private string EncodeGenericToString(ReadOnlySpan<byte> data)
{
Span<byte> digits = stackalloc byte[size];
int digitCount = ComputeGenericDigits(inputSpan, digits);
var state = new EncodeState(digits, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
var state = new EncodeState<TAlphabet>(digits, 0, digitCount, leadingZeros);
return string.Create(state.OutputLength, state, static (span, s) => s.EmitReverse(span));
}

Expand All @@ -91,7 +91,7 @@ private string EncodeGenericToStringLarge(ReadOnlySpan<byte> inputSpan, int lead
try
{
int digitCount = ComputeGenericDigits(inputSpan, rented);
var state = new EncodeState(rented, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
var state = new EncodeState<TAlphabet>(rented, 0, digitCount, leadingZeros);
return string.Create(state.OutputLength, state, static (span, s) => s.EmitReverse(span));
}
finally
Expand Down Expand Up @@ -129,7 +129,7 @@ private int EncodeGenericToBytes(ReadOnlySpan<byte> data, Span<byte> destination
ThrowHelper.ThrowDestinationTooSmall(nameof(destination));
}

var state = new EncodeState(digits, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
var state = new EncodeState<TAlphabet>(digits, 0, digitCount, leadingZeros);
state.EmitReverse(destination);
return outputLength;
}
Expand All @@ -149,7 +149,7 @@ private int EncodeGenericToBytesLarge(ReadOnlySpan<byte> inputSpan, int leadingZ
ThrowHelper.ThrowDestinationTooSmall(nameof(destination));
}

var state = new EncodeState(rented, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
var state = new EncodeState<TAlphabet>(rented, 0, digitCount, leadingZeros);
state.EmitReverse(destination);
return outputLength;
}
Expand Down Expand Up @@ -202,7 +202,7 @@ internal static string EncodeBitcoin32FastToString(ReadOnlySpan<byte> data)
Debug.Assert(skip >= 0, "rawLeadingZeros should always be >= inLeadingZeros by Base58 math");
int digitCount = Base58BitcoinTables.Raw58Sz32 - rawLeadingZeros;

var state = new EncodeState(rawBase58, rawLeadingZeros, digitCount, Base58BitcoinTables.BitcoinChars, (byte)'1', inLeadingZeros);
var state = new EncodeState<TAlphabet>(rawBase58, rawLeadingZeros, digitCount, inLeadingZeros);
return string.Create(state.OutputLength, state, static (span, s) => s.EmitForward(span));
}

Expand Down Expand Up @@ -235,7 +235,7 @@ private static int EncodeBitcoin32FastToBytes(ReadOnlySpan<byte> data, Span<byte
ThrowHelper.ThrowDestinationTooSmall(nameof(destination));
}

var state = new EncodeState(rawBase58, rawLeadingZeros, digitCount, Base58BitcoinTables.BitcoinChars, (byte)'1', inLeadingZeros);
var state = new EncodeState<TAlphabet>(rawBase58, rawLeadingZeros, digitCount, inLeadingZeros);
state.EmitForward(destination);
return outputLength;
}
Expand Down Expand Up @@ -311,7 +311,7 @@ internal static string EncodeBitcoin64FastToString(ReadOnlySpan<byte> data)
Debug.Assert(skip >= 0, "rawLeadingZeros should always be >= inLeadingZeros by Base58 math");
int digitCount = Base58BitcoinTables.Raw58Sz64 - rawLeadingZeros;

var state = new EncodeState(rawBase58, rawLeadingZeros, digitCount, Base58BitcoinTables.BitcoinChars, (byte)'1', inLeadingZeros);
var state = new EncodeState<TAlphabet>(rawBase58, rawLeadingZeros, digitCount, inLeadingZeros);
return string.Create(state.OutputLength, state, static (span, s) => s.EmitForward(span));
}

Expand Down Expand Up @@ -344,7 +344,7 @@ private static int EncodeBitcoin64FastToBytes(ReadOnlySpan<byte> data, Span<byte
ThrowHelper.ThrowDestinationTooSmall(nameof(destination));
}

var state = new EncodeState(rawBase58, rawLeadingZeros, digitCount, Base58BitcoinTables.BitcoinChars, (byte)'1', inLeadingZeros);
var state = new EncodeState<TAlphabet>(rawBase58, rawLeadingZeros, digitCount, inLeadingZeros);
state.EmitForward(destination);
return outputLength;
}
Expand Down Expand Up @@ -419,28 +419,23 @@ private static int ComputeBitcoin64FastRaw(ReadOnlySpan<byte> data, Span<byte> r
return rawLeadingZeros;
}

private readonly ref struct EncodeState
private readonly ref struct EncodeState<T>
where T : struct, IBase58Alphabet
{
public readonly ReadOnlySpan<byte> Digits;
public readonly ReadOnlySpan<byte> Alphabet;
public readonly int DigitStart;
public readonly int DigitCount;
public readonly byte LeadingFill;
public readonly int LeadingCount;

public EncodeState(
ReadOnlySpan<byte> digits,
int digitStart,
int digitCount,
ReadOnlySpan<byte> alphabet,
byte leadingFill,
int leadingCount)
{
Digits = digits;
DigitStart = digitStart;
DigitCount = digitCount;
Alphabet = alphabet;
LeadingFill = leadingFill;
LeadingCount = leadingCount;
}

Expand All @@ -451,14 +446,15 @@ public void EmitForward<TChar>(Span<TChar> destination)
{
if (LeadingCount > 0)
{
destination[..LeadingCount].Fill(TChar.CreateTruncating(LeadingFill));
destination[..LeadingCount].Fill(TChar.CreateTruncating(T.FirstCharacter));
}

int index = LeadingCount;
int end = DigitStart + DigitCount;
ReadOnlySpan<byte> alphabet = T.Characters;
for (int i = DigitStart; i < end; i++)
{
destination[index++] = TChar.CreateTruncating((ushort)Alphabet[Digits[i]]);
destination[index++] = TChar.CreateTruncating((ushort)alphabet[Digits[i]]);
}
}

Expand All @@ -467,13 +463,14 @@ public void EmitReverse<TChar>(Span<TChar> destination)
{
if (LeadingCount > 0)
{
destination[..LeadingCount].Fill(TChar.CreateTruncating(LeadingFill));
destination[..LeadingCount].Fill(TChar.CreateTruncating(T.FirstCharacter));
}

int index = LeadingCount;
ReadOnlySpan<byte> alphabet = T.Characters;
for (int i = DigitStart + DigitCount - 1; i >= DigitStart; i--)
{
destination[index++] = TChar.CreateTruncating((ushort)Alphabet[Digits[i]]);
destination[index++] = TChar.CreateTruncating((ushort)alphabet[Digits[i]]);
}
}
}
Expand Down
Loading