mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 17:08:46 +00:00
Compare commits
16 Commits
19c467d88b
...
db96c9e6fb
Author | SHA1 | Date | |
---|---|---|---|
db96c9e6fb | |||
d022a71ce6 | |||
e51296d285 | |||
8eaa01b505 | |||
68197ef5c7 | |||
e5e27c0afd | |||
c338f4263e | |||
d2924d7ac0 | |||
77dd144321 | |||
69157b9517 | |||
4a80c93cc2 | |||
f389731703 | |||
195e25e0e3 | |||
bd1b12da71 | |||
|
8d2b4b011b | ||
25062bbf8b |
4
.github/workflows/dotnet.yml
vendored
4
.github/workflows/dotnet.yml
vendored
@ -24,7 +24,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
6.0.x
|
6.0.x
|
||||||
7.0.x
|
|
||||||
8.0.x
|
8.0.x
|
||||||
|
|
||||||
- name: Add NuGet source
|
- name: Add NuGet source
|
||||||
@ -39,9 +38,6 @@ jobs:
|
|||||||
- name: Test .NET 6
|
- name: Test .NET 6
|
||||||
run: dotnet test --no-build --verbosity normal --configuration Release --framework net6.0 --collect:"XPlat Code Coverage" --results-directory test-results/net6.0
|
run: dotnet test --no-build --verbosity normal --configuration Release --framework net6.0 --collect:"XPlat Code Coverage" --results-directory test-results/net6.0
|
||||||
|
|
||||||
- name: Test .NET 7
|
|
||||||
run: dotnet test --no-build --verbosity normal --configuration Release --framework net7.0 --collect:"XPlat Code Coverage" --results-directory test-results/net7.0
|
|
||||||
|
|
||||||
- name: Test .NET 8
|
- name: Test .NET 8
|
||||||
run: dotnet test --no-build --verbosity normal --configuration Release --framework net8.0 --collect:"XPlat Code Coverage" --results-directory test-results/net8.0
|
run: dotnet test --no-build --verbosity normal --configuration Release --framework net8.0 --collect:"XPlat Code Coverage" --results-directory test-results/net8.0
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- X10D: Added `TextWriter.WriteLineNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
- X10D: Added `TextWriter.WriteLineNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
- X10D: Added `TextWriter.WriteLineNoAlloc(long[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
- X10D: Added `TextWriter.WriteLineNoAlloc(long[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
- X10D: Added `TextWriter.WriteLineNoAlloc(ulong[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
- X10D: Added `TextWriter.WriteLineNoAlloc(ulong[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `Range.GetEnumerator` (and `RangeEnumerator`), implementing Python-esque `for` loops in C#.
|
||||||
- X10D: Added `string.ConcatIf`.
|
- X10D: Added `string.ConcatIf`.
|
||||||
- X10D: Added `string.MDBold`, `string.MDCode`, `string.MDCodeBlock([string])`, `string.MDHeading(int)`,
|
- X10D: Added `string.MDBold`, `string.MDCode`, `string.MDCodeBlock([string])`, `string.MDHeading(int)`,
|
||||||
`string.MDItalic`, `string.MDLink`, `string.MDStrikeOut`, and `string.MDUnderline` for Markdown formatting.
|
`string.MDItalic`, `string.MDLink`, `string.MDStrikeOut`, and `string.MDUnderline` for Markdown formatting.
|
||||||
@ -39,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
BigEndian/LittleEndian methods.
|
BigEndian/LittleEndian methods.
|
||||||
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` now throw ArgumentException in lieu of
|
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` now throw ArgumentException in lieu of
|
||||||
TypeInitializationException.
|
TypeInitializationException.
|
||||||
- X10D: `char.IsEmoji` no longer allocates for .NET 7.
|
- X10D: `char.IsEmoji` no longer allocates for .NET 7+.
|
||||||
- X10D: `string.Repeat` is now more efficient.
|
- X10D: `string.Repeat` is now more efficient.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
@ -48,6 +49,7 @@ TypeInitializationException.
|
|||||||
- X10D: Removed `Endianness` enum.
|
- X10D: Removed `Endianness` enum.
|
||||||
- X10D: Removed `Span<T>.Replace(T, T)` for .NET 8 target.
|
- X10D: Removed `Span<T>.Replace(T, T)` for .NET 8 target.
|
||||||
- X10D: Removed .NET Standard 2.1 target.
|
- X10D: Removed .NET Standard 2.1 target.
|
||||||
|
- X10D: Removed extensions for `Progress<T>`. These are already provided by [`Observable.FromEventPattern`](https://learn.microsoft.com/en-us/previous-versions/dotnet/reactive-extensions/hh229424(v=vs.103)).
|
||||||
- X10D.Hosting: Removed .NET Standard 2.1 target.
|
- X10D.Hosting: Removed .NET Standard 2.1 target.
|
||||||
- X10D.DSharpPlus: Complete sunset of library. This library will not be updated to support DSharpPlus v5.0.0 (#83).
|
- X10D.DSharpPlus: Complete sunset of library. This library will not be updated to support DSharpPlus v5.0.0 (#83).
|
||||||
- X10D.Unity: Complete sunset of library. This library will not be updated effective immediately (#86).
|
- X10D.Unity: Complete sunset of library. This library will not be updated effective immediately (#86).
|
||||||
@ -56,6 +58,7 @@ TypeInitializationException.
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- X10D: Fixed `decimal.TryWriteBigEndianBytes` and `decimal.TryWriteLittleEndianBytes`.
|
||||||
- X10D.Hosting: Fixed `AddHostedSingleton` not accepting an interface as the service type.
|
- X10D.Hosting: Fixed `AddHostedSingleton` not accepting an interface as the service type.
|
||||||
|
|
||||||
## [3.3.0] - 2023-08-21
|
## [3.3.0] - 2023-08-21
|
||||||
|
@ -5,7 +5,7 @@ or submit a pull request.
|
|||||||
|
|
||||||
### Pull request guidelines
|
### Pull request guidelines
|
||||||
|
|
||||||
This project uses C# 11.0 language features where feasible, and adheres to StyleCop rules with some minor adjustments.
|
This project uses C# 12.0 language features where feasible, and adheres to StyleCop rules with some minor adjustments.
|
||||||
There is an `.editorconfig` included in this repository. For quick and painless pull requests, ensure that the analyzer does not
|
There is an `.editorconfig` included in this repository. For quick and painless pull requests, ensure that the analyzer does not
|
||||||
throw warnings.
|
throw warnings.
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ convetional commits specification.
|
|||||||
|
|
||||||
Below are a few pointers to which you may refer, but keep in mind this is not an exhaustive list:
|
Below are a few pointers to which you may refer, but keep in mind this is not an exhaustive list:
|
||||||
|
|
||||||
- Use C# 11.0 features where possible
|
- Use C# 12.0 features where possible
|
||||||
- Try to ensure code is CLS-compliant. Where this is not possible, decorate methods with `CLSCompliantAttribute` and pass `false`
|
- Try to ensure code is CLS-compliant. Where this is not possible, decorate methods with `CLSCompliantAttribute` and pass `false`
|
||||||
- Follow all .NET guidelines and coding conventions.
|
- Follow all .NET guidelines and coding conventions.
|
||||||
See https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions
|
See https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>11.0</LangVersion>
|
<LangVersion>12.0</LangVersion>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<ImplicitUsings>true</ImplicitUsings>
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
<CoverletOutputFormat>xml,cobertura</CoverletOutputFormat>
|
<CoverletOutputFormat>xml,cobertura</CoverletOutputFormat>
|
||||||
|
66
X10D.Tests/src/Core/RangeTests.cs
Normal file
66
X10D.Tests/src/Core/RangeTests.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.Core;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Core;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
internal class RangeTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Range_GetEnumerator_ShouldReturnRangeEnumerator()
|
||||||
|
{
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(5..10, Is.TypeOf<Range>());
|
||||||
|
Assert.That((5..10).GetEnumerator(), Is.TypeOf<RangeEnumerator>());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Loop_OverRange0To10_ShouldCountFrom0To10Inclusive()
|
||||||
|
{
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
foreach (int i in 0..10)
|
||||||
|
{
|
||||||
|
Assert.That(i, Is.EqualTo(value));
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Loop_OverRangeNegative5To5_ShouldCountFromNegative5To5Inclusive()
|
||||||
|
{
|
||||||
|
int value = -5;
|
||||||
|
|
||||||
|
foreach (int i in ^5..5)
|
||||||
|
{
|
||||||
|
Assert.That(i, Is.EqualTo(value));
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Loop_OverRange5ToNegative5_ShouldCountFrom5ToNegative5Inclusive()
|
||||||
|
{
|
||||||
|
int value = 5;
|
||||||
|
|
||||||
|
foreach (int i in 5..^5)
|
||||||
|
{
|
||||||
|
Assert.That(i, Is.EqualTo(value));
|
||||||
|
value--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Loop_OverRange10To0_ShouldCountFrom10To0Inclusive()
|
||||||
|
{
|
||||||
|
int value = 10;
|
||||||
|
|
||||||
|
foreach (int i in 10..0)
|
||||||
|
{
|
||||||
|
Assert.That(i, Is.EqualTo(value));
|
||||||
|
value--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
X10D.Tests/src/IO/DecimalTests.cs
Normal file
72
X10D.Tests/src/IO/DecimalTests.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.IO;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
internal class DecimalTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void GetBigEndianBytes_ShouldReturnBytes_InBigEndian()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210];
|
||||||
|
|
||||||
|
byte[] bytes = value.GetBigEndianBytes();
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetLittleEndianBytes_ShouldReturnBytes_InLittleEndian()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
byte[] expected = [210, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
|
byte[] bytes = value.GetLittleEndianBytes();
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryWriteBigEndianBytes_ShouldWriteBytes_InBigEndian()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
byte[] expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 210];
|
||||||
|
|
||||||
|
Span<byte> bytes = stackalloc byte[16];
|
||||||
|
Assert.That(value.TryWriteBigEndianBytes(bytes));
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, bytes.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryWriteLittleEndianBytes_ShouldWriteBytes_InLittleEndian()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
byte[] expected = [210, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
|
Span<byte> bytes = stackalloc byte[16];
|
||||||
|
Assert.That(value.TryWriteLittleEndianBytes(bytes));
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(expected, bytes.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryWriteBigEndianBytes_ShouldReturnFalse_GivenSmallSpan()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
|
||||||
|
Span<byte> bytes = Span<byte>.Empty;
|
||||||
|
Assert.That(value.TryWriteBigEndianBytes(bytes), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TryWriteLittleEndianBytes_ShouldReturnFalse_GivenSmallSpan()
|
||||||
|
{
|
||||||
|
const decimal value = 1234m;
|
||||||
|
|
||||||
|
Span<byte> bytes = Span<byte>.Empty;
|
||||||
|
Assert.That(value.TryWriteLittleEndianBytes(bytes), Is.False);
|
||||||
|
}
|
||||||
|
}
|
@ -48,9 +48,10 @@ internal partial class StreamTests
|
|||||||
Span<byte> actual = stackalloc byte[16];
|
Span<byte> actual = stackalloc byte[16];
|
||||||
ReadOnlySpan<byte> expected = stackalloc byte[]
|
ReadOnlySpan<byte> expected = stackalloc byte[]
|
||||||
{
|
{
|
||||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x68
|
||||||
};
|
};
|
||||||
int read = stream.Read(actual);
|
int read = stream.Read(actual);
|
||||||
|
Trace.WriteLine(string.Join(' ', actual.ToArray()));
|
||||||
|
|
||||||
Assert.That(read, Is.EqualTo(16));
|
Assert.That(read, Is.EqualTo(16));
|
||||||
CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray());
|
CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray());
|
||||||
|
32
X10D.Tests/src/Numerics/NumberTests.cs
Normal file
32
X10D.Tests/src/Numerics/NumberTests.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#if NET7_0_OR_GREATER
|
||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.Math;
|
||||||
|
|
||||||
|
namespace X10D.Tests.Numerics;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
internal class NumberTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Sign_ShouldReturn1_GivenPositiveNumber()
|
||||||
|
{
|
||||||
|
Assert.That(NumberExtensions.Sign(2), Is.Positive);
|
||||||
|
Assert.That(NumberExtensions.Sign(2), Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Sign_Should0_GivenZero()
|
||||||
|
{
|
||||||
|
Assert.That(NumberExtensions.Sign(0), Is.Not.Positive);
|
||||||
|
Assert.That(NumberExtensions.Sign(0), Is.Not.Negative);
|
||||||
|
Assert.That(NumberExtensions.Sign(0), Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Sign_ShouldReturnNegative1_GivenNegativeNumber()
|
||||||
|
{
|
||||||
|
Assert.That(NumberExtensions.Sign(-2), Is.Negative);
|
||||||
|
Assert.That(NumberExtensions.Sign(-2), Is.EqualTo(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,67 +0,0 @@
|
|||||||
using NUnit.Framework;
|
|
||||||
using X10D.Reactive;
|
|
||||||
|
|
||||||
namespace X10D.Tests.Reactive;
|
|
||||||
|
|
||||||
[TestFixture]
|
|
||||||
internal class ProgressTests
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void OnProgressChanged_ShouldCallCompletionDelegate_GivenCompletionValue()
|
|
||||||
{
|
|
||||||
var subscriberWasCalled = false;
|
|
||||||
var completionWasCalled = false;
|
|
||||||
|
|
||||||
var progress = new Progress<float>();
|
|
||||||
progress.OnProgressChanged(1.0f).Subscribe(_ => subscriberWasCalled = true, () => completionWasCalled = true);
|
|
||||||
|
|
||||||
((IProgress<float>)progress).Report(0.5f);
|
|
||||||
((IProgress<float>)progress).Report(1.0f);
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
Assert.That(subscriberWasCalled);
|
|
||||||
Assert.That(completionWasCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnProgressChanged_ShouldCallSubscribers_OnProgressChanged()
|
|
||||||
{
|
|
||||||
var subscriberWasCalled = false;
|
|
||||||
|
|
||||||
var progress = new Progress<float>();
|
|
||||||
progress.OnProgressChanged().Subscribe(_ => subscriberWasCalled = true);
|
|
||||||
|
|
||||||
((IProgress<float>)progress).Report(0.5f);
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
Assert.That(subscriberWasCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnProgressChanged_ShouldCallSubscribers_OnProgressChanged_GivenCompletionValue()
|
|
||||||
{
|
|
||||||
var subscriberWasCalled = false;
|
|
||||||
|
|
||||||
var progress = new Progress<float>();
|
|
||||||
progress.OnProgressChanged(1.0f).Subscribe(_ => subscriberWasCalled = true);
|
|
||||||
|
|
||||||
((IProgress<float>)progress).Report(0.5f);
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
Assert.That(subscriberWasCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnProgressChanged_ShouldThrowArgumentNullException_GivenNullProgress()
|
|
||||||
{
|
|
||||||
Progress<float> progress = null!;
|
|
||||||
Assert.Throws<ArgumentNullException>(() => progress.OnProgressChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void OnProgressChanged_ShouldThrowArgumentNullException_GivenNullProgressAndCompletionValue()
|
|
||||||
{
|
|
||||||
Progress<float> progress = null!;
|
|
||||||
Assert.Throws<ArgumentNullException>(() => progress.OnProgressChanged(1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#if NET7_0_OR_GREATER
|
#if NET7_0_OR_GREATER
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -48,6 +49,28 @@ public static class BinaryIntegerExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnpackInternal(value, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(CompilerResources.MaxOptimization)]
|
||||||
|
private static void UnpackInternal_Fallback<TInteger>(this TInteger value, Span<bool> destination)
|
||||||
|
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
int bitCount = sizeof(TInteger) * 8;
|
||||||
|
for (var index = 0; index < bitCount; index++)
|
||||||
|
{
|
||||||
|
destination[index] = (value & (TInteger.One << index)) != TInteger.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ExcludeFromCodeCoverage]
|
||||||
|
[MethodImpl(CompilerResources.MaxOptimization)]
|
||||||
|
private static void UnpackInternal<TInteger>(TInteger value, Span<bool> destination)
|
||||||
|
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
||||||
|
{
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case byte valueByte when Sse3.IsSupported:
|
case byte valueByte when Sse3.IsSupported:
|
||||||
@ -71,19 +94,5 @@ public static class BinaryIntegerExtensions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(CompilerResources.MaxOptimization)]
|
|
||||||
internal static void UnpackInternal_Fallback<TInteger>(this TInteger value, Span<bool> destination)
|
|
||||||
where TInteger : unmanaged, IBinaryInteger<TInteger>
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
int bitCount = sizeof(TInteger) * 8;
|
|
||||||
for (var index = 0; index < bitCount; index++)
|
|
||||||
{
|
|
||||||
destination[index] = (value & (TInteger.One << index)) != TInteger.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
53
X10D/src/Core/RangeEnumerator.cs
Normal file
53
X10D/src/Core/RangeEnumerator.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
namespace X10D.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerates the indices of a <see cref="Range" />.
|
||||||
|
/// </summary>
|
||||||
|
public struct RangeEnumerator
|
||||||
|
{
|
||||||
|
private readonly bool _decrement;
|
||||||
|
private readonly int _endValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RangeEnumerator" /> structure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="range">The range over which to enumerate.</param>
|
||||||
|
public RangeEnumerator(Range range)
|
||||||
|
{
|
||||||
|
Index start = range.Start;
|
||||||
|
Index end = range.End;
|
||||||
|
|
||||||
|
int startValue = start.IsFromEnd ? -start.Value : start.Value;
|
||||||
|
_endValue = end.IsFromEnd ? -end.Value : end.Value;
|
||||||
|
|
||||||
|
_decrement = _endValue < startValue;
|
||||||
|
Current = _decrement ? startValue + 1 : startValue - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the element in the collection at the current position of the enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The element in the collection at the current position of the enumerator.</value>
|
||||||
|
public int Current { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Advances the enumerator to the next element of the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if the enumerator was successfully advanced to the next element; <see langword="false" /> if
|
||||||
|
/// the enumerator has passed the end of the collection.
|
||||||
|
/// </returns>
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
int value = Current;
|
||||||
|
|
||||||
|
if (_decrement)
|
||||||
|
{
|
||||||
|
Current--;
|
||||||
|
return value > _endValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Current++;
|
||||||
|
return value < _endValue;
|
||||||
|
}
|
||||||
|
}
|
48
X10D/src/Core/RangeExtensions.cs
Normal file
48
X10D/src/Core/RangeExtensions.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
namespace X10D.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="Range" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class RangeExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the ability to use a <c>for</c> loop to iterate over the indices of a <see cref="Range" />. The indices of the
|
||||||
|
/// range are the inclusive lower and upper bounds of the enumeration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="range">The range whose indices over which will be enumerated.</param>
|
||||||
|
/// <returns>A <see cref="RangeEnumerator" /> that will enumerate over the indices of <paramref name="range" />.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// This method aims to implement Python-esque for loops in C# by taking advantage of the language syntax used to define
|
||||||
|
/// a <see cref="Range" /> value. Negative bounds may be specified using the C# <c>^</c> operator, or by providing an
|
||||||
|
/// <see cref="Index" /> whose <see cref="Index.IsFromEnd" /> property is <see langword="true" />.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// The following example counts from 0 to 10 inclusive:
|
||||||
|
/// <code>
|
||||||
|
/// foreach (var i in 0..10)
|
||||||
|
/// {
|
||||||
|
/// Console.WriteLine(i);
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
///
|
||||||
|
/// To use negative bounds, use the <c>^</c> operator. The following example counts from -5 to 5 inclusive:
|
||||||
|
/// <code>
|
||||||
|
/// foreach (var i in ^5..5)
|
||||||
|
/// {
|
||||||
|
/// Console.WriteLine(i);
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
///
|
||||||
|
/// Decrementing enumeration is supported. The following example counts from 5 to -5 inclusive:
|
||||||
|
/// <code>
|
||||||
|
/// foreach (var i in 5..^5)
|
||||||
|
/// {
|
||||||
|
/// Console.WriteLine(i);
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
public static RangeEnumerator GetEnumerator(this Range range)
|
||||||
|
{
|
||||||
|
return new RangeEnumerator(range);
|
||||||
|
}
|
||||||
|
}
|
@ -92,14 +92,12 @@ public static class SpanExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dotcover disable
|
// dotcover disable
|
||||||
//NOSONAR
|
|
||||||
default:
|
default:
|
||||||
#if NET7_0_OR_GREATER
|
#if NET7_0_OR_GREATER
|
||||||
throw new UnreachableException(string.Format(ExceptionMessages.EnumSizeIsUnexpected, Unsafe.SizeOf<T>()));
|
throw new UnreachableException(string.Format(ExceptionMessages.EnumSizeIsUnexpected, Unsafe.SizeOf<T>()));
|
||||||
#else
|
#else
|
||||||
throw new ArgumentException(string.Format(ExceptionMessages.EnumSizeIsUnexpected, Unsafe.SizeOf<T>()));
|
throw new ArgumentException(string.Format(ExceptionMessages.EnumSizeIsUnexpected, Unsafe.SizeOf<T>()));
|
||||||
#endif
|
#endif
|
||||||
//NOSONAR
|
|
||||||
// dotcover enable
|
// dotcover enable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@ -13,11 +12,11 @@ public static class DecimalExtensions
|
|||||||
/// Converts the current decimal number into an array of bytes, as little endian.
|
/// Converts the current decimal number into an array of bytes, as little endian.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The <see cref="int" /> value.</param>
|
/// <param name="value">The <see cref="int" /> value.</param>
|
||||||
/// <returns>An array of bytes with length 4.</returns>
|
/// <returns>An array of bytes with length 16.</returns>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static byte[] GetBigEndianBytes(this decimal value)
|
public static byte[] GetBigEndianBytes(this decimal value)
|
||||||
{
|
{
|
||||||
Span<byte> buffer = stackalloc byte[4];
|
Span<byte> buffer = stackalloc byte[16];
|
||||||
value.TryWriteBigEndianBytes(buffer);
|
value.TryWriteBigEndianBytes(buffer);
|
||||||
return buffer.ToArray();
|
return buffer.ToArray();
|
||||||
}
|
}
|
||||||
@ -26,11 +25,11 @@ public static class DecimalExtensions
|
|||||||
/// Converts the current decimal number into an array of bytes, as little endian.
|
/// Converts the current decimal number into an array of bytes, as little endian.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The <see cref="int" /> value.</param>
|
/// <param name="value">The <see cref="int" /> value.</param>
|
||||||
/// <returns>An array of bytes with length 4.</returns>
|
/// <returns>An array of bytes with length 16.</returns>
|
||||||
[Pure]
|
[Pure]
|
||||||
public static byte[] GetLittleEndianBytes(this decimal value)
|
public static byte[] GetLittleEndianBytes(this decimal value)
|
||||||
{
|
{
|
||||||
Span<byte> buffer = stackalloc byte[4];
|
Span<byte> buffer = stackalloc byte[16];
|
||||||
value.TryWriteLittleEndianBytes(buffer);
|
value.TryWriteLittleEndianBytes(buffer);
|
||||||
return buffer.ToArray();
|
return buffer.ToArray();
|
||||||
}
|
}
|
||||||
@ -44,23 +43,17 @@ public static class DecimalExtensions
|
|||||||
public static bool TryWriteBigEndianBytes(this decimal value, Span<byte> destination)
|
public static bool TryWriteBigEndianBytes(this decimal value, Span<byte> destination)
|
||||||
{
|
{
|
||||||
Span<int> buffer = stackalloc int[4];
|
Span<int> buffer = stackalloc int[4];
|
||||||
GetBits(value, buffer);
|
decimal.GetBits(value, buffer);
|
||||||
|
|
||||||
if (buffer[0].TryWriteBigEndianBytes(destination[..4]) &&
|
Span<byte> result = stackalloc byte[16];
|
||||||
buffer[1].TryWriteBigEndianBytes(destination[4..8]) &&
|
MemoryMarshal.Cast<int, byte>(buffer).CopyTo(result);
|
||||||
buffer[2].TryWriteBigEndianBytes(destination[8..12]) &&
|
|
||||||
buffer[3].TryWriteBigEndianBytes(destination[12..]))
|
if (BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
if (BitConverter.IsLittleEndian)
|
result.Reverse();
|
||||||
{
|
|
||||||
destination.Reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destination.Clear();
|
return result.TryCopyTo(destination);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -72,44 +65,16 @@ public static class DecimalExtensions
|
|||||||
public static bool TryWriteLittleEndianBytes(this decimal value, Span<byte> destination)
|
public static bool TryWriteLittleEndianBytes(this decimal value, Span<byte> destination)
|
||||||
{
|
{
|
||||||
Span<int> buffer = stackalloc int[4];
|
Span<int> buffer = stackalloc int[4];
|
||||||
GetBits(value, buffer);
|
decimal.GetBits(value, buffer);
|
||||||
|
|
||||||
if (buffer[0].TryWriteLittleEndianBytes(destination[..4]) &&
|
Span<byte> result = stackalloc byte[16];
|
||||||
buffer[1].TryWriteLittleEndianBytes(destination[4..8]) &&
|
MemoryMarshal.Cast<int, byte>(buffer).CopyTo(result);
|
||||||
buffer[2].TryWriteLittleEndianBytes(destination[8..12]) &&
|
|
||||||
buffer[3].TryWriteLittleEndianBytes(destination[12..]))
|
if (!BitConverter.IsLittleEndian)
|
||||||
{
|
{
|
||||||
if (!BitConverter.IsLittleEndian)
|
result.Reverse();
|
||||||
{
|
|
||||||
destination.Reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destination.Clear();
|
return result.TryCopyTo(destination);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetBits(decimal value, Span<int> destination)
|
|
||||||
{
|
|
||||||
_ = decimal.GetBits(value, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !NET5_0_OR_GREATER
|
|
||||||
private static void WriteBits(Span<int> destination, Span<byte> buffer)
|
|
||||||
{
|
|
||||||
var flags = MemoryMarshal.Read<int>(buffer[..4]);
|
|
||||||
var hi = MemoryMarshal.Read<int>(buffer[4..8]);
|
|
||||||
var lo = MemoryMarshal.Read<long>(buffer[8..]);
|
|
||||||
|
|
||||||
var low = (uint)lo;
|
|
||||||
var mid = (uint)(lo >> 32);
|
|
||||||
|
|
||||||
destination[0] = (int)low;
|
|
||||||
destination[1] = (int)mid;
|
|
||||||
destination[2] = hi;
|
|
||||||
destination[3] = flags;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
namespace X10D.Reactive;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a disposable that removes an observer from a collection of observers.
|
|
||||||
/// </summary>
|
|
||||||
internal readonly struct ObservableDisposer<T> : IDisposable
|
|
||||||
{
|
|
||||||
private readonly HashSet<IObserver<T>> _observers;
|
|
||||||
private readonly IObserver<T> _observer;
|
|
||||||
private readonly Action? _additionalAction;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ObservableDisposer{T}" /> struct.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="observers">A collection of observers from which to remove the specified observer.</param>
|
|
||||||
/// <param name="observer">The observer to remove from the collection.</param>
|
|
||||||
/// <param name="additionalAction">The additional action to run on dispose.</param>
|
|
||||||
public ObservableDisposer(HashSet<IObserver<T>> observers, IObserver<T> observer, Action? additionalAction)
|
|
||||||
{
|
|
||||||
_observers = observers ?? throw new ArgumentNullException(nameof(observers));
|
|
||||||
_observer = observer ?? throw new ArgumentNullException(nameof(observer));
|
|
||||||
_additionalAction = additionalAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the observer from the collection of observers.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_observers.Remove(_observer);
|
|
||||||
_additionalAction?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
namespace X10D.Reactive;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides extension methods for <see cref="Progress{T}" />.
|
|
||||||
/// </summary>
|
|
||||||
public static class ProgressExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the <see cref="Progress{T}.ProgressChanged" /> event of the current <see cref="Progress{T}" /> in an
|
|
||||||
/// <see cref="IObservable{T}" /> object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="progress">The progress whose <see cref="Progress{T}.ProgressChanged" /> event to wrap.</param>
|
|
||||||
/// <typeparam name="T">The type of progress update value.</typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// An <see cref="IObservable{T}" /> object that wraps the <see cref="Progress{T}.ProgressChanged" /> event of the current
|
|
||||||
/// <see cref="Progress{T}" />.
|
|
||||||
/// </returns>
|
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="progress" /> is <see langword="null" />.</exception>
|
|
||||||
public static IObservable<T> OnProgressChanged<T>(this Progress<T> progress)
|
|
||||||
{
|
|
||||||
if (progress is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(progress));
|
|
||||||
}
|
|
||||||
|
|
||||||
var progressObservable = new ProgressObservable<T>();
|
|
||||||
|
|
||||||
void ProgressChangedHandler(object? sender, T args)
|
|
||||||
{
|
|
||||||
IObserver<T>[] observers = progressObservable.Observers;
|
|
||||||
|
|
||||||
for (var index = 0; index < observers.Length; index++)
|
|
||||||
{
|
|
||||||
observers[index].OnNext(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.ProgressChanged += ProgressChangedHandler;
|
|
||||||
progressObservable.OnDispose = () => progress.ProgressChanged -= ProgressChangedHandler;
|
|
||||||
|
|
||||||
return progressObservable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the <see cref="Progress{T}.ProgressChanged" /> event of the current <see cref="Progress{T}" /> in an
|
|
||||||
/// <see cref="IObservable{T}" /> object, and completes the observable when the progress reaches the specified value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="progress">The progress whose <see cref="Progress{T}.ProgressChanged" /> event to wrap.</param>
|
|
||||||
/// <param name="completeValue">The value that indicates completion.</param>
|
|
||||||
/// <typeparam name="T">The type of progress update value.</typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// An <see cref="IObservable{T}" /> object that wraps the <see cref="Progress{T}.ProgressChanged" /> event of the current
|
|
||||||
/// <see cref="Progress{T}" />.
|
|
||||||
/// </returns>
|
|
||||||
/// <exception cref="ArgumentNullException"><paramref name="progress" /> is <see langword="null" />.</exception>
|
|
||||||
public static IObservable<T> OnProgressChanged<T>(this Progress<T> progress, T completeValue)
|
|
||||||
{
|
|
||||||
if (progress is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(progress));
|
|
||||||
}
|
|
||||||
|
|
||||||
var progressObservable = new ProgressObservable<T>();
|
|
||||||
var comparer = EqualityComparer<T>.Default;
|
|
||||||
|
|
||||||
void ProgressChangedHandler(object? sender, T args)
|
|
||||||
{
|
|
||||||
IObserver<T>[] observers = progressObservable.Observers;
|
|
||||||
|
|
||||||
for (var index = 0; index < observers.Length; index++)
|
|
||||||
{
|
|
||||||
observers[index].OnNext(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comparer.Equals(args, completeValue))
|
|
||||||
{
|
|
||||||
for (var index = 0; index < observers.Length; index++)
|
|
||||||
{
|
|
||||||
observers[index].OnCompleted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress.ProgressChanged += ProgressChangedHandler;
|
|
||||||
progressObservable.OnDispose = () => progress.ProgressChanged -= ProgressChangedHandler;
|
|
||||||
|
|
||||||
return progressObservable;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
namespace X10D.Reactive;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a concrete implementation of <see cref="IObservable{T}" /> that tracks progress of a <see cref="Progress{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class ProgressObservable<T> : IObservable<T>
|
|
||||||
{
|
|
||||||
private readonly HashSet<IObserver<T>> _observers = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the observers.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The observers.</value>
|
|
||||||
public IObserver<T>[] Observers
|
|
||||||
{
|
|
||||||
get => _observers.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Action? OnDispose { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Subscribes the specified observer to the progress tracker.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="observer">The observer.</param>
|
|
||||||
/// <returns>An object which can be disposed to unsubscribe from progress tracking.</returns>
|
|
||||||
public IDisposable Subscribe(IObserver<T> observer)
|
|
||||||
{
|
|
||||||
if (observer is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(observer));
|
|
||||||
}
|
|
||||||
|
|
||||||
_observers.Add(observer);
|
|
||||||
return new ObservableDisposer<T>(_observers, observer, OnDispose);
|
|
||||||
}
|
|
||||||
}
|
|
@ -98,7 +98,6 @@ public static class RuneExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dotcover disable
|
// dotcover disable
|
||||||
//NOSONAR
|
|
||||||
default:
|
default:
|
||||||
string exceptionFormat = ExceptionMessages.UnexpectedRuneUtf8SequenceLength;
|
string exceptionFormat = ExceptionMessages.UnexpectedRuneUtf8SequenceLength;
|
||||||
string message = string.Format(CultureInfo.CurrentCulture, exceptionFormat, length);
|
string message = string.Format(CultureInfo.CurrentCulture, exceptionFormat, length);
|
||||||
@ -107,7 +106,6 @@ public static class RuneExtensions
|
|||||||
#else
|
#else
|
||||||
throw new InvalidOperationException(message);
|
throw new InvalidOperationException(message);
|
||||||
#endif
|
#endif
|
||||||
//NOSONAR
|
|
||||||
// dotcover enable
|
// dotcover enable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
codecov.yml
Normal file
2
codecov.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ignore:
|
||||||
|
- "X10D/src/ExceptionMessages.Designer.cs"
|
@ -3,6 +3,9 @@
|
|||||||
X10D 4.0.0 is a major release that introduces breaking changes. This document will help you migrate your code from 3.x.x
|
X10D 4.0.0 is a major release that introduces breaking changes. This document will help you migrate your code from 3.x.x
|
||||||
to 4.0.0.
|
to 4.0.0.
|
||||||
|
|
||||||
|
When a breaking change is mentioned, the compatibility mirrors that of the Microsoft documentation for .NET, which you
|
||||||
|
can find [here](https://learn.microsoft.com/en-us/dotnet/core/compatibility/categories).
|
||||||
|
|
||||||
## Removed APIs
|
## Removed APIs
|
||||||
|
|
||||||
### X10D.DSharpPlus library
|
### X10D.DSharpPlus library
|
||||||
@ -12,8 +15,18 @@ wrapper library. However, I have since moved to using a different library, and a
|
|||||||
scope of X10D or in my best interest to maintain it. The library will remain available on NuGet until DSharpPlus release
|
scope of X10D or in my best interest to maintain it. The library will remain available on NuGet until DSharpPlus release
|
||||||
5.0.0 as stable, and X10D.DSharpPlus will NOT be part of X10D 4.0.0. I'm sorry for any inconvenience this may cause.
|
5.0.0 as stable, and X10D.DSharpPlus will NOT be part of X10D 4.0.0. I'm sorry for any inconvenience this may cause.
|
||||||
|
|
||||||
|
### X10D.Unity library
|
||||||
|
|
||||||
|
The `X10D.Unity` library has been removed. This library was used to provide extension methods for the Unity API. Due to
|
||||||
|
game development politics, I no longer feel it in my best interest to continue development of the Unity package. The
|
||||||
|
library will remain on NuGet for the foreseeable future but will no longer be maintained. The `upm` branch of the Git
|
||||||
|
repository will remain available indefinitely also.
|
||||||
|
|
||||||
|
|
||||||
### `Endianness` enum
|
### `Endianness` enum
|
||||||
|
|
||||||
|
**Source incompatible change**
|
||||||
|
|
||||||
The `Endianness` enum was used to specify the endianness of data when reading or writing to a stream. This was causing
|
The `Endianness` enum was used to specify the endianness of data when reading or writing to a stream. This was causing
|
||||||
some clutter, and makes it harder to develop X10D, so it was removed. In its stead, any method which accepted an
|
some clutter, and makes it harder to develop X10D, so it was removed. In its stead, any method which accepted an
|
||||||
`Endianness` parameter now has two overloads: one for big-endian, and one for little-endian. For example, the following
|
`Endianness` parameter now has two overloads: one for big-endian, and one for little-endian. For example, the following
|
||||||
@ -41,12 +54,16 @@ Span<byte> buffer = stackalloc byte[4];
|
|||||||
|
|
||||||
### `IEnumerable<T>.ConcatOne(T)` extension method
|
### `IEnumerable<T>.ConcatOne(T)` extension method
|
||||||
|
|
||||||
|
**Source incompatible change**
|
||||||
|
|
||||||
The `IEnumerable<T>.ConcatOne` extension method was used to concatenate a single item to an enumerable. At the time, I
|
The `IEnumerable<T>.ConcatOne` extension method was used to concatenate a single item to an enumerable. At the time, I
|
||||||
was unaware of the `Enumerable.Append` method, which does the same thing. As such, `ConcatOne` has been removed. There
|
was unaware of the `Enumerable.Append` method, which does the same thing. As such, `ConcatOne` has been removed. There
|
||||||
is no migration path for this, as the built in `Append` method from LINQ is a drop-in replacement.
|
is no migration path for this, as the built in `Append` method from LINQ is a drop-in replacement.
|
||||||
|
|
||||||
## Exception Changes
|
## Exception Changes
|
||||||
|
|
||||||
|
**Source incompatible change**
|
||||||
|
|
||||||
If you were previously catching TypeInitializationException when calling `Stream.GetHash<>` or `Stream.TryWriteHash<>`,
|
If you were previously catching TypeInitializationException when calling `Stream.GetHash<>` or `Stream.TryWriteHash<>`,
|
||||||
you will now need to catch a ArgumentException instead. The justification for this change is that ArgumentException is
|
you will now need to catch a ArgumentException instead. The justification for this change is that ArgumentException is
|
||||||
more general, and more easily understood by developers.
|
more general, and more easily understood by developers.
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net7.0;net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
|
Loading…
Reference in New Issue
Block a user