The IBinaryEncoding interface
The per-encoding static classes (Base16, Base32, Base64, Base58, Base85) are the recommended entry point
when the encoding is known at compile time. They are fast, support variant-specific options (line breaks, padding
control, MIME wrapping), and produce the cleanest call sites.
For code that must select the encoding at runtime - configuration-driven serializers, plugin pipelines, generic utilities - the library exposes a unified contract:
public interface IBinaryEncoding
{
string Name { get; }
string Description { get; }
int GetMaxEncodedLength(int byteCount);
int GetMaxDecodedLength(int charCount);
string Encode(ReadOnlySpan<byte> bytes);
byte[] Decode(ReadOnlySpan<char> chars);
bool TryEncode(ReadOnlySpan<byte> source, Span<char> destination, out int charsWritten);
bool TryDecode(ReadOnlySpan<char> source, Span<byte> destination, out int bytesWritten);
bool IsValid(ReadOnlySpan<char> source);
}
The interface deliberately hides variant-specific encoding options. Code that needs OmitPadding,
InsertLineBreaks, MIME wrapping, or other per-variant flags should keep using the static classes.
Ready-made instances
The BinaryEncodings static class exposes thread-safe singleton instances for every variant the library ships:
| Property | Underlying static call |
|---|---|
BinaryEncodings.Base16Lower |
Base16.Encode(bytes) (default lower case) |
BinaryEncodings.Base16Upper |
Base16.Encode(bytes, BaseFormattingOptions.UpperCase) |
BinaryEncodings.Base32 |
Base32.Encode(bytes, Base32Variant.Standard) |
BinaryEncodings.Base32Hex |
Base32.Encode(bytes, Base32Variant.HexExtended) |
BinaryEncodings.Base32Crockford |
Base32.Encode(bytes, Base32Variant.Crockford) |
BinaryEncodings.Base32ZBase32 |
Base32.Encode(bytes, Base32Variant.ZBase32) |
BinaryEncodings.Base64 |
Base64.Encode(bytes, Base64Variant.Standard) |
BinaryEncodings.Base64UrlSafe |
Base64.Encode(bytes, Base64Variant.UrlSafe) |
BinaryEncodings.Base64Mime |
Base64.Encode(bytes, Base64Variant.Mime) |
BinaryEncodings.Base45 |
Base45.Encode(bytes) |
BinaryEncodings.Base58 |
Base58.Encode(bytes, Base58Variant.BitcoinFlickr) |
BinaryEncodings.Base58Ripple |
Base58.Encode(bytes, Base58Variant.Ripple) |
BinaryEncodings.Base62 |
Base62.Encode(bytes) |
BinaryEncodings.Ascii85 |
Base85.Encode(bytes, Base85Variant.Ascii85) |
BinaryEncodings.Z85 |
Base85.Encode(bytes, Base85Variant.Z85) |
BinaryEncodings.Base85Git |
Base85.Encode(bytes, Base85Variant.GitCompact) |
using Bodu.Text.Encoding;
IBinaryEncoding encoding = BinaryEncodings.Base64UrlSafe;
string token = encoding.Encode(secretKey);
byte[] back = encoding.Decode(token);
Runtime lookup by name
BinaryEncodings.Get(name) resolves a case-insensitive string identifier to the matching instance. The recognised
names include canonical forms and common aliases:
| Canonical | Aliases |
|---|---|
base16-lower |
base16, hex |
base16-upper |
hex-upper |
base32 |
- |
base32hex |
- |
base32-crockford |
- |
z-base-32 |
zbase32 |
base64 |
- |
base64-urlsafe |
base64url |
base64-mime |
- |
base45 |
- |
base58 |
base58-bitcoin, base58-flickr |
base58-ripple |
- |
base62 |
- |
ascii85 |
base85 |
base85-git |
git-base85, b85 |
z85 |
- |
string encodingName = configuration["TokenEncoding"]; // e.g. "base64-urlsafe"
IBinaryEncoding encoding = BinaryEncodings.Get(encodingName);
string encoded = encoding.Encode(rawBytes);
byte[] decoded = encoding.Decode(encoded);
Unknown names throw ArgumentException.
Extension methods
The BinaryEncodingExtensions class includes two generic extensions that route through IBinaryEncoding:
using Bodu.Text.Encoding;
byte[] data = { 0xDE, 0xAD, 0xBE, 0xEF };
IBinaryEncoding encoding = BinaryEncodings.Get(name);
string s = data.Encode(encoding); // dispatches through the interface
byte[] back = s.Decode(encoding);
It also exposes per-encoding fluent shortcuts that dispatch through the static classes (no virtual call):
data.ToBase16String(); // "deadbeef"
data.ToBase32String(); // "32W6P3XO"
data.ToBase64String(); // "3q2+7w=="
data.ToBase58String(); // "6h8cQN"
data.ToBase85String(); // ".(0%g"
"deadbeef".FromBase16String();
"3q2+7w==".FromBase64String();
"6h8cQN".FromBase58String();
Common patterns
Configuration-driven serialization
public sealed class TokenEncoder
{
private readonly IBinaryEncoding _encoding;
public TokenEncoder(string encodingName)
{
_encoding = BinaryEncodings.Get(encodingName);
}
public string Encode(ReadOnlySpan<byte> payload) => _encoding.Encode(payload);
public byte[] Decode(string token) => _encoding.Decode(token);
}
Plugin pipeline
public interface ITokenStage
{
IBinaryEncoding InputEncoding { get; }
IBinaryEncoding OutputEncoding { get; }
byte[] Process(byte[] input);
}
public static byte[] Run(ITokenStage stage, string input)
{
byte[] bytes = stage.InputEncoding.Decode(input);
byte[] output = stage.Process(bytes);
return output; // caller wraps with stage.OutputEncoding.Encode
}
Generic round-trip helper
public static bool TryRoundTrip(IBinaryEncoding encoding, ReadOnlySpan<byte> data)
{
string encoded = encoding.Encode(data);
byte[] back = encoding.Decode(encoded);
return data.SequenceEqual(back);
}
When to not use the interface
The interface is a convenience for the runtime-selection use case. Skip it when:
- The encoding is known at compile time - use the static class directly for the cleanest call site.
- You need variant-specific options like
BaseFormattingOptions.InsertLineBreaks,BaseFormattingOptions.OmitPadding, orBaseFormatStyles.AllowPrefix- those are not exposed via the interface by design (each encoding has different option semantics). - You need the
UTF-8byte path or theOperationStatusstreaming decode - those are only available on the static classes.
Where to go next
- Base16 guide, Base32 guide, Base64 guide, Base58 guide, Base85 guide - the static-class entry points with the full option set.
- Core concepts - vocabulary refresher.
- Text & Serialization guides - every guide in this topic, across Bodu.Text.Encoding, Bodu.Text.Formats, and the Bencode / TOML serializers.