Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UTF-16 option to Base64 encoder/decoder #63

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,68 @@ public async Task EncodeUtf8()
_inputBox.Text("Hello world &é'(-è_çèà)");
await _tool.WorkTask;
_outputBox.Text.Should().Be("SGVsbG8gd29ybGQgJsOpJygtw6hfw6fDqMOgKQ==");
}

[Fact]
public async Task EncodeUtf16()
{
var encodingOption = (IUISelectDropDownList)((IUISetting)_toolView.GetChildElementById("base64-text-encoding-setting")).InteractiveElement;
encodingOption.Select(2); // Select UTF-16

_inputBox.Text("Hello world &é'(-è_çèà)");
await _tool.WorkTask;
_outputBox.Text.Should().Be("//5IAGUAbABsAG8AIAB3AG8AcgBsAGQAIAAmAOkAJwAoAC0A6ABfAOcA6ADgACkA");
}

[Fact]
public async Task EncodeAscii()
{
var encodingOption = (IUISelectDropDownList)((IUISetting)_toolView.GetChildElementById("base64-text-encoding-setting")).InteractiveElement;
encodingOption.Select(1); // Select ASCII
encodingOption.Select(0); // Select ASCII

_inputBox.Text("Hello world &é'(-è_çèà)");
await _tool.WorkTask;
_outputBox.Text.Should().Be("SGVsbG8gd29ybGQgJj8nKC0/Xz8/Pyk=");
}

[Fact]
public async Task DecodeUtf8()
{
var conversionMode = (IUISwitch)_toolView.GetChildElementById("base64-text-conversion-mode-switch");
conversionMode.Off(); // Switch to Decode

_inputBox.Text("SGVsbG8gd29ybGQgJsOpJygtw6hfw6fDqMOgKQ==");
await _tool.WorkTask;
_outputBox.Text.Should().Be("Hello world &é'(-è_çèà)");
}

[Fact]
public async Task DecodeUtf16()
{
var conversionMode = (IUISwitch)_toolView.GetChildElementById("base64-text-conversion-mode-switch");
conversionMode.Off(); // Switch to Decode

var encodingOption = (IUISelectDropDownList)((IUISetting)_toolView.GetChildElementById("base64-text-encoding-setting")).InteractiveElement;
encodingOption.Select(2); // Select UTF-16

_inputBox.Text("//5IAGUAbABsAG8AIAB3AG8AcgBsAGQAIAAmAOkAJwAoAC0A6ABfAOcA6ADgACkA");
await _tool.WorkTask;
_outputBox.Text.Should().Be("Hello world &é'(-è_çèà)");
}

[Fact]
public async Task DecodeAscii()
{
var conversionMode = (IUISwitch)_toolView.GetChildElementById("base64-text-conversion-mode-switch");
conversionMode.Off(); // Switch to Decode

var encodingOption = (IUISelectDropDownList)((IUISetting)_toolView.GetChildElementById("base64-text-encoding-setting")).InteractiveElement;
encodingOption.Select(0); // Select ASCII

_inputBox.Text("SGVsbG8gd29ybGQgJj8nKC0/Xz8/Pyk=");
await _tool.WorkTask;
_outputBox.Text.Should().Be("Hello world &?'(-?_???)");
}

[Fact]
public async Task SwitchConversionMode()
Expand Down
23 changes: 14 additions & 9 deletions src/DevToys.Tools.UnitTests/Tools/Helpers/Base64HelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ namespace DevToys.Tools.UnitTests.Tools.Helpers;
public class Base64HelperTests
{
[Theory]
[InlineData(null, false)]
[InlineData("", false)]
[InlineData(" ", false)]
[InlineData("aGVsbG8gd29ybGQ=", true)]
[InlineData("aGVsbG8gd2f9ybGQ=", false)]
[InlineData("SGVsbG8gV29y", true)]
[InlineData("SGVsbG8gVa29y", false)]
public void IsValid(string input, bool expectedResult)
[InlineData(null, Base64Encoding.Utf8, false)]
[InlineData("", Base64Encoding.Utf8, false)]
[InlineData(" ", Base64Encoding.Utf8, false)]
[InlineData("aGVsbG8gd29ybGQ=", Base64Encoding.Utf8, true)]
[InlineData("aGVsbG8gd2f9ybGQ=", Base64Encoding.Utf8, false)]
[InlineData("SGVsbG8gV29y", Base64Encoding.Utf8, true)]
[InlineData("SGVsbG8gVa29y", Base64Encoding.Utf8, false)]
[InlineData("//5oAGUAbABsAG8AIAB3AG8AcgBsAGQA", Base64Encoding.Utf16, true)]
[InlineData("//5oAGUAbABsAG8AIAB3AG8AcgBsAGQAAAA=", Base64Encoding.Utf8, false)] // NUL
[InlineData("aGVsbG8gd29ybGTvv70=", Base64Encoding.Utf8, false)] // Invalid Unicode char
internal void IsValid(string input, Base64Encoding encoding, bool expectedResult)
{
Base64Helper.IsBase64DataStrict(input).Should().Be(expectedResult);
Base64Helper.IsBase64DataStrict(input, encoding).Should().Be(expectedResult);
}

[Theory]
[InlineData(null, "", Base64Encoding.Utf8)]
[InlineData("Hello World!", "SGVsbG8gV29ybGQh", Base64Encoding.Utf8)]
[InlineData("Hello World! é)à", "SGVsbG8gV29ybGQhIMOpKcOg", Base64Encoding.Utf8)]
[InlineData("Hello World! é)à", "//5IAGUAbABsAG8AIABXAG8AcgBsAGQAIQAgAOkAKQDgAA==", Base64Encoding.Utf16)]
[InlineData("Hello World! é)à", "SGVsbG8gV29ybGQhID8pPw==", Base64Encoding.Ascii)]
internal void FromTextToBase64(string input, string expectedResult, Base64Encoding encoding)
{
Expand All @@ -38,6 +42,7 @@ internal void FromTextToBase64(string input, string expectedResult, Base64Encodi
[InlineData(null, "", Base64Encoding.Utf8)]
[InlineData("SGVsbG8gV29ybGQh", "Hello World!", Base64Encoding.Utf8)]
[InlineData("SGVsbG8gV29ybGQhIMOpKcOg", "Hello World! é)à", Base64Encoding.Utf8)]
[InlineData("//5IAGUAbABsAG8AIABXAG8AcgBsAGQAIQAgAOkAKQDgAA==", "Hello World! é)à", Base64Encoding.Utf16)]
[InlineData("SGVsbG8gV29ybGQhID8pPw==", "Hello World! ?)?", Base64Encoding.Ascii)]
internal void FromBase64ToText(string input, string expectedResult, Base64Encoding encoding)
{
Expand Down
27 changes: 20 additions & 7 deletions src/DevToys.Tools/Helpers/Base64Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace DevToys.Tools.Helpers;

internal static partial class Base64Helper
{
internal static bool IsBase64DataStrict(string? data)
internal static bool IsBase64DataStrict(string? data, Base64Encoding encoding)
{
if (string.IsNullOrWhiteSpace(data))
{
Expand Down Expand Up @@ -38,8 +38,11 @@ internal static bool IsBase64DataStrict(string? data)

try
{
byte[]? decodedData = Convert.FromBase64String(data);
decoded = Encoding.UTF8.GetString(decodedData);
Encoding encoder = GetEncoder(encoding);
byte[] decodedData = Convert.FromBase64String(data);
using MemoryStream decodedStream = new(decodedData);
using StreamReader reader = new(decodedStream, encoder);
decoded = reader.ReadToEnd();
}
catch (Exception)
{
Expand Down Expand Up @@ -81,7 +84,13 @@ internal static string FromTextToBase64(string? data, Base64Encoding encoding, I
try
{
Encoding encoder = GetEncoder(encoding);
byte[]? dataBytes = encoder.GetBytes(data);

byte[] dataBytes = new byte[encoder.Preamble.Length + encoder.GetByteCount(data)];
using(MemoryStream dataStream = new(dataBytes))
using (StreamWriter writer = new(dataStream, encoder))
{
writer.Write(data);
}

cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -127,7 +136,7 @@ internal static string FromBase64ToText(string? data, Base64Encoding encoding, I

if (encoder is UTF8Encoding && decodedData != null)
{
byte[] preamble = encoder.GetPreamble();
byte[] preamble = Encoding.UTF8.GetPreamble();
if (decodedData.Take(preamble.Length).SequenceEqual(preamble))
{
// need to keep it this way to have the dom char
Expand All @@ -139,7 +148,10 @@ internal static string FromBase64ToText(string? data, Base64Encoding encoding, I

if (decodedData is not null)
{
decoded += encoder.GetString(decodedData);
using MemoryStream dataStream = new(decodedData);
using StreamReader reader = new(dataStream, encoder);

decoded += reader.ReadToEnd();
}
}
catch (Exception ex) when (ex is OperationCanceledException || ex is FormatException)
Expand All @@ -159,8 +171,9 @@ private static Encoding GetEncoder(Base64Encoding encoding)
{
return encoding switch
{
Base64Encoding.Utf8 => new UTF8Encoding(true),
Base64Encoding.Utf8 => new UTF8Encoding(false),
Base64Encoding.Ascii => Encoding.ASCII,
Base64Encoding.Utf16 => Encoding.Unicode,
_ => throw new NotSupportedException(),
};
}
Expand Down
3 changes: 2 additions & 1 deletion src/DevToys.Tools/Models/Base64Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
internal enum Base64Encoding
{
Utf8,
Ascii
Ascii,
Utf16
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>نص Base64</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@
</data>
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Text en Base64</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64-Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Texte Base64</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<data name="ShortDisplayTitle" xml:space="preserve">
<value>Base64 Text</value>
</data>
<data name="Utf16" xml:space="preserve">
<value>UTF-16</value>
</data>
<data name="Utf8" xml:space="preserve">
<value>UTF-8</value>
</data>
Expand Down
Loading