Compare commits
4 Commits
30af957fc6
...
v1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b68ba982d | |||
| 43135a5ffb | |||
| 2afd66aa57 | |||
| 71ec5b2f35 |
@@ -56,7 +56,7 @@ public class Decode
|
|||||||
var actualBytesArray = Base32.Decode(testString);
|
var actualBytesArray = Base32.Decode(testString);
|
||||||
actualBytesArray.Should().Equal(expected);
|
actualBytesArray.Should().Equal(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(" ")]
|
[InlineData(" ")]
|
||||||
[InlineData("hg2515i3215")]
|
[InlineData("hg2515i3215")]
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class Encode
|
|||||||
var resultBytes = Base32.Decode(testString);
|
var resultBytes = Base32.Decode(testString);
|
||||||
var resultString = Base32.Encode(resultBytes);
|
var resultString = Base32.Encode(resultBytes);
|
||||||
|
|
||||||
resultString.Should().BeEquivalentTo(testString);
|
resultString.Should().Be(testString);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -43,14 +43,27 @@ public class Encode
|
|||||||
{
|
{
|
||||||
var str = Base32.Encode(testArray);
|
var str = Base32.Encode(testArray);
|
||||||
str.Should().Be(expected);
|
str.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(new byte[] { })]
|
[InlineData(new byte[] { })]
|
||||||
[InlineData(null)]
|
[InlineData(null)]
|
||||||
public void WhenCalledWithEmptyByteArray_ShouldReturnEmptyString(byte[] testArray)
|
public void WhenCalledWithEmptyByteArray_ShouldReturnEmptyString(byte[] testArray)
|
||||||
{
|
{
|
||||||
var actualBase32 = Base32.Encode(testArray);
|
var actualBase32 = Base32.Encode(testArray);
|
||||||
actualBase32?.Should().Be(string.Empty);
|
actualBase32.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[] { })]
|
||||||
|
[InlineData(null)]
|
||||||
|
public void WhenCalledWithEmptyByteArray_ShouldReturnZeroAndNotChangeOutput(byte[] testArray)
|
||||||
|
{
|
||||||
|
char[] output = ['1', '2', '3', '4'];
|
||||||
|
|
||||||
|
var charsWritten = Base32.Encode(testArray, output);
|
||||||
|
|
||||||
|
charsWritten.Should().Be(0);
|
||||||
|
output.Should().Equal(['1', '2', '3', '4']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,4 +50,36 @@ public class Decode
|
|||||||
var result = Base64Url.Decode(testString);
|
var result = Base64Url.Decode(testString);
|
||||||
result.Should().BeEquivalentTo(expected);
|
result.Should().BeEquivalentTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(" ")]
|
||||||
|
[InlineData("hg2&515i3215")]
|
||||||
|
[InlineData("hg712)21")]
|
||||||
|
[InlineData("hg712f 21")]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Test case")]
|
||||||
|
public void WhenCalledWithInvalidString_ShouldThrowFormatException(string testString)
|
||||||
|
{
|
||||||
|
Action action = () => Base64Url.Decode(testString);
|
||||||
|
action.Should().Throw<FormatException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("5QrdUxDUV CAEGw8pvLsEw")]
|
||||||
|
[InlineData("6nE2uKQ4$0ar9kpmybgkdw")]
|
||||||
|
[InlineData("PyD6zwDqXkG*S1HPsp41wQ")]
|
||||||
|
[InlineData("!dOlPOh3wEe9PlyQgTMt2g")]
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Test case")]
|
||||||
|
public void WhenCalledWithInvalidGuidString_ShouldThrowFormatException(string testString)
|
||||||
|
{
|
||||||
|
Action action = () => Base64Url.DecodeGuid(testString);
|
||||||
|
action.Should().Throw<FormatException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(null)]
|
||||||
|
[InlineData("")]
|
||||||
|
public void WhenCalledWithNullString_ShouldReturnEmptyArray(string testString)
|
||||||
|
{
|
||||||
|
Base64Url.Decode(testString).Should().BeEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,26 @@ public class Encode
|
|||||||
var result = Base64Url.Encode(testBytes);
|
var result = Base64Url.Encode(testBytes);
|
||||||
result.Should().Be(expected);
|
result.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[] { })]
|
||||||
|
[InlineData(null)]
|
||||||
|
public void WhenCalledWithEmptyByteArray_ShouldReturnEmptyString(byte[] testArray)
|
||||||
|
{
|
||||||
|
var actualBase32 = Base64Url.Encode(testArray);
|
||||||
|
actualBase32.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[] { })]
|
||||||
|
[InlineData(null)]
|
||||||
|
public void WhenCalledWithEmptyByteArray_ShouldReturnZeroAndNotChangeOutput(byte[] testArray)
|
||||||
|
{
|
||||||
|
char[] output = ['1', '2', '3', '4'];
|
||||||
|
|
||||||
|
var charsWritten = Base64Url.Encode(testArray, output);
|
||||||
|
|
||||||
|
charsWritten.Should().Be(0);
|
||||||
|
output.Should().Equal(['1', '2', '3', '4']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
58
Core.Tests/SystemIOStreamExtensionsTests/Populate.cs
Normal file
58
Core.Tests/SystemIOStreamExtensionsTests/Populate.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using Just.Core.Extensions;
|
||||||
|
|
||||||
|
namespace Just.Core.Tests.SystemIOStreamExtensionsTests;
|
||||||
|
|
||||||
|
public class Populate
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0, 0)]
|
||||||
|
[InlineData(0, 1)]
|
||||||
|
[InlineData(0, 3)]
|
||||||
|
[InlineData(0, 5)]
|
||||||
|
[InlineData(3, 0)]
|
||||||
|
[InlineData(3, 1)]
|
||||||
|
[InlineData(3, 5)]
|
||||||
|
[InlineData(5, 0)]
|
||||||
|
[InlineData(5, 1)]
|
||||||
|
[InlineData(5, 5)]
|
||||||
|
public void WhenCalled_ShouldPopulateSpecifiedRange(int offset, int length)
|
||||||
|
{
|
||||||
|
byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,];
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[10];
|
||||||
|
|
||||||
|
stream.Populate(buffer, offset, length);
|
||||||
|
|
||||||
|
buffer.Skip(offset).Take(length).Should().Equal(streamContent.Take(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 4)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 4)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 5)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 5)]
|
||||||
|
public void WhenStreamContainsSameOrGreaterAmmountOfItems_ShouldPopulateBuffer(byte[] streamContent, int bufferSize)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
stream.Populate(buffer);
|
||||||
|
|
||||||
|
buffer.Should().Equal(streamContent.Take(bufferSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 5)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 6)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 10)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 9)]
|
||||||
|
public void WhenStreamContainsLessItems_ShouldThrowEndOfStreamException(byte[] streamContent, int bufferSize)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
Action action = () => stream.Populate(buffer);
|
||||||
|
|
||||||
|
action.Should().Throw<EndOfStreamException>();
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs
Normal file
72
Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using Just.Core.Extensions;
|
||||||
|
|
||||||
|
namespace Just.Core.Tests.SystemIOStreamExtensionsTests;
|
||||||
|
|
||||||
|
public class PopulateAsync
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task WhenCancellationRequested_ShouldThrowOperationCanceledException()
|
||||||
|
{
|
||||||
|
using var cts = new CancellationTokenSource();
|
||||||
|
byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,];
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[5];
|
||||||
|
|
||||||
|
Func<Task> action = async () => await stream.PopulateAsync(buffer, cts.Token);
|
||||||
|
cts.Cancel();
|
||||||
|
|
||||||
|
await action.Should().ThrowAsync<OperationCanceledException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0, 0)]
|
||||||
|
[InlineData(0, 1)]
|
||||||
|
[InlineData(0, 3)]
|
||||||
|
[InlineData(0, 5)]
|
||||||
|
[InlineData(3, 0)]
|
||||||
|
[InlineData(3, 1)]
|
||||||
|
[InlineData(3, 5)]
|
||||||
|
[InlineData(5, 0)]
|
||||||
|
[InlineData(5, 1)]
|
||||||
|
[InlineData(5, 5)]
|
||||||
|
public async Task WhenCalled_ShouldPopulateSpecifiedRange(int offset, int length)
|
||||||
|
{
|
||||||
|
byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,];
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[10];
|
||||||
|
|
||||||
|
await stream.PopulateAsync(buffer, offset, length);
|
||||||
|
|
||||||
|
buffer.Skip(offset).Take(length).Should().Equal(streamContent.Take(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 4)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 4)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 5)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 5)]
|
||||||
|
public async Task WhenStreamContainsSameOrGreaterAmmountOfItems_ShouldPopulateBuffer(byte[] streamContent, int bufferSize)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
await stream.PopulateAsync(buffer);
|
||||||
|
|
||||||
|
buffer.Should().Equal(streamContent.Take(bufferSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 5)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 6)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 10)]
|
||||||
|
[InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 9)]
|
||||||
|
public async Task WhenStreamContainsLessItems_ShouldThrowEndOfStreamException(byte[] streamContent, int bufferSize)
|
||||||
|
{
|
||||||
|
using var stream = new MemoryStream(streamContent);
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
Func<Task> action = async () => await stream.PopulateAsync(buffer);
|
||||||
|
|
||||||
|
await action.Should().ThrowAsync<EndOfStreamException>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,8 @@ public static class Base32
|
|||||||
[Pure]
|
[Pure]
|
||||||
public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
||||||
{
|
{
|
||||||
|
if (input.IsEmpty) return 0;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ReadOnlySpan<char> alphabet = Alphabet;
|
ReadOnlySpan<char> alphabet = Alphabet;
|
||||||
for (int offset = 0; offset < input.Length;)
|
for (int offset = 0; offset < input.Length;)
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ public static class Base64Url
|
|||||||
|
|
||||||
[Pure] public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
[Pure] public static int Encode(ReadOnlySpan<byte> input, Span<char> output)
|
||||||
{
|
{
|
||||||
|
if (input.IsEmpty) return 0;
|
||||||
|
|
||||||
var charlen = 8 * ((input.Length + 5) / 6);
|
var charlen = 8 * ((input.Length + 5) / 6);
|
||||||
Span<char> chars = stackalloc char[charlen];
|
Span<char> chars = stackalloc char[charlen];
|
||||||
Convert.TryToBase64Chars(input, chars, out int charsWritten);
|
Convert.TryToBase64Chars(input, chars, out int charsWritten);
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Just.Core.Collections;
|
namespace Just.Core.Collections;
|
||||||
|
|
||||||
public class ImmutableSequence<T> :
|
public class ImmutableSequence<T> :
|
||||||
IEnumerable<T>,
|
IEnumerable<T>,
|
||||||
IReadOnlyList<T>,
|
IReadOnlyList<T>,
|
||||||
IEquatable<ImmutableSequence<T>>,
|
IEquatable<ImmutableSequence<T>>
|
||||||
IEqualityOperators<ImmutableSequence<T>, ImmutableSequence<T>, bool>
|
|
||||||
{
|
{
|
||||||
private static readonly int InitialHash = typeof(ImmutableSequence<T>).GetHashCode();
|
private static readonly int InitialHash = typeof(ImmutableSequence<T>).GetHashCode();
|
||||||
private static readonly Func<T?, T?, bool> CompareItem = EqualityComparer<T>.Default.Equals;
|
private static readonly Func<T?, T?, bool> CompareItem = EqualityComparer<T>.Default.Equals;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<Description>Small .Net library with useful helper classes, functions and extensions.</Description>
|
<Description>Small .Net library with useful helper classes, functions and extensions.</Description>
|
||||||
<PackageTags>extensions;helpers;helper-functions</PackageTags>
|
<PackageTags>extensions;helpers;helper-functions</PackageTags>
|
||||||
<Authors>JustFixMe</Authors>
|
<Authors>JustFixMe</Authors>
|
||||||
<Copyright>Copyright (c) 2023 JustFixMe</Copyright>
|
<Copyright>Copyright (c) 2023,2024 JustFixMe</Copyright>
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<RepositoryUrl>https://github.com/JustFixMe/Just.Core/</RepositoryUrl>
|
<RepositoryUrl>https://github.com/JustFixMe/Just.Core/</RepositoryUrl>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public static class SystemIOStreamExtensions
|
|||||||
=> stream.Populate(buffer.AsSpan());
|
=> stream.Populate(buffer.AsSpan());
|
||||||
public static void Populate(this Stream stream, Span<byte> buffer)
|
public static void Populate(this Stream stream, Span<byte> buffer)
|
||||||
{
|
{
|
||||||
do
|
while (buffer.Length > 0)
|
||||||
{
|
{
|
||||||
var readed = stream.Read(buffer);
|
var readed = stream.Read(buffer);
|
||||||
|
|
||||||
@@ -19,7 +19,6 @@ public static class SystemIOStreamExtensions
|
|||||||
|
|
||||||
buffer = buffer[readed..];
|
buffer = buffer[readed..];
|
||||||
}
|
}
|
||||||
while (buffer.Length > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ValueTask PopulateAsync(this Stream stream, byte[] buffer, CancellationToken cancellationToken = default)
|
public static async ValueTask PopulateAsync(this Stream stream, byte[] buffer, CancellationToken cancellationToken = default)
|
||||||
@@ -28,7 +27,7 @@ public static class SystemIOStreamExtensions
|
|||||||
=> await stream.PopulateAsync(buffer.AsMemory(offset, length), cancellationToken);
|
=> await stream.PopulateAsync(buffer.AsMemory(offset, length), cancellationToken);
|
||||||
public static async ValueTask PopulateAsync(this Stream stream, Memory<byte> buffer, CancellationToken cancellationToken = default)
|
public static async ValueTask PopulateAsync(this Stream stream, Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
do
|
while (buffer.Length > 0)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -41,6 +40,5 @@ public static class SystemIOStreamExtensions
|
|||||||
|
|
||||||
buffer = buffer[readed..];
|
buffer = buffer[readed..];
|
||||||
}
|
}
|
||||||
while (buffer.Length > 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2023 JustFixMe
|
Copyright (c) 2023,2024 JustFixMe
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
Reference in New Issue
Block a user