Skip to content

Instantly share code, notes, and snippets.

@skolima
Created October 18, 2018 18:23
Show Gist options
  • Save skolima/9b5dd595398e5f8f5ff9d368c4f1cf8c to your computer and use it in GitHub Desktop.
Save skolima/9b5dd595398e5f8f5ff9d368c4f1cf8c to your computer and use it in GitHub Desktop.
Create shortest possible base64 url safe representation of a 64 bit number
namespace XUnitTestProject1
{
using System;
using Xunit;
using Microsoft.AspNetCore.WebUtilities;
// https://tools.ietf.org/html/rfc4648#page-7 Base64 URL-safe Alphabet
// uses Microsoft.AspNetCore.WebUtilities.Base64UrlTextEncoder from
// https://www.nuget.org/packages/Microsoft.AspNetCore.WebUtilities
// the same implementation also exists as Microsoft.IdentityModel.Tokens.Base64UrlEncoder,
// but that other package has a lot more dependencies
// Normally Base64UrlTextEncoder would always use full byte size (8) of Int64 - we want something shorter
public static class ShortestBase64Encoder
{
public static long DecodeUrlSafe(string encoded)
{
var bytes = new byte[8];
Base64UrlTextEncoder.Decode(encoded).CopyTo(bytes, 0);
return BitConverter.ToInt64(bytes, 0);
}
public static string EncodeUrlSafe(long data)
{
var bytes = BitConverter.GetBytes(data);
var index = bytes.Length;
for (; index > 0 && bytes[index - 1] == 0; index--)
{
}
var newBytes = new byte[index];
Array.Copy(bytes, newBytes, index);
return Base64UrlTextEncoder.Encode(newBytes);
}
}
public class ShortestBase64EncoderTests
{
[Theory]
[InlineData(0, "", 0)]
[InlineData(1, "AQ", 2)]
[InlineData(byte.MaxValue, "_w", 2)]
[InlineData(short.MaxValue, "_38", 3)]
[InlineData(2608086, "1ssn", 4)]
[InlineData(123456789, "Fc1bBw", 6)]
[InlineData(int.MaxValue, "____fw", 6)]
[InlineData(long.MaxValue >> 7, "_________w", 10)]
[InlineData(long.MaxValue, "_________38", 11)]
public void ShouldEncodeAndDecodeCorrectly(long input, string expected, int expectedLength)
{
var encoded = ShortestBase64Encoder.EncodeUrlSafe(input);
Assert.Equal(expected, encoded);
Assert.Equal(expectedLength, encoded.Length);
var decoded = ShortestBase64Encoder.DecodeUrlSafe(encoded);
Assert.Equal(input, decoded);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment