Skip to content

Commit ed219a5

Browse files
authored
Merge pull request #5 from unsafePtr/refactor/encode-state-generic
refactor: make EncodeState generic over TAlphabet to fold alphabet
2 parents d9abb3f + 21578c0 commit ed219a5

1 file changed

Lines changed: 16 additions & 19 deletions

File tree

src/Base58Encoding/Base58.Encode.cs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ private string EncodeGenericToString(ReadOnlySpan<byte> data)
7878
{
7979
Span<byte> digits = stackalloc byte[size];
8080
int digitCount = ComputeGenericDigits(inputSpan, digits);
81-
var state = new EncodeState(digits, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
81+
var state = new EncodeState<TAlphabet>(digits, 0, digitCount, leadingZeros);
8282
return string.Create(state.OutputLength, state, static (span, s) => s.EmitReverse(span));
8383
}
8484

@@ -91,7 +91,7 @@ private string EncodeGenericToStringLarge(ReadOnlySpan<byte> inputSpan, int lead
9191
try
9292
{
9393
int digitCount = ComputeGenericDigits(inputSpan, rented);
94-
var state = new EncodeState(rented, 0, digitCount, TAlphabet.Characters, TAlphabet.FirstCharacter, leadingZeros);
94+
var state = new EncodeState<TAlphabet>(rented, 0, digitCount, leadingZeros);
9595
return string.Create(state.OutputLength, state, static (span, s) => s.EmitReverse(span));
9696
}
9797
finally
@@ -129,7 +129,7 @@ private int EncodeGenericToBytes(ReadOnlySpan<byte> data, Span<byte> destination
129129
ThrowHelper.ThrowDestinationTooSmall(nameof(destination));
130130
}
131131

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

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

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

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

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

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

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

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

422-
private readonly ref struct EncodeState
422+
private readonly ref struct EncodeState<T>
423+
where T : struct, IBase58Alphabet
423424
{
424425
public readonly ReadOnlySpan<byte> Digits;
425-
public readonly ReadOnlySpan<byte> Alphabet;
426426
public readonly int DigitStart;
427427
public readonly int DigitCount;
428-
public readonly byte LeadingFill;
429428
public readonly int LeadingCount;
430429

431430
public EncodeState(
432431
ReadOnlySpan<byte> digits,
433432
int digitStart,
434433
int digitCount,
435-
ReadOnlySpan<byte> alphabet,
436-
byte leadingFill,
437434
int leadingCount)
438435
{
439436
Digits = digits;
440437
DigitStart = digitStart;
441438
DigitCount = digitCount;
442-
Alphabet = alphabet;
443-
LeadingFill = leadingFill;
444439
LeadingCount = leadingCount;
445440
}
446441

@@ -451,14 +446,15 @@ public void EmitForward<TChar>(Span<TChar> destination)
451446
{
452447
if (LeadingCount > 0)
453448
{
454-
destination[..LeadingCount].Fill(TChar.CreateTruncating(LeadingFill));
449+
destination[..LeadingCount].Fill(TChar.CreateTruncating(T.FirstCharacter));
455450
}
456451

457452
int index = LeadingCount;
458453
int end = DigitStart + DigitCount;
454+
ReadOnlySpan<byte> alphabet = T.Characters;
459455
for (int i = DigitStart; i < end; i++)
460456
{
461-
destination[index++] = TChar.CreateTruncating((ushort)Alphabet[Digits[i]]);
457+
destination[index++] = TChar.CreateTruncating((ushort)alphabet[Digits[i]]);
462458
}
463459
}
464460

@@ -467,13 +463,14 @@ public void EmitReverse<TChar>(Span<TChar> destination)
467463
{
468464
if (LeadingCount > 0)
469465
{
470-
destination[..LeadingCount].Fill(TChar.CreateTruncating(LeadingFill));
466+
destination[..LeadingCount].Fill(TChar.CreateTruncating(T.FirstCharacter));
471467
}
472468

473469
int index = LeadingCount;
470+
ReadOnlySpan<byte> alphabet = T.Characters;
474471
for (int i = DigitStart + DigitCount - 1; i >= DigitStart; i--)
475472
{
476-
destination[index++] = TChar.CreateTruncating((ushort)Alphabet[Digits[i]]);
473+
destination[index++] = TChar.CreateTruncating((ushort)alphabet[Digits[i]]);
477474
}
478475
}
479476
}

0 commit comments

Comments
 (0)