Skip to content

Commit

Permalink
Showing 2 changed files with 171 additions and 14 deletions.
153 changes: 144 additions & 9 deletions src/Cake.Issues.Tests/ByteArrayExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

public sealed class ByteArrayExtensionsTests
{
public sealed class TheUtf8ToStringExtension
public sealed class TheToStringUsingEncodingExtension
{
[Fact]
public void Should_Throw_If_Value_Is_Null()
@@ -18,7 +18,7 @@ public void Should_Throw_If_Value_Is_Null()
byte[] value = null;

// When
var result = Record.Exception(() => value.Utf8ToString(true));
var result = Record.Exception(() => value.ToStringUsingEncoding());

// Then
result.IsArgumentNullException("value");
@@ -31,50 +31,185 @@ public void Should_Throw_If_Value_Is_Empty()
byte[] value = Array.Empty<byte>();

// When
var result = Record.Exception(() => value.Utf8ToString(true));
var result = Record.Exception(() => value.ToStringUsingEncoding());

// Then
result.IsArgumentException("value");
}

[Fact]
public void Should_Throw_If_BOM_Should_Be_Skipped_But_No_BOM_Passed()
public void Should_Return_Correct_Value_Without_Preamble()
{
// Given
var stringValue = "foo🐱bar";
var byteArrayValue = stringValue.ToByteArray();

// When
var result = Record.Exception(() => byteArrayValue.Utf8ToString(true));
var result = byteArrayValue.ToStringUsingEncoding();

// Then
result.ShouldBe(stringValue);
}
}

public sealed class TheToStringUsingEncodingWithSkipPreambleExtension
{
[Fact]
public void Should_Throw_If_Value_Is_Null()
{
// Given
byte[] value = null;

// When
var result = Record.Exception(() => value.ToStringUsingEncoding(true));

// Then
result.IsArgumentNullException("value");
}

[Fact]
public void Should_Throw_If_Value_Is_Empty()
{
// Given
byte[] value = Array.Empty<byte>();

// When
var result = Record.Exception(() => value.ToStringUsingEncoding(true));

// Then
result.IsArgumentException("value");
}

[Fact]
public void Should_Throw_If_Preamble_Should_Be_Skipped_But_No_Preamble_Passed()
{
// Given
var stringValue = "foo🐱bar";
var byteArrayValue = stringValue.ToByteArray();

// When
var result = Record.Exception(() => byteArrayValue.ToStringUsingEncoding(true));

// Then
result.IsArgumentException("value");
}

[Fact]
public void Should_Return_Correct_Value_Without_BOM()
public void Should_Return_Correct_Value_Without_Preamble()
{
// Given
var stringValue = "foo🐱bar";
var byteArrayValue = stringValue.ToByteArray();

// When
var result = byteArrayValue.Utf8ToString(false);
var result = byteArrayValue.ToStringUsingEncoding(false);

// Then
result.ShouldBe(stringValue);
}

[Fact]
public void Should_Return_Correct_Value_With_BOM()
public void Should_Return_Correct_Value_With_Preamble()
{
// Given
var stringValue = "foo🐱bar";
var preamble = Encoding.UTF8.GetPreamble();
var byteArrayValue = preamble.Concat(stringValue.ToByteArray()).ToArray();

// When
var result = byteArrayValue.Utf8ToString(true);
var result = byteArrayValue.ToStringUsingEncoding(true);

// Then
result.ShouldBe(stringValue);
}
}

public sealed class TheToStringUsingEncodingWithEncodingAndSkipPreambleExtension
{
[Fact]
public void Should_Throw_If_Value_Is_Null()
{
// Given
byte[] value = null;
var encoding = Encoding.UTF32;

// When
var result = Record.Exception(() => value.ToStringUsingEncoding(encoding, true));

// Then
result.IsArgumentNullException("value");
}

[Fact]
public void Should_Throw_If_Value_Is_Empty()
{
// Given
byte[] value = Array.Empty<byte>();
var encoding = Encoding.UTF32;

// When
var result = Record.Exception(() => value.ToStringUsingEncoding(encoding, true));

// Then
result.IsArgumentException("value");
}

[Fact]
public void Should_Throw_If_Preamble_Should_Be_Skipped_But_No_Preamble_Passed()
{
// Given
var encoding = Encoding.UTF32;
var stringValue = "foo🐱bar";
var byteArrayValue = stringValue.ToByteArray(encoding);

// When
var result = Record.Exception(() => byteArrayValue.ToStringUsingEncoding(encoding, true));

// Then
result.IsArgumentException("value");
}

[Fact]
public void Should_Return_Value_If_Preamble_Should_Be_Skipped_But_Encoding_Does_Not_Have_Preamble()
{
// Given
var stringValue = "foo";
var byteArrayValue = stringValue.ToByteArray();
var encoding = Encoding.ASCII;

// When
var result = byteArrayValue.ToStringUsingEncoding(encoding, true);

// Then
result.ShouldBe(stringValue);
}

[Fact]
public void Should_Return_Correct_Value_Without_Preamble()
{
// Given
var encoding = Encoding.UTF32;
var stringValue = "foo🐱bar";
var byteArrayValue = stringValue.ToByteArray(encoding);

// When
var result = byteArrayValue.ToStringUsingEncoding(encoding, false);

// Then
result.ShouldBe(stringValue);
}

[Fact]
public void Should_Return_Correct_Value_With_Preamble()
{
// Given
var encoding = Encoding.UTF32;
var stringValue = "foo🐱bar";
var preamble = encoding.GetPreamble();
var byteArrayValue = preamble.Concat(stringValue.ToByteArray(encoding)).ToArray();

// When
var result = byteArrayValue.ToStringUsingEncoding(encoding, true);

// Then
result.ShouldBe(stringValue);
32 changes: 27 additions & 5 deletions src/Cake.Issues/ByteArrayExtensions.cs
Original file line number Diff line number Diff line change
@@ -13,21 +13,43 @@ public static class ByteArrayExtensions
/// Converts a byte array of an UTF-8 encoded string to a string.
/// </summary>
/// <param name="value">Value to convert.</param>
/// <param name="skipByteOrderMark">True if <paramref name="value"/> contains a BOM which should not be returned.</param>
/// <returns>Converted string.</returns>
public static string Utf8ToString(this byte[] value, bool skipByteOrderMark)
public static string ToStringUsingEncoding(this byte[] value)
{
value.NotNullOrEmpty(nameof(value));

var encoding = new UTF8Encoding(skipByteOrderMark);
return value.ToStringUsingEncoding(false);
}

/// <summary>
/// Converts a byte array of an UTF-8 encoded string to a string.
/// </summary>
/// <param name="value">Value to convert.</param>
/// <param name="skipPreamble">True if <paramref name="value"/> contains a BOM which should not be returned.</param>
/// <returns>Converted string.</returns>
public static string ToStringUsingEncoding(this byte[] value, bool skipPreamble)
{
return value.ToStringUsingEncoding(Encoding.UTF8, skipPreamble);
}

/// <summary>
/// Converts a byte array to a string.
/// </summary>
/// <param name="value">Value to convert.</param>
/// <param name="encoding">Encoding of the string.</param>
/// <param name="skipPreamble">True if <paramref name="value"/> contains a preamble which should not be returned.</param>
/// <returns>Converted string.</returns>
public static string ToStringUsingEncoding(this byte[] value, Encoding encoding, bool skipPreamble)
{
value.NotNullOrEmpty(nameof(value));

if (skipByteOrderMark)
if (skipPreamble)
{
var preamble = encoding.GetPreamble();

if (preamble.Where((p, i) => p != value[i]).Any())
{
throw new ArgumentException("Value contains no UTF-8 byte order mark.", nameof(value));
throw new ArgumentException("Value contains no preamble.", nameof(value));
}

value = value.Skip(preamble.Length).ToArray();

0 comments on commit 4202cdb

Please sign in to comment.