1
0
mirror of https://github.com/oliverbooth/X10D synced 2024-11-22 23:58:48 +00:00

Compare commits

..

No commits in common. "6020a6e602465dc0749fb70feb1270525856af7d" and "25062bbf8b674437f8b884b79fd74d535da8cf69" have entirely different histories.

524 changed files with 17293 additions and 5551 deletions

18
.github/workflows/activate-unity.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: Acquire activation file
on:
workflow_dispatch: {}
jobs:
activation:
name: Request manual activation file 🔑
runs-on: ubuntu-latest
steps:
# Request manual activation file
- name: Request manual activation file
id: getManualLicenseFile
uses: game-ci/unity-request-activation-file@v2
# Upload artifact (Unity_v20XX.X.XXXX.alf)
- name: Expose as artifact
uses: actions/upload-artifact@v2
with:
name: ${{ steps.getManualLicenseFile.outputs.filePath }}
path: ${{ steps.getManualLicenseFile.outputs.filePath }}

View File

@ -23,8 +23,9 @@ jobs:
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: | dotnet-version: |
3.1.x
6.0.x 6.0.x
8.0.x 7.0.x
- name: Add NuGet source - name: Add NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json" run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
@ -32,18 +33,36 @@ jobs:
- name: Restore dependencies - name: Restore dependencies
run: dotnet restore run: dotnet restore
- name: Install coverage tools
run: |
dotnet tool install --global JetBrains.dotCover.GlobalTool
dotnet tool install --global dotnet-reportgenerator-globaltool
- name: Build - name: Build
run: dotnet build --no-restore --configuration Release run: dotnet build --no-restore --configuration Release
- name: Test .NET Core 3.1
run: dotnet test --no-build --verbosity normal --configuration Release --framework netcoreapp3.1
- 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
- name: Test .NET 7
run: dotnet test --no-build --verbosity normal --configuration Release --framework 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
- name: Collect coverage
run: dotnet dotcover test --dcReportType=DetailedXML
- name: Convert coverage
run: reportgenerator -reports:./dotCover.Output.xml -targetdir:. -reporttypes:Cobertura
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.0 uses: codecov/codecov-action@v4.0.0
with: with:
directory: test-results disable_search: true
file: Cobertura.xml
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
slug: oliverbooth/X10D slug: oliverbooth/X10D

View File

@ -18,7 +18,7 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: 8.0.x dotnet-version: 7.0.x
- name: Add GitHub NuGet source - name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json" run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
@ -33,7 +33,9 @@ jobs:
run: | run: |
mkdir build mkdir build
dotnet pack X10D --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }} dotnet pack X10D --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.DSharpPlus --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Hosting --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }} dotnet pack X10D.Hosting --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Unity --configuration Debug --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub - name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
@ -46,3 +48,42 @@ jobs:
with: with:
name: build name: build
path: build/ path: build/
- name: Checkout upm branch
uses: actions/checkout@v3
with:
ref: upm
path: upm
- name: Build package.json
run: |
dotnet run --project ./tools/UpmPackageGenerator/UpmPackageGenerator.csproj "./X10D/bin/Debug/netstandard2.1/X10D.dll"
cp package.json upm/package.json
- name: Copy built artifacts to upm
run: |
cd upm
cp ../X10D/bin/Debug/netstandard2.1/X10D.dll ./X10D.dll
cp ../X10D/bin/Debug/netstandard2.1/X10D.xml ./X10D.xml
cp ../X10D.Unity/bin/Debug/netstandard2.1/X10D.Unity.dll ./X10D.Unity.dll
cp ../X10D.Unity/bin/Debug/netstandard2.1/X10D.Unity.xml ./X10D.Unity.xml
- name: Check for changes
run: |
cd upm
git diff --quiet
continue-on-error: true
- name: Commit update
if: ${{ success() }}
run: |
cd upm
git config user.name github-actions
git config user.email github-actions@github.com
git add X10D.dll
git add X10D.Unity.dll
git add X10D.xml
git add X10D.Unity.xml
git add package.json
git commit -m "Update upm branch ($GITHUB_SHA)"
git push

View File

@ -17,7 +17,7 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: 8.0.x dotnet-version: 7.0.x
- name: Add GitHub NuGet source - name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json" run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
@ -32,7 +32,9 @@ jobs:
run: | run: |
mkdir build mkdir build
dotnet pack X10D --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} dotnet pack X10D --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.DSharpPlus --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Hosting --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} dotnet pack X10D.Hosting --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Unity --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub - name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
@ -51,3 +53,42 @@ jobs:
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true prerelease: true
- name: Checkout upm branch
uses: actions/checkout@v3
with:
ref: upm
path: upm
- name: Build package.json
run: |
dotnet run --project ./tools/UpmPackageGenerator/UpmPackageGenerator.csproj "./X10D/bin/Release/netstandard2.1/X10D.dll"
cp package.json upm/package.json
- name: Copy built artifacts to upm
run: |
cd upm
cp ../X10D/bin/Release/netstandard2.1/X10D.dll ./X10D.dll
cp ../X10D/bin/Release/netstandard2.1/X10D.xml ./X10D.xml
cp ../X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.dll ./X10D.Unity.dll
cp ../X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.xml ./X10D.Unity.xml
- name: Check for changes
run: |
cd upm
git diff --quiet
continue-on-error: true
- name: Commit update
if: ${{ success() }}
run: |
cd upm
git config user.name github-actions
git config user.email github-actions@github.com
git add X10D.dll
git add X10D.Unity.dll
git add X10D.xml
git add X10D.Unity.xml
git add package.json
git commit -m "Update upm branch ($GITHUB_SHA)"
git push

View File

@ -17,7 +17,7 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: 8.0.x dotnet-version: 7.0.x
- name: Add GitHub NuGet source - name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json" run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
@ -32,7 +32,9 @@ jobs:
run: | run: |
mkdir build mkdir build
dotnet pack X10D --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build dotnet pack X10D --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.DSharpPlus --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.Hosting --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build dotnet pack X10D.Hosting --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.Unity --configuration Release --no-build -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
- name: Push NuGet Package to GitHub - name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
@ -51,3 +53,42 @@ jobs:
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false prerelease: false
- name: Checkout upm branch
uses: actions/checkout@v3
with:
ref: upm
path: upm
- name: Build package.json
run: |
dotnet run --project ./tools/UpmPackageGenerator/UpmPackageGenerator.csproj "./X10D/bin/Release/netstandard2.1/X10D.dll"
cp package.json upm/package.json
- name: Copy built artifacts to upm
run: |
cd upm
cp ../X10D/bin/Release/netstandard2.1/X10D.dll ./X10D.dll
cp ../X10D/bin/Release/netstandard2.1/X10D.xml ./X10D.xml
cp ../X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.dll ./X10D.Unity.dll
cp ../X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.xml ./X10D.Unity.xml
- name: Check for changes
run: |
cd upm
git diff --quiet
continue-on-error: true
- name: Commit update
if: ${{ success() }}
run: |
cd upm
git config user.name github-actions
git config user.email github-actions@github.com
git add X10D.dll
git add X10D.Unity.dll
git add X10D.xml
git add X10D.Unity.xml
git add package.json
git commit -m "Update upm branch ($GITHUB_SHA)"
git push

View File

@ -19,7 +19,7 @@ jobs:
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v3 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: 8.0.x dotnet-version: 7.0.x
- name: Add GitHub NuGet source - name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json" run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
@ -31,4 +31,4 @@ jobs:
run: dotnet build -c Debug run: dotnet build -c Debug
- name: Run Source Validation - name: Run Source Validation
run: dotnet run --project ./tools/SourceValidator/SourceValidator.csproj ./X10D/src run: dotnet run --project ./tools/SourceValidator/SourceValidator.csproj ./X10D/src ./X10D.Unity/src

50
.github/workflows/unity.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: Unity Test Runner
on:
push:
branches:
- '*'
- '*/*'
pull_request:
branches:
- '*'
- '*/*'
jobs:
build:
name: "Unity Test Runner"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release
- name: Copy artifacts to project
run: |
mkdir -p ./X10D.Unity.Tests/Assets/Libraries
cp -r ./X10D/bin/Release/netstandard2.1/X10D.dll ./X10D.Unity.Tests/Assets/Libraries/X10D.dll
cp -r ./X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.dll ./X10D.Unity.Tests/Assets/Libraries/X10D.Unity.dll
- name: Unity - Test runner
uses: game-ci/unity-test-runner@v2.1.0
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with:
projectPath: X10D.Unity.Tests
githubToken: ${{ secrets.GITHUB_TOKEN }}

View File

@ -5,63 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 4.0.0 - [Unreleased]
### Added
- X10D: Add support for generic math interfaces.
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
- X10D: Added math-related extension methods for `BigInteger`.
- X10D: Added `Queue<T>.EnqueueAll` and `Queue<T>.DequeueAll`.
- X10D: Added `Stack<T>.PushAll` and `Stack<T>.PopAll`.
- X10D: Added `Span<T>.Replace(T, T)`.
- X10D: Added `CountDigits` for integer types.
- X10D: Added `IEnumerable<T>.Except(T)`.
- X10D: Added `Progress<T>.OnProgressChanged([T])`.
- X10D: Added `TextWriter.WriteNoAlloc(int[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteNoAlloc(long[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteNoAlloc(ulong[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteLineNoAlloc(int[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteLineNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
- X10D: Added `TextWriter.WriteLineNoAlloc(long[, 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.MDBold`, `string.MDCode`, `string.MDCodeBlock([string])`, `string.MDHeading(int)`,
`string.MDItalic`, `string.MDLink`, `string.MDStrikeOut`, and `string.MDUnderline` for Markdown formatting.
- X10D: Added Span overloads which complement `char.Repeat` and `string.Repeat`.
### Fixed
- X10D: Fixed XMLDoc for `Line3D` to read "single-precision floating-point" instead of "32-bit signed integer".
### Changed
- X10D: DateTime.Age(DateTime) and DateTimeOffset.Age(DateTimeOffset) parameter renamed from asOf to referenceDate.
- X10D: Methods which accepted the `Endianness` enum as an argument have been replaced with explicit
BigEndian/LittleEndian methods.
- X10D: `Stream.GetHash<>` and `Stream.TryWriteHash<>` now throw ArgumentException in lieu of
TypeInitializationException.
- X10D: `char.IsEmoji` no longer allocates for .NET 7+.
- X10D: `string.Repeat` is now more efficient.
### Removed
- X10D: Removed `IEnumerable<T>.ConcatOne` - this functionality already exists with `Append`.
- X10D: Removed `Endianness` enum.
- X10D: Removed `Span<T>.Replace(T, T)` for .NET 8 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.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).
## [3.3.1] - 2023-08-21 ## [3.3.1] - 2023-08-21
### 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

View File

@ -5,7 +5,7 @@ or submit a pull request.
### Pull request guidelines ### Pull request guidelines
This project uses C# 12.0 language features where feasible, and adheres to StyleCop rules with some minor adjustments. This project uses C# 11.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# 12.0 features where possible - Use C# 11.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

100
README.md
View File

@ -9,115 +9,29 @@
<a href="https://github.com/oliverbooth/X10D/blob/master/LICENSE.md"><img src="https://img.shields.io/github/license/oliverbooth/X10D?style=flat-square" alt="MIT License" title="MIT License"></a> <a href="https://github.com/oliverbooth/X10D/blob/master/LICENSE.md"><img src="https://img.shields.io/github/license/oliverbooth/X10D?style=flat-square" alt="MIT License" title="MIT License"></a>
</p> </p>
## About ### About
X10D (pronounced *extend*), is a .NET package that provides extension methods for numerous types. The purpose of this library is to simplify a codebase by reducing the need for repeated code when performing common operations. Simplify your codebase. Take advantage of .NET. Use extension methods. X10D (pronounced *extend*), is a .NET package that provides extension methods for numerous types. The purpose of this library is to simplify a codebase by reducing the need for repeated code when performing common operations. Simplify your codebase. Take advantage of .NET. Use extension methods.
*(I'm also [dogfooding](https://www.pcmag.com/encyclopedia/term/dogfooding) this library, so there's that.)* *(I'm also [dogfooding](https://www.pcmag.com/encyclopedia/term/dogfooding) this library, so there's that.)*
### What are extension methods?
Extension methods are a clever .NET feature that augment existing types with new functionality. They are defined as
static methods in a static class, and are called as if they were instance methods on the type they are extending. Take,
for example, the following code:
```csharp
public static class Program
{
public static void Main()
{
string str = "Hello, world!";
Console.WriteLine(str.Reverse());
}
}
public static class StringExtensions
{
public static string Reverse(this string str)
{
char[] chars = str.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
}
```
This will print `!dlrow ,olleH` to the console. The `Reverse` method is defined in the `StringExtensions` class, yet is
called as if it were an instance method on the `str` variable, even though it's not.
### Why use extension methods?
Extension methods were introduced when LINQ was added to .NET. LINQ is a set of extension methods that provide a way to
query, filter, and transform data. If you were to access LINQ's methods statically, you would have to write code like
this:
```csharp
public static class Program
{
public static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
IEnumerable<int> evenNumbers = Enumerable.Where(numbers, x => x % 2 == 0);
IEnumerable<int> doubledNumbers = Enumerable.Select(evenNumbers, x => x * 2);
int sum = Enumerable.Sum(doubledNumbers);
Console.WriteLine(sum);
}
}
```
And if you wanted to one-line this, you'd have to write this:
```csharp
public static class Program
{
public static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(Enumerable.Sum(Enumerable.Select(Enumerable.Where(numbers, x => x % 2 == 0), x => x * 2)));
}
}
```
This is a lot of code to write, and it's not very readable. The nested method calls make it incredibly difficult to
follow. However, because LINQ is implemented as extension methods, you can write the following code instead:
```csharp
public static class Program
{
public static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers.Where(x => x % 2 == 0).Select(x => x * 2).Sum());
}
}
```
Because the methods are called as if they were instance methods on `IEnumerable<T>`, they can be chained together,
making the code much more readable.
X10D aims to provide these same benefits as LINQ, but for dozens of other types and for countless other use cases. See
the [documentation](#documentation) for a complete breakdown of what's available.
## Installation ## Installation
### NuGet installation ### NuGet installation
```ps ```ps
Install-Package X10D -Version 4.0.0 Install-Package X10D -Version 3.3.1
``` ```
### Manual installation ### Manual installation
Download the [latest release](https://github.com/oliverbooth/X10D/releases/latest) from this repository and adding a direct assembly reference for your chosen platform. Download the [latest release](https://github.com/oliverbooth/X10D/releases/latest) from this repository and adding a direct assembly reference for your chosen platform.
## Documentation ### Unity installation
For the Unity installation guide, refer to the [README.md in X10D.Unity](X10D.Unity/README.md).
Documentation and the API reference is available at https://oliverbooth.github.io/X10D/index.html. *I'm sorry this took ## Features
so long to get up and running. DocFX will be the death of me.* I'm planning on writing complete and extensive documentation in the near future. As of this time, feel free to browse the source or the API using your favourite IDE.
For those familiar with the 2.6.0 API, please read [CHANGELOG.md](CHANGELOG.md) for a complete list of changes. **3.0.0 is a major release and introduces many breaking changes.**
## Contributing ## Contributing
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
## License ## License
X10D is released under the MIT License. See [here](https://github.com/oliverbooth/X10D/blob/main/LICENSE.md) for more details. X10D is released under the MIT License. See [here](https://github.com/oliverbooth/X10D/blob/main/LICENSE.md) for more details.

View File

@ -1,16 +1,11 @@
<Project> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<LangVersion>12.0</LangVersion> <TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
<LangVersion>11.0</LangVersion>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<ImplicitUsings>true</ImplicitUsings> <ImplicitUsings>true</ImplicitUsings>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<VersionPrefix>4.0.0</VersionPrefix>
<Authors>Oliver Booth</Authors> <Authors>Oliver Booth</Authors>
<Nullable>enable</Nullable>
<NeutralLanguage>en</NeutralLanguage> <NeutralLanguage>en</NeutralLanguage>
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl> <RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
@ -19,9 +14,16 @@
<PackageIcon>branding_Icon.png</PackageIcon> <PackageIcon>branding_Icon.png</PackageIcon>
<PackageIconUrl/> <PackageIconUrl/>
<PackageTags>dotnet extension-methods</PackageTags> <PackageTags>dotnet extension-methods</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../CHANGELOG.md"))</PackageReleaseNotes>
<PackageReleaseNotes>See CHANGELOG.md for a full list of changes.</PackageReleaseNotes>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors> <CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<VersionPrefix>3.3.1</VersionPrefix>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ExcludeFromCodeCoverage>true</ExcludeFromCodeCoverage>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'"> <PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
@ -46,6 +48,10 @@
<FileVersion>$(VersionPrefix).0</FileVersion> <FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="DSharpPlus" Version="4.3.0" PrivateAssets="All"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\branding_Icon.png"> <None Include="..\branding_Icon.png">
<Pack>True</Pack> <Pack>True</Pack>
@ -55,13 +61,10 @@
<Pack>True</Pack> <Pack>True</Pack>
<PackagePath/> <PackagePath/>
</None> </None>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\CHANGELOG.md"> <None Include="..\CHANGELOG.md">
<Pack>True</Pack> <Pack>True</Pack>
<PackagePath/> <PackagePath/>
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1 @@
[assembly: CLSCompliant(false)]

View File

@ -0,0 +1,80 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordChannel" />.
/// </summary>
public static class DiscordChannelExtensions
{
/// <summary>
/// Gets the category of this channel.
/// </summary>
/// <param name="channel">The channel whose category to retrieve.</param>
/// <returns>
/// The category of <paramref name="channel" />, or <paramref name="channel" /> itself if it is already a category;
/// <see langword="null" /> if this channel is not defined in a category.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="channel" /> is <see langword="null" />.</exception>
public static DiscordChannel? GetCategory(this DiscordChannel channel)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(channel);
#else
if (channel is null)
{
throw new ArgumentNullException(nameof(channel));
}
#endif
while (true)
{
if (channel.IsCategory)
{
return channel;
}
if (channel.Parent is not { } parent)
{
return null;
}
channel = parent;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordChannel" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="channel">The <see cref="DiscordChannel" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordChannel" /> whose public values will match <paramref name="channel" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="channel" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordChannel> NormalizeClientAsync(this DiscordChannel channel, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(channel);
ArgumentNullException.ThrowIfNull(client);
#else
if (channel is null)
{
throw new ArgumentNullException(nameof(channel));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetChannelAsync(channel.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,79 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordClient" />.
/// </summary>
public static class DiscordClientExtensions
{
/// <summary>
/// Instructs the client to automatically join all existing threads, and any newly-created threads.
/// </summary>
/// <param name="client">The <see cref="DiscordClient" /> whose events should be subscribed.</param>
/// <param name="rejoinIfRemoved">
/// <see langword="true" /> to automatically rejoin a thread if this client was removed; otherwise,
/// <see langword="false" />.
/// </param>
/// <exception cref="ArgumentNullException"><paramref name="client" /> is <see langword="null" />.</exception>
public static void AutoJoinThreads(this DiscordClient client, bool rejoinIfRemoved = true)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(client);
#else
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
client.GuildAvailable += (_, args) => args.Guild.JoinAllThreadsAsync();
client.ThreadCreated += (_, args) => args.Thread.JoinThreadAsync();
if (rejoinIfRemoved)
{
client.ThreadMembersUpdated += (_, args) =>
{
if (args.RemovedMembers.Any(m => m.Id == client.CurrentUser.Id))
return args.Thread.JoinThreadAsync();
return Task.CompletedTask;
};
}
}
/// <summary>
/// Gets a user by their ID. If the user is not found, <see langword="null" /> is returned instead of
/// <see cref="NotFoundException" /> being thrown.
/// </summary>
/// <param name="client">The Discord client.</param>
/// <param name="userId">The ID of the user to retrieve.</param>
/// <exception cref="ArgumentNullException"><paramref name="client" /> is <see langword="null" />.</exception>
public static async Task<DiscordUser?> GetUserOrNullAsync(this DiscordClient client, ulong userId)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(client);
#else
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
try
{
// we should never use exceptions for flow control but this is D#+ we're talking about.
// NotFoundException isn't even documented, and yet it gets thrown when a user doesn't exist.
// so this method should hopefully clearly express that - and at least using exceptions for flow control *here*,
// removes the need to do the same in consumer code.
// god I hate this.
return await client.GetUserAsync(userId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
}

View File

@ -0,0 +1,239 @@
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordEmbedBuilder" />.
/// </summary>
public static class DiscordEmbedBuilderExtensions
{
/// <summary>
/// Adds a field of any value type to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder" /> is <see langword="null" />.</exception>
public static DiscordEmbedBuilder AddField<T>(
this DiscordEmbedBuilder builder,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
#endif
return builder.AddField(name, value?.ToString(), inline);
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder" /> is <see langword="null" />.</exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
bool condition,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
#endif
if (condition)
{
builder.AddField(name, value?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
Func<bool> predicate,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(predicate);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (predicate is null)
{
throw new ArgumentNullException(nameof(predicate));
}
#endif
if (predicate.Invoke())
{
builder.AddField(name, value?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
Func<bool> predicate,
string name,
Func<T?> valueFactory,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(predicate);
ArgumentNullException.ThrowIfNull(valueFactory);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (predicate is null)
{
throw new ArgumentNullException(nameof(predicate));
}
if (valueFactory is null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
#endif
if (predicate.Invoke())
{
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
bool condition,
string name,
Func<T?> valueFactory,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(valueFactory);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (valueFactory is null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
#endif
if (condition)
{
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Sets the embed's author.
/// </summary>
/// <param name="builder">The embed builder to modify.</param>
/// <param name="user">The author.</param>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />.</returns>
public static DiscordEmbedBuilder WithAuthor(this DiscordEmbedBuilder builder, DiscordUser user)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(user);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
#endif
return builder.WithAuthor(user.GetUsernameWithDiscriminator(), iconUrl: user.AvatarUrl);
}
}

View File

@ -0,0 +1,97 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordGuild" />.
/// </summary>
public static class DiscordGuildExtensions
{
/// <summary>
/// Joins all active threads in the guild that this client has permission to view.
/// </summary>
/// <param name="guild">The guild whose active threads to join.</param>
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
public static async Task JoinAllThreadsAsync(this DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
await Task.WhenAll(guild.Threads.Values.Select(t => t.JoinThreadAsync())).ConfigureAwait(false);
}
/// <summary>
/// Gets a guild member by their ID. If the member is not found, <see langword="null" /> is returned instead of
/// <see cref="NotFoundException" /> being thrown.
/// </summary>
/// <param name="guild">The guild whose member list to search.</param>
/// <param name="userId">The ID of the member to retrieve.</param>
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
public static async Task<DiscordMember?> GetMemberOrNullAsync(this DiscordGuild guild, ulong userId)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
try
{
// we should never use exceptions for flow control but this is D#+ we're talking about.
// NotFoundException isn't even documented, and yet it gets thrown when a member doesn't exist.
// so this method should hopefully clearly express that - and at least using exceptions for flow control *here*,
// removes the need to do the same in consumer code.
// god I hate this.
return await guild.GetMemberAsync(userId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordGuild" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="guild">The <see cref="DiscordGuild" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordGuild" /> whose public values will match <paramref name="guild" />, but whose internal client is
/// <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="guild" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordGuild> NormalizeClientAsync(this DiscordGuild guild, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
ArgumentNullException.ThrowIfNull(client);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetGuildAsync(guild.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,73 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordMember" />.
/// </summary>
public static class DiscordMemberExtensions
{
/// <summary>
/// Returns a value indicating whether this member has the specified role.
/// </summary>
/// <param name="member">The member whose roles to search.</param>
/// <param name="role">The role for which to check.</param>
/// <returns>
/// <see langword="true" /> if <paramref name="member" /> has the role; otherwise, <see langword="false" />.
/// </returns>
public static bool HasRole(this DiscordMember member, DiscordRole role)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(member);
ArgumentNullException.ThrowIfNull(role);
#else
if (member is null)
{
throw new ArgumentNullException(nameof(member));
}
if (role is null)
{
throw new ArgumentNullException(nameof(role));
}
#endif
return member.Roles.Contains(role);
}
/// <summary>
/// Normalizes a <see cref="DiscordMember" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="member">The <see cref="DiscordMember" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordMember" /> whose public values will match <paramref name="member" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="member" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordMember> NormalizeClientAsync(this DiscordMember member, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(member);
ArgumentNullException.ThrowIfNull(client);
#else
if (member is null)
{
throw new ArgumentNullException(nameof(member));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
DiscordGuild guild = await member.Guild.NormalizeClientAsync(client).ConfigureAwait(false);
return await guild.GetMemberAsync(member.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,89 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordMessage" />.
/// </summary>
public static class DiscordMessageExtensions
{
/// <summary>
/// Deletes this message after a specified delay.
/// </summary>
/// <param name="message">The message to delete.</param>
/// <param name="delay">The delay before deletion.</param>
/// <param name="reason">The reason for the deletion.</param>
/// <exception cref="ArgumentNullException"><paramref name="message" /> is <see langword="null" />.</exception>
public static async Task DeleteAfterAsync(this DiscordMessage message, TimeSpan delay, string? reason = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(message);
#else
if (message is null)
{
throw new ArgumentNullException(nameof(message));
}
#endif
await Task.Delay(delay).ConfigureAwait(false);
await message.DeleteAsync(reason).ConfigureAwait(false);
}
/// <summary>
/// Deletes the message as created by this task after a specified delay.
/// </summary>
/// <param name="task">The task whose <see cref="DiscordMessage" /> result should be deleted.</param>
/// <param name="delay">The delay before deletion.</param>
/// <param name="reason">The reason for the deletion.</param>
/// <exception cref="ArgumentNullException"><paramref name="task" /> is <see langword="null" />.</exception>
public static async Task DeleteAfterAsync(this Task<DiscordMessage> task, TimeSpan delay, string? reason = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(task);
#else
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}
#endif
DiscordMessage message = await task.ConfigureAwait(false);
await message.DeleteAfterAsync(delay, reason).ConfigureAwait(false);
}
/// <summary>
/// Normalizes a <see cref="DiscordMessage" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="message">The <see cref="DiscordMessage" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordMessage" /> whose public values will match <paramref name="message" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="message" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordMessage> NormalizeClientAsync(this DiscordMessage message, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(message);
ArgumentNullException.ThrowIfNull(client);
#else
if (message is null)
{
throw new ArgumentNullException(nameof(message));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
DiscordChannel channel = await message.Channel.NormalizeClientAsync(client).ConfigureAwait(false);
return await channel.GetMessageAsync(message.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,164 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordUser" />.
/// </summary>
public static class DiscordUserExtensions
{
/// <summary>
/// Returns the current <see cref="DiscordUser" /> as a member of the specified guild.
/// </summary>
/// <param name="user">The user to transform.</param>
/// <param name="guild">The guild whose member list to search.</param>
/// <returns>
/// A <see cref="DiscordMember" /> whose <see cref="DiscordMember.Guild" /> is equal to <paramref name="guild" />, or
/// <see langword="null" /> if this user is not in the specified <paramref name="guild" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="user" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="guild" /> is <see langword="null" />.</para>
/// </exception>
public static async Task<DiscordMember?> GetAsMemberOfAsync(this DiscordUser user, DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(guild);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
if (user is DiscordMember member && member.Guild == guild)
{
return member;
}
if (guild.Members.TryGetValue(user.Id, out member!))
{
return member;
}
try
{
return await guild.GetMemberAsync(user.Id).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
/// <summary>
/// Returns the user's username with the discriminator, in the format <c>username#discriminator</c>.
/// </summary>
/// <param name="user">The user whose username and discriminator to retrieve.</param>
/// <returns>A string in the format <c>username#discriminator</c></returns>
/// <exception cref="ArgumentNullException"><paramref name="user" /> is <see langword="null" />.</exception>
public static string GetUsernameWithDiscriminator(this DiscordUser user)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
#endif
if (user.Discriminator == "0")
{
// user has a new username. see: https://discord.com/blog/usernames
return user.Username;
}
return $"{user.Username}#{user.Discriminator}";
}
/// <summary>
/// Returns a value indicating whether the current user is in the specified guild.
/// </summary>
/// <param name="user">The user to check.</param>
/// <param name="guild">The guild whose member list to search.</param>
/// <returns>
/// <see langword="true" /> if <paramref name="user" /> is a member of <paramref name="guild" />; otherwise,
/// <see langword="false" />.
/// </returns>
public static async Task<bool> IsInGuildAsync(this DiscordUser user, DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(guild);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
if (guild.Members.TryGetValue(user.Id, out _))
{
return true;
}
try
{
DiscordMember? member = await guild.GetMemberAsync(user.Id).ConfigureAwait(false);
return member is not null;
}
catch (NotFoundException)
{
return false;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordUser" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="user">The <see cref="DiscordUser" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordUser" /> whose public values will match <paramref name="user" />, but whose internal client is
/// <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="user" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordUser> NormalizeClientAsync(this DiscordUser user, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(client);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetUserAsync(user.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,329 @@
using System.Globalization;
namespace X10D.DSharpPlus;
/// <summary>
/// Provides methods for encoding and decoding Discord mention strings.
/// </summary>
/// <remarks>
/// The implementations in this class are designed to resemble <c>MentionUtils</c> as provided by Discord.NET. The source is
/// available
/// <a href="https://github.com/discord-net/Discord.Net/blob/dev/src/Discord.Net.Core/Utils/MentionUtils.cs">
/// here
/// </a>.
/// </remarks>
public static class MentionUtility
{
/// <summary>
/// Returns a channel mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the channel to mention.</param>
/// <returns>A channel mention string in the format <c>&lt;#123&gt;</c>.</returns>
public static string MentionChannel(decimal id)
{
return $"<#{id:N0}>";
}
/// <summary>
/// Returns a channel mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the channel to mention.</param>
/// <returns>A channel mention string in the format <c>&lt;#123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionChannel(ulong id)
{
return $"<#{id}>";
}
/// <summary>
/// Returns a role mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the role to mention.</param>
/// <returns>A role mention string in the format <c>&lt;@&amp;123&gt;</c>.</returns>
public static string MentionRole(decimal id)
{
return $"<@&{id:N0}>";
}
/// <summary>
/// Returns a role mention string built from the specified role ID.
/// </summary>
/// <param name="id">The ID of the role to mention.</param>
/// <returns>A role mention string in the format <c>&lt;@&amp;123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionRole(ulong id)
{
return $"<@&{id}>";
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <returns>A user mention string in the format <c>&lt;@123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionUser(decimal id)
{
return MentionUser(id, false);
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <param name="nickname">
/// <see langword="true" /> if the mention string should account for nicknames; otherwise, <see langword="false" />.
/// </param>
/// <returns>
/// A user mention string in the format <c>&lt;@!123&gt;</c> if <paramref name="nickname" /> is <see langword="true" />,
/// or in the format <c>&lt;@123&gt;</c> if <paramref name="nickname" /> is <see langword="false" />.
/// </returns>
[CLSCompliant(false)]
public static string MentionUser(decimal id, bool nickname)
{
return nickname ? $"<@!{id:N0}>" : $"<@{id:N0}>";
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <returns>A user mention string in the format <c>&lt;@123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionUser(ulong id)
{
return MentionUser(id, false);
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <param name="nickname">
/// <see langword="true" /> if the mention string should account for nicknames; otherwise, <see langword="false" />.
/// </param>
/// <returns>
/// A user mention string in the format <c>&lt;@!123&gt;</c> if <paramref name="nickname" /> is <see langword="true" />,
/// or in the format <c>&lt;@123&gt;</c> if <paramref name="nickname" /> is <see langword="false" />.
/// </returns>
[CLSCompliant(false)]
public static string MentionUser(ulong id, bool nickname)
{
return nickname ? $"<@!{id}>" : $"<@{id}>";
}
/// <summary>
/// Parses a provided channel mention string to a decimal value representing the channel ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;#123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the channel ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseChannel(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '#' || value[^1] != '>')
{
return false;
}
value = value.Substring(2, value.Length - 3); // <#123>
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided channel mention string to a 64-bit unsigned integer representing the channel ID. A return value
/// indicates whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;#123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the channel ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseChannel(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '#' || value[^1] != '>')
{
return false;
}
value = value.Substring(2, value.Length - 3); // <#123>
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
/// <summary>
/// Parses a provided role mention string to a decimal value representing the role ID. A return value indicates whether
/// the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;@&amp;123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the role ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseRole(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 4 || value[0] != '<' || value[1] != '@' || value[2] != '&' || value[^1] != '>')
{
return false;
}
value = value.Substring(3, value.Length - 4); // <@&123>
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided role mention string to a 64-bit unsigned integer representing the role ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;@&amp;123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the role ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseRole(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 4 || value[0] != '<' || value[1] != '@' || value[2] != '&' || value[^1] != '>')
{
return false;
}
value = value.Substring(3, value.Length - 4); // <@&123>
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
/// <summary>
/// Parses a provided user mention string to a decimal value representing the user ID. A return value indicates whether
/// the parse succeeded.
/// </summary>
/// <param name="value">
/// A string containing a mention string to parse, in the format <c>&lt;@123&gt;</c> or <c>&lt;@!123&gt;</c>.
/// </param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the user ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseUser(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '@' || value[^1] != '>')
{
return false;
}
if (value.Length >= 4 && value[2] == '!')
{
value = value.Substring(3, value.Length - 4); // <@!123>
}
else
{
value = value.Substring(2, value.Length - 3); // <@123>
}
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided user mention string to a 64-bit unsigned integer representing the user ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">
/// A string containing a mention string to parse, in the format <c>&lt;@123&gt;</c> or <c>&lt;@!123&gt;</c>.
/// </param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the user ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseUser(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '@' || value[^1] != '>')
{
return false;
}
if (value.Length >= 4 && value[2] == '!')
{
value = value.Substring(3, value.Length - 4); // <@!123>
}
else
{
value = value.Substring(2, value.Length - 3); // <@123>
}
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
}

View File

@ -1,11 +1,69 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks> <TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
<LangVersion>11.0</LangVersion>
<Optimize>true</Optimize>
<ImplicitUsings>true</ImplicitUsings>
<Authors>Oliver Booth</Authors>
<NeutralLanguage>en</NeutralLanguage>
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Extension methods on crack.</Description>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageIcon>branding_Icon.png</PackageIcon>
<PackageIconUrl/>
<PackageTags>dotnet extension-methods</PackageTags>
<PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../CHANGELOG.md"))</PackageReleaseNotes>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<VersionPrefix>3.3.1</VersionPrefix>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' == ''">
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">
<Version>$(VersionPrefix)-$(VersionSuffix).$(BuildNumber)</Version>
<AssemblyVersion>$(VersionPrefix).$(BuildNumber)</AssemblyVersion>
<FileVersion>$(VersionPrefix).$(BuildNumber)</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' == ''">
<Version>$(VersionPrefix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0"/> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\branding_Icon.png">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\CHANGELOG.md">
<Pack>True</Pack>
<PackagePath/>
</None>
</ItemGroup>
</Project> </Project>

View File

@ -1 +1 @@
[assembly: CLSCompliant(true)] [assembly: CLSCompliant(true)]

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
namespace X10D.Hosting.DependencyInjection; namespace X10D.Hosting.DependencyInjection;

View File

@ -1,4 +1,4 @@
2 2
3 3
5 5
7 7

View File

@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks> <TargetFrameworks>net7.0;net6.0;netcoreapp3.1</TargetFrameworks>
<LangVersion>11.0</LangVersion>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject> <Nullable>enable</Nullable>
<CoverletOutputFormat>xml,cobertura</CoverletOutputFormat> <ImplicitUsings>true</ImplicitUsings>
<CoverletOutputFormat>json,cobertura</CoverletOutputFormat>
<CollectCoverage>true</CollectCoverage> <CollectCoverage>true</CollectCoverage>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
@ -14,14 +15,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0"/>
<PackageReference Include="NSubstitute" Version="5.1.0"/> <PackageReference Include="NSubstitute" Version="5.0.0"/>
<PackageReference Include="NUnit" Version="3.14.0"/> <PackageReference Include="NUnit" Version="3.13.3"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/> <PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/> <PackageReference Include="coverlet.collector" Version="3.2.0"/>
<PackageReference Include="System.Reactive" Version="6.0.0"/> <PackageReference Include="System.Reactive" Version="5.0.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1 +1 @@
[assembly: CLSCompliant(false)] [assembly: CLSCompliant(true)]

View File

@ -1,12 +1,12 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal static partial class ArrayTests public partial class ArrayTests
{ {
[TestFixture] [TestFixture]
internal class AsReadOnlyTests public class AsReadOnlyTests
{ {
[Test] [Test]
public void AsReadOnly_ShouldReturnReadOnlyCollection_WhenArrayIsNotNull() public void AsReadOnly_ShouldReturnReadOnlyCollection_WhenArrayIsNotNull()

View File

@ -1,9 +1,9 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal static partial class ArrayTests public partial class ArrayTests
{ {
[TestFixture] [TestFixture]
public class ClearTests public class ClearTests

View File

@ -1,8 +1,8 @@
using NUnit.Framework; using NUnit.Framework;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal static partial class ArrayTests public partial class ArrayTests
{ {
} }

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class BoolListTests public class BoolListTests
{ {
[Test] [Test]
public void PackByte_Should_Pack_Correctly() public void PackByte_Should_Pack_Correctly()

View File

@ -1,11 +1,11 @@
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class ByteTests public class ByteTests
{ {
[Test] [Test]
public void Unpack_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
@ -47,6 +47,7 @@ internal class ByteTests
}); });
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void UnpackInternal_Fallback_ShouldUnpackToSpanCorrectly() public void UnpackInternal_Fallback_ShouldUnpackToSpanCorrectly()
{ {
@ -91,6 +92,7 @@ internal class ByteTests
Assert.That(bits[7], Is.True); Assert.That(bits[7], Is.True);
}); });
} }
#endif
[Test] [Test]
public void Unpack_ShouldRepackEqually() public void Unpack_ShouldRepackEqually()

View File

@ -1,11 +1,11 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal partial class CollectionTests public partial class CollectionTests
{ {
[TestFixture] [TestFixture]
public class ClearAndDisposeAllTests public class ClearAndDisposeAllTests

View File

@ -1,11 +1,11 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal partial class CollectionTests public partial class CollectionTests
{ {
[TestFixture] [TestFixture]
public class ClearAndDisposeAllAsyncTests public class ClearAndDisposeAllAsyncTests

View File

@ -1,8 +1,8 @@
using NUnit.Framework; using NUnit.Framework;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal partial class CollectionTests public partial class CollectionTests
{ {
} }

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class DictionaryTests public class DictionaryTests
{ {
[Test] [Test]
public void AddOrUpdate_ShouldAddNewKey_IfNotExists_GivenConcreteDictionary() public void AddOrUpdate_ShouldAddNewKey_IfNotExists_GivenConcreteDictionary()

View File

@ -1,10 +1,10 @@
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal partial class EnumerableTests public partial class EnumerableTests
{ {
[TestFixture] [TestFixture]
public class DisposeAllTests public class DisposeAllTests

View File

@ -1,10 +1,10 @@
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
internal partial class EnumerableTests public partial class EnumerableTests
{ {
[TestFixture] [TestFixture]
public class DisposeAllAsyncTests public class DisposeAllAsyncTests

View File

@ -1,11 +1,11 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal partial class EnumerableTests public partial class EnumerableTests
{ {
[Test] [Test]
public void CountWhereNot_ShouldReturnCorrectCount_GivenSequence() public void CountWhereNot_ShouldReturnCorrectCount_GivenSequence()

View File

@ -1,11 +1,11 @@
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class Int16Tests public class Int16Tests
{ {
[Test] [Test]
public void Unpack_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
@ -82,6 +82,7 @@ internal class Int16Tests
}); });
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void UnpackInternal_Ssse3_ShouldUnpackToSpanCorrectly() public void UnpackInternal_Ssse3_ShouldUnpackToSpanCorrectly()
{ {
@ -112,6 +113,7 @@ internal class Int16Tests
} }
}); });
} }
#endif
[Test] [Test]
public void Unpack_ShouldRepackEqually() public void Unpack_ShouldRepackEqually()

View File

@ -1,11 +1,11 @@
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class Int32Tests public class Int32Tests
{ {
[Test] [Test]
public void Unpack_ShouldUnpackToArrayCorrectly() public void Unpack_ShouldUnpackToArrayCorrectly()
@ -83,6 +83,7 @@ internal class Int32Tests
}); });
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void UnpackInternal_Ssse3_ShouldUnpackToSpanCorrectly() public void UnpackInternal_Ssse3_ShouldUnpackToSpanCorrectly()
{ {
@ -142,6 +143,7 @@ internal class Int32Tests
} }
}); });
} }
#endif
[Test] [Test]
public void Unpack_ShouldRepackEqually() public void Unpack_ShouldRepackEqually()

View File

@ -1,12 +1,11 @@
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class Int64Tests public class Int64Tests
{ {
[Test] [Test]
public void UnpackBits_ShouldUnpackToArrayCorrectly() public void UnpackBits_ShouldUnpackToArrayCorrectly()
@ -30,7 +29,7 @@ internal class Int64Tests
for (var index = 8; index < 64; index++) for (var index = 8; index < 64; index++)
{ {
Assert.That(bits[index], Is.False, index.ToString(CultureInfo.InvariantCulture)); Assert.That(bits[index], Is.False, index.ToString());
} }
}); });
} }
@ -54,7 +53,7 @@ internal class Int64Tests
for (var index = 8; index < 64; index++) for (var index = 8; index < 64; index++)
{ {
Assert.That(bits[index], Is.False, index.ToString(CultureInfo.InvariantCulture)); Assert.That(bits[index], Is.False, index.ToString());
} }
}); });
} }

View File

@ -1,11 +1,12 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class ListTests public class ListTests
{ {
[CLSCompliant(false)]
[Test] [Test]
[TestCase(1)] [TestCase(1)]
[TestCase(1, 2, 3)] [TestCase(1, 2, 3)]
@ -25,6 +26,7 @@ internal class ListTests
CollectionAssert.AreEqual(all42, list); CollectionAssert.AreEqual(all42, list);
} }
[CLSCompliant(false)]
[Test] [Test]
[TestCase(1)] [TestCase(1)]
[TestCase(1, 2, 3)] [TestCase(1, 2, 3)]
@ -175,9 +177,9 @@ internal class ListTests
} }
[Test] [Test]
public void RemoveRange_ShouldThrowArgumentOutOfRangeException_GivenEndIndexLessThanStart() public void RemoveRange_ShouldThrowArgumentException_GivenEndIndexLessThanStart()
{ {
Assert.Throws<ArgumentOutOfRangeException>(() => new List<int>().RemoveRange(2..0)); Assert.Throws<ArgumentException>(() => new List<int>().RemoveRange(2..0));
} }
[Test] [Test]

View File

@ -1,68 +0,0 @@
using NUnit.Framework;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestFixture]
internal class QueueTests
{
[Test]
public void EnqueueAll_ShouldThrowArgumentNullException_GivenNullQueue()
{
Queue<int> queue = null!;
Assert.Throws<ArgumentNullException>(() => queue.EnqueueAll([]));
}
[Test]
public void EnqueueAll_ShouldThrowArgumentNullException_GivenNullElements()
{
var queue = new Queue<int>();
Assert.Throws<ArgumentNullException>(() => queue.EnqueueAll(null!));
}
[Test]
public void DequeueAll_ShouldThrowArgumentNullException_GivenNullQueue()
{
Queue<int> queue = null!;
Assert.Throws<ArgumentNullException>(() => _ = queue.DequeueAll().ToArray());
}
[Test]
public void EnqueueAll_ShouldAddElementsToQueue_GivenValidEnumerable()
{
var queue = new Queue<int>();
int[] elements = [1, 2, 3, 4, 5];
Assert.That(queue, Is.Empty);
queue.EnqueueAll(elements);
Assert.That(queue, Is.Not.Empty);
Assert.That(queue, Has.Count.EqualTo(5));
var index = 0;
foreach (int i in queue)
{
Assert.That(i, Is.EqualTo(elements[index]));
index++;
}
}
[Test]
public void DequeueAll_ShouldRemoveElementsFromQueue()
{
var queue = new Queue<int>([1, 2, 3, 4, 5]);
Assert.That(queue, Is.Not.Empty);
Assert.That(queue, Has.Count.EqualTo(5));
var index = 1;
foreach (int i in queue.DequeueAll())
{
Assert.That(i, Is.EqualTo(index));
index++;
}
Assert.That(queue, Is.Empty);
}
}

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
namespace X10D.Tests.Collections; namespace X10D.Tests.Collections;
[TestFixture] [TestFixture]
internal class SpanTest public class SpanTest
{ {
[Test] [Test]
public void Count_ShouldReturn0_GivenEmptySpan() public void Count_ShouldReturn0_GivenEmptySpan()

View File

@ -1,68 +0,0 @@
using NUnit.Framework;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestFixture]
internal class StackTests
{
[Test]
public void PushAll_ShouldThrowArgumentNullException_GivenNullStack()
{
Stack<int> stack = null!;
Assert.Throws<ArgumentNullException>(() => stack.PushAll([]));
}
[Test]
public void PushAll_ShouldThrowArgumentNullException_GivenNullElements()
{
var stack = new Stack<int>();
Assert.Throws<ArgumentNullException>(() => stack.PushAll(null!));
}
[Test]
public void PopAll_ShouldThrowArgumentNullException_GivenNullStack()
{
Stack<int> stack = null!;
Assert.Throws<ArgumentNullException>(() => _ = stack.PopAll().ToArray());
}
[Test]
public void PushAll_ShouldAddElementsToStack_GivenValidEnumerable()
{
var stack = new Stack<int>();
int[] elements = [1, 2, 3, 4, 5];
Assert.That(stack, Is.Empty);
stack.PushAll(elements);
Assert.That(stack, Is.Not.Empty);
Assert.That(stack, Has.Count.EqualTo(5));
var index = 4;
foreach (int i in stack)
{
Assert.That(i, Is.EqualTo(elements[index]));
index--;
}
}
[Test]
public void PopAll_ShouldRemoveElementsFromStack()
{
var stack = new Stack<int>([1, 2, 3, 4, 5]);
Assert.That(stack, Is.Not.Empty);
Assert.That(stack, Has.Count.EqualTo(5));
var index = 5;
foreach (int i in stack.PopAll())
{
Assert.That(i, Is.EqualTo(index));
index--;
}
Assert.That(stack, Is.Empty);
}
}

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class CoreTests public class CoreTests
{ {
[Test] [Test]
[TestCase(1)] [TestCase(1)]

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class EnumTests public class EnumTests
{ {
// Microsoft wrongfully decided to have Sunday be 0, Monday be 1, etc. // Microsoft wrongfully decided to have Sunday be 0, Monday be 1, etc.
// I personally hate this, Sunday is not the first day of the week. // I personally hate this, Sunday is not the first day of the week.

View File

@ -1,3 +1,4 @@
#if NET6_0_OR_GREATER
using System.Runtime.Intrinsics; using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
using NUnit.Framework; using NUnit.Framework;
@ -6,7 +7,7 @@ using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class IntrinsicTests public class IntrinsicTests
{ {
[Test] [Test]
public void CorrectBoolean_ShouldReturnExpectedVector64Result_GivenInputVector() public void CorrectBoolean_ShouldReturnExpectedVector64Result_GivenInputVector()
@ -222,3 +223,4 @@ internal class IntrinsicTests
Assert.That(result, Is.EqualTo(expectedResult)); Assert.That(result, Is.EqualTo(expectedResult));
} }
} }
#endif

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class NullableTests public class NullableTests
{ {
[Test] [Test]
public void TryGetValue_ShouldBeTrue_GivenValue() public void TryGetValue_ShouldBeTrue_GivenValue()

View File

@ -1,11 +1,11 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Collections; using X10D.Collections;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class RandomTests public class RandomTests
{ {
[Test] [Test]
public void NextBoolean_ShouldBeFalse_GivenSeed1234() public void NextBoolean_ShouldBeFalse_GivenSeed1234()

View File

@ -1,66 +0,0 @@
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--;
}
}
}

View File

@ -1,12 +1,14 @@
#if NET5_0_OR_GREATER
using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
#endif
using NUnit.Framework; using NUnit.Framework;
using X10D.Core; using X10D.Core;
namespace X10D.Tests.Core; namespace X10D.Tests.Core;
[TestFixture] [TestFixture]
internal class SpanTest public class SpanTest
{ {
[Test] [Test]
public void Contains_ShouldReturnFalse_GivenReadOnlySpanWithNoMatchingElements_UsingByteEnum() public void Contains_ShouldReturnFalse_GivenReadOnlySpanWithNoMatchingElements_UsingByteEnum()
@ -207,6 +209,7 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void PackByteInternal_Sse2_ShouldReturnCorrectByte_GivenReadOnlySpan_Using() public void PackByteInternal_Sse2_ShouldReturnCorrectByte_GivenReadOnlySpan_Using()
{ {
@ -223,6 +226,23 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test]
public void PackByteInternal_AdvSimd_ShouldReturnCorrectByte_GivenReadOnlySpan_Using()
{
if (!AdvSimd.IsSupported)
{
return;
}
const byte expected = 0b00110011;
ReadOnlySpan<bool> span = stackalloc bool[8] {true, true, false, false, true, true, false, false};
byte actual = span.PackByteInternal_AdvSimd();
Assert.That(actual, Is.EqualTo(expected));
}
#endif
[Test] [Test]
public void PackInt16_ShouldReturnSameAsPackByte_WhenSpanHasLength8() public void PackInt16_ShouldReturnSameAsPackByte_WhenSpanHasLength8()
{ {
@ -248,6 +268,7 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void PackInt16Internal_Sse2_ShouldReturnCorrectInt16_GivenReadOnlySpan_Using() public void PackInt16Internal_Sse2_ShouldReturnCorrectInt16_GivenReadOnlySpan_Using()
{ {
@ -266,6 +287,7 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
#endif
[Test] [Test]
public void PackInt32Internal_Fallback_ShouldReturnCorrectInt32_GivenReadOnlySpan() public void PackInt32Internal_Fallback_ShouldReturnCorrectInt32_GivenReadOnlySpan()
@ -282,6 +304,7 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
#if NET5_0_OR_GREATER
[Test] [Test]
public void PackInt32Internal_Sse2_ShouldReturnCorrectInt32_GivenReadOnlySpan() public void PackInt32Internal_Sse2_ShouldReturnCorrectInt32_GivenReadOnlySpan()
{ {
@ -322,6 +345,27 @@ internal class SpanTest
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test]
public void PackInt32Internal_AdvSimd_ShouldReturnCorrectInt32_GivenReadOnlySpan()
{
if (!AdvSimd.IsSupported)
{
return;
}
const int expected = 0b01010101_10101010_01010101_10101010;
ReadOnlySpan<bool> span = stackalloc bool[32]
{
false, true, false, true, false, true, false, true, true, false, true, false, true, false, true, false, false,
true, false, true, false, true, false, true, true, false, true, false, true, false, true, false,
};
int actual = span.PackInt32Internal_AdvSimd();
Assert.That(actual, Is.EqualTo(expected));
}
#endif
[Test] [Test]
public void PackInt32_ShouldReturnSameAsPackByte_WhenSpanHasLength8_UsingReadOnlySpan() public void PackInt32_ShouldReturnSameAsPackByte_WhenSpanHasLength8_UsingReadOnlySpan()
{ {

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class CircleFTests public class CircleFTests
{ {
[Test] [Test]
public void Area_ShouldBePiRadiusRadius_GivenUnitCircle() public void Area_ShouldBePiRadiusRadius_GivenUnitCircle()

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class CircleTests public class CircleTests
{ {
[Test] [Test]
public void Area_ShouldBePiRadiusRadius_GivenUnitCircle() public void Area_ShouldBePiRadiusRadius_GivenUnitCircle()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class ColorTests public class ColorTests
{ {
private static readonly Color Black = Color.FromArgb(0, 0, 0); private static readonly Color Black = Color.FromArgb(0, 0, 0);
private static readonly Color White = Color.FromArgb(255, 255, 255); private static readonly Color White = Color.FromArgb(255, 255, 255);
@ -207,7 +207,9 @@ internal class ColorTests
Assert.That(Color.Plum.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray)); Assert.That(Color.Plum.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray));
Assert.That(Color.PowderBlue.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray)); Assert.That(Color.PowderBlue.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray));
Assert.That(Color.Purple.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkMagenta)); Assert.That(Color.Purple.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkMagenta));
#if NET6_0_OR_GREATER
Assert.That(Color.RebeccaPurple.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkMagenta)); Assert.That(Color.RebeccaPurple.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkMagenta));
#endif
Assert.That(Color.Red.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.Red)); Assert.That(Color.Red.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.Red));
Assert.That(Color.RosyBrown.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray)); Assert.That(Color.RosyBrown.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkGray));
Assert.That(Color.RoyalBlue.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkCyan)); Assert.That(Color.RoyalBlue.GetClosestConsoleColor(), Is.EqualTo(ConsoleColor.DarkCyan));

View File

@ -1,11 +1,11 @@
using System.Numerics; using System.Numerics;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class CuboidTests public class CuboidTests
{ {
[Test] [Test]
public void Corners_ShouldBeCorrect_GivenCubeOfSize1() public void Corners_ShouldBeCorrect_GivenCubeOfSize1()

View File

@ -1,4 +1,4 @@
using System.Drawing; using System.Drawing;
using System.Numerics; using System.Numerics;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
@ -6,7 +6,7 @@ using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class EllipseFTests public class EllipseFTests
{ {
[Test] [Test]
public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse() public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class EllipseTests public class EllipseTests
{ {
[Test] [Test]
public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse() public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse()

View File

@ -1,4 +1,4 @@
using System.Drawing; using System.Drawing;
using System.Numerics; using System.Numerics;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
@ -6,7 +6,7 @@ using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class Line3DTests public class Line3DTests
{ {
[Test] [Test]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne() public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class LineFTests public class LineFTests
{ {
[Test] [Test]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne() public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class LineTests public class LineTests
{ {
[Test] [Test]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne() public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()

View File

@ -1,4 +1,4 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
#if !NET6_0_OR_GREATER #if !NET6_0_OR_GREATER
using X10D.Core; using X10D.Core;
@ -8,7 +8,7 @@ using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class PointFTests public class PointFTests
{ {
[Test] [Test]
public void IsOnLine_ShouldReturnTrue_GivenPointOnLine() public void IsOnLine_ShouldReturnTrue_GivenPointOnLine()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class PointTests public class PointTests
{ {
[Test] [Test]
public void IsOnLine_ShouldReturnTrue_GivenPointOnLine() public void IsOnLine_ShouldReturnTrue_GivenPointOnLine()

View File

@ -1,4 +1,4 @@
using System.Drawing; using System.Drawing;
using System.Numerics; using System.Numerics;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
@ -6,7 +6,7 @@ using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class PolygonFTests public class PolygonFTests
{ {
[Test] [Test]
public void AddVertices_ShouldAddVertices() public void AddVertices_ShouldAddVertices()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class PolygonTests public class PolygonTests
{ {
[Test] [Test]
public void AddVertices_ShouldAddVertices() public void AddVertices_ShouldAddVertices()

View File

@ -1,11 +1,11 @@
using System.Numerics; using System.Numerics;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class PolyhedronTests public class PolyhedronTests
{ {
[Test] [Test]
public void AddVertices_ShouldAddVertices() public void AddVertices_ShouldAddVertices()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class RandomTests public class RandomTests
{ {
[Test] [Test]
public void NextColorArgb_ShouldReturn331515e5_GivenSeed1234() public void NextColorArgb_ShouldReturn331515e5_GivenSeed1234()

View File

@ -1,11 +1,11 @@
using System.Drawing; using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class SizeTests public class SizeTests
{ {
[Test] [Test]
public void ToPoint_ShouldReturnPoint_WithEquivalentMembers() public void ToPoint_ShouldReturnPoint_WithEquivalentMembers()

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.Drawing; using X10D.Drawing;
namespace X10D.Tests.Drawing; namespace X10D.Tests.Drawing;
[TestFixture] [TestFixture]
internal class SphereTests public class SphereTests
{ {
[Test] [Test]
public void Circumference_ShouldBe2PiRadius_GivenUnitCircle() public void Circumference_ShouldBe2PiRadius_GivenUnitCircle()

View File

@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using NUnit.Framework; using NUnit.Framework;
using X10D.Hosting.DependencyInjection; using X10D.Hosting.DependencyInjection;
@ -6,7 +6,7 @@ using X10D.Hosting.DependencyInjection;
namespace X10D.Tests.Hosting; namespace X10D.Tests.Hosting;
[TestFixture] [TestFixture]
internal class ServiceCollectionTests public class ServiceCollectionTests
{ {
[Test] [Test]
public void AddHostedSingleton_ShouldRegisterServiceAsSingletonAndAsHostedService() public void AddHostedSingleton_ShouldRegisterServiceAsSingletonAndAsHostedService()

View File

@ -1,10 +1,10 @@
using NUnit.Framework; using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class BooleanTests public class BooleanTests
{ {
[Test] [Test]
public void GetBytes_ReturnsArrayContaining1() public void GetBytes_ReturnsArrayContaining1()

View File

@ -4,7 +4,7 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class ByteTests public class ByteTests
{ {
[Test] [Test]
public void GetBytes_ReturnsArrayContainingItself() public void GetBytes_ReturnsArrayContainingItself()

View File

@ -1,72 +0,0 @@
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);
}
}

View File

@ -4,7 +4,7 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class DirectoryInfoTests public class DirectoryInfoTests
{ {
[Test] [Test]
public void Clear_ShouldClear_GivenValidDirectory() public void Clear_ShouldClear_GivenValidDirectory()

View File

@ -4,63 +4,63 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class DoubleTests public class DoubleTests
{ {
[Test] [Test]
public void GetBigEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue()
{ {
const double value = 42.5; const double value = 42.5;
byte[] bytes = BitConverter.IsLittleEndian
var expected = new byte[] { 0x40, 0x45, 0x40, 0, 0, 0, 0, 0 }; ? new byte[] {0, 0, 0, 0, 0, 0x40, 0x45, 0x40}
byte[] actual = value.GetBigEndianBytes(); : new byte[] {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
CollectionAssert.AreEqual(expected, actual); CollectionAssert.AreEqual(bytes, value.GetBytes());
} }
[Test] [Test]
public void GetLittleEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue_WithEndianness()
{ {
const double value = 42.5; const double value = 42.5;
byte[] littleEndian = {0, 0, 0, 0, 0, 0x40, 0x45, 0x40};
byte[] bigEndian = {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
var expected = new byte[] { 0, 0, 0, 0, 0, 0x40, 0x45, 0x40 }; CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
byte[] actual = value.GetLittleEndianBytes(); CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{ {
const double value = 42.5; const double value = 42.5;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0, 0, 0, 0x40, 0x45, 0x40}
: new byte[] {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
var expected = new byte[] { 0x40, 0x45, 0x40, 0, 0, 0, 0, 0 }; Span<byte> buffer = stackalloc byte[8];
Span<byte> actual = stackalloc byte[8]; Assert.That(value.TryWriteBytes(buffer));
Assert.That(value.TryWriteBigEndianBytes(actual)); CollectionAssert.AreEqual(bytes, buffer.ToArray());
CollectionAssert.AreEqual(expected, actual.ToArray());
} }
[Test] [Test]
public void TryWriteLittleEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{ {
const double value = 42.5; const double value = 42.5;
byte[] littleEndian = {0, 0, 0, 0, 0, 0x40, 0x45, 0x40};
byte[] bigEndian = {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
var expected = new byte[] { 0, 0, 0, 0, 0, 0x40, 0x45, 0x40 }; Span<byte> buffer = stackalloc byte[8];
Span<byte> actual = stackalloc byte[8];
Assert.That(value.TryWriteLittleEndianBytes(actual)); Assert.That(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(expected, actual.ToArray()); CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.That(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsFalse_GivenSmallSpan() public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{ {
const double value = 42.5; const double value = 42.5;
Span<byte> buffer = stackalloc byte[0]; Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteBigEndianBytes(buffer), Is.False); Assert.That(value.TryWriteBytes(buffer), Is.False);
}
[Test]
public void TryWriteLittleEndian_RReturnsFalse_GivenSmallSpan()
{
const double value = 42.5;
Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteLittleEndianBytes(buffer), Is.False);
} }
} }

View File

@ -5,7 +5,7 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class FileInfoTests public class FileInfoTests
{ {
[Test] [Test]
public void GetHashSha1ShouldBeCorrect() public void GetHashSha1ShouldBeCorrect()

View File

@ -4,63 +4,59 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class Int16Tests public class Int16Tests
{ {
[Test] [Test]
public void GetLittleEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue()
{ {
const short value = 0x0F; const short value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
byte[] expected = { 0x0F, 0 }; CollectionAssert.AreEqual(bytes, value.GetBytes());
byte[] actual = value.GetLittleEndianBytes();
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void GetBigEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue_WithEndianness()
{ {
const short value = 0x0F; const short value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
byte[] expected = { 0, 0x0F }; CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
byte[] actual = value.GetBigEndianBytes(); CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void TryWriteLittleEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{ {
const short value = 0x0F; const short value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
byte[] expected = { 0x0F, 0 }; Span<byte> buffer = stackalloc byte[2];
Span<byte> actual = stackalloc byte[2]; Assert.That(value.TryWriteBytes(buffer));
Assert.That(value.TryWriteLittleEndianBytes(actual)); CollectionAssert.AreEqual(bytes, buffer.ToArray());
CollectionAssert.AreEqual(expected, actual.ToArray());
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{ {
const short value = 0x0F; const short value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
byte[] expected = { 0, 0x0F }; Span<byte> buffer = stackalloc byte[2];
Span<byte> actual = stackalloc byte[2];
Assert.That(value.TryWriteBigEndianBytes(actual)); Assert.That(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(expected, actual.ToArray()); CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.That(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
} }
[Test] [Test]
public void TryWriteLittleEndian_RReturnsFalse_GivenSmallSpan() public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{ {
const short value = 0x0F; const short value = 0x0F;
Span<byte> buffer = stackalloc byte[0]; Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteLittleEndianBytes(buffer), Is.False); Assert.That(value.TryWriteBytes(buffer), Is.False);
}
[Test]
public void TryWriteBigEndian_ReturnsFalse_GivenSmallSpan()
{
const short value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteBigEndianBytes(buffer), Is.False);
} }
} }

View File

@ -4,63 +4,59 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class Int32Tests public class Int32Tests
{ {
[Test] [Test]
public void GetBigEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue()
{ {
const int value = 0x0F; const int value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
var expected = new byte[] { 0, 0, 0, 0x0F }; CollectionAssert.AreEqual(bytes, value.GetBytes());
byte[] actual = value.GetBigEndianBytes();
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void GetLittleEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue_WithEndianness()
{ {
const int value = 0x0F; const int value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
var expected = new byte[] { 0x0F, 0, 0, 0 }; CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
byte[] actual = value.GetLittleEndianBytes(); CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{ {
const int value = 0x0F; const int value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
var expected = new byte[] { 0, 0, 0, 0x0F }; Span<byte> buffer = stackalloc byte[4];
Span<byte> actual = stackalloc byte[4]; Assert.That(value.TryWriteBytes(buffer));
Assert.That(value.TryWriteBigEndianBytes(actual)); CollectionAssert.AreEqual(bytes, buffer.ToArray());
CollectionAssert.AreEqual(expected, actual.ToArray());
} }
[Test] [Test]
public void TryWriteLittleEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{ {
const int value = 0x0F; const int value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
var expected = new byte[] { 0x0F, 0, 0, 0 }; Span<byte> buffer = stackalloc byte[4];
Span<byte> actual = stackalloc byte[4];
Assert.That(value.TryWriteLittleEndianBytes(actual)); Assert.That(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(expected, actual.ToArray()); CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.That(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsFalse_GivenSmallSpan() public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{ {
const int value = 0x0F; const int value = 0x0F;
Span<byte> buffer = stackalloc byte[0]; Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteBigEndianBytes(buffer), Is.False); Assert.That(value.TryWriteBytes(buffer), Is.False);
}
[Test]
public void TryWriteLittleEndian_RReturnsFalse_GivenSmallSpan()
{
const int value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteLittleEndianBytes(buffer), Is.False);
} }
} }

View File

@ -4,63 +4,63 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class Int64Tests public class Int64Tests
{ {
[Test] [Test]
public void GetLittleEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue()
{ {
const long value = 0x0F; const long value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
byte[] expected = { 0x0F, 0, 0, 0, 0, 0, 0, 0 }; ? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
byte[] actual = value.GetLittleEndianBytes(); : new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
CollectionAssert.AreEqual(expected, actual); CollectionAssert.AreEqual(bytes, value.GetBytes());
} }
[Test] [Test]
public void GetBigEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue_WithEndianness()
{ {
const long value = 0x0F; const long value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
byte[] expected = { 0, 0, 0, 0, 0, 0, 0, 0x0F }; CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
byte[] actual = value.GetBigEndianBytes(); CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void TryWriteLittleEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{ {
const long value = 0x0F; const long value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
: new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
byte[] expected = { 0x0F, 0, 0, 0, 0, 0, 0, 0 }; Span<byte> buffer = stackalloc byte[8];
Span<byte> actual = stackalloc byte[8]; Assert.That(value.TryWriteBytes(buffer));
Assert.That(value.TryWriteLittleEndianBytes(actual)); CollectionAssert.AreEqual(bytes, buffer.ToArray());
CollectionAssert.AreEqual(expected, actual.ToArray());
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{ {
const long value = 0x0F; const long value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
byte[] expected = { 0, 0, 0, 0, 0, 0, 0, 0x0F }; Span<byte> buffer = stackalloc byte[8];
Span<byte> actual = stackalloc byte[8];
Assert.That(value.TryWriteBigEndianBytes(actual)); Assert.That(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(expected, actual.ToArray()); CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.That(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
} }
[Test] [Test]
public void TryWriteLittleEndian_RReturnsFalse_GivenSmallSpan() public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{ {
const long value = 0x0F; const long value = 0x0F;
Span<byte> buffer = stackalloc byte[0]; Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteLittleEndianBytes(buffer), Is.False); Assert.That(value.TryWriteBytes(buffer), Is.False);
}
[Test]
public void TryWriteBigEndian_ReturnsFalse_GivenSmallSpan()
{
const long value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteBigEndianBytes(buffer), Is.False);
} }
} }

View File

@ -5,7 +5,7 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class ListOfByteTests public class ListOfByteTests
{ {
[Test] [Test]
public void AsString_ShouldReturnBytes_GivenBytes() public void AsString_ShouldReturnBytes_GivenBytes()

View File

@ -4,7 +4,8 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class SByteTests [CLSCompliant(false)]
public class SByteTests
{ {
[Test] [Test]
public void GetBytes_ReturnsArrayContainingItself() public void GetBytes_ReturnsArrayContainingItself()

View File

@ -4,63 +4,63 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
[TestFixture] [TestFixture]
internal class SingleTests public class SingleTests
{ {
[Test] [Test]
public void GetBigEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue()
{ {
const float value = 42.5f; const float value = 42.5f;
byte[] bytes = BitConverter.IsLittleEndian
var expected = new byte[] { 0x42, 0x2A, 0, 0 }; ? new byte[] {0, 0, 0x2A, 0x42}
byte[] actual = value.GetBigEndianBytes(); : new byte[] {0x42, 0x2A, 0, 0};
CollectionAssert.AreEqual(expected, actual); CollectionAssert.AreEqual(bytes, value.GetBytes());
} }
[Test] [Test]
public void GetLittleEndianBytes_ReturnsCorrectValue() public void GetBytes_ReturnsCorrectValue_WithEndianness()
{ {
const float value = 42.5f; const float value = 42.5f;
byte[] littleEndian = {0, 0, 0x2A, 0x42};
byte[] bigEndian = {0x42, 0x2A, 0, 0};
var expected = new byte[] { 0, 0, 0x2A, 0x42 }; CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
byte[] actual = value.GetLittleEndianBytes(); CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
CollectionAssert.AreEqual(expected, actual);
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{ {
const float value = 42.5f; const float value = 42.5f;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0x2A, 0x42}
: new byte[] {0x42, 0x2A, 0, 0};
var expected = new byte[] { 0x42, 0x2A, 0, 0 }; Span<byte> buffer = stackalloc byte[4];
Span<byte> actual = stackalloc byte[4]; Assert.That(value.TryWriteBytes(buffer));
Assert.That(value.TryWriteBigEndianBytes(actual)); CollectionAssert.AreEqual(bytes, buffer.ToArray());
CollectionAssert.AreEqual(expected, actual.ToArray());
} }
[Test] [Test]
public void TryWriteLittleEndian_ReturnsTrue_FillsSpanCorrectly() public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{ {
const float value = 42.5f; const float value = 42.5f;
byte[] littleEndian = {0, 0, 0x2A, 0x42};
byte[] bigEndian = {0x42, 0x2A, 0, 0};
var expected = new byte[] { 0, 0, 0x2A, 0x42 }; Span<byte> buffer = stackalloc byte[4];
Span<byte> actual = stackalloc byte[4];
Assert.That(value.TryWriteLittleEndianBytes(actual)); Assert.That(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(expected, actual.ToArray()); CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.That(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
} }
[Test] [Test]
public void TryWriteBigEndian_ReturnsFalse_GivenSmallSpan() public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{ {
const float value = 42.5f; const float value = 42.5f;
Span<byte> buffer = stackalloc byte[0]; Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteBigEndianBytes(buffer), Is.False); Assert.That(value.TryWriteBytes(buffer), Is.False);
}
[Test]
public void TryWriteLittleEndian_RReturnsFalse_GivenSmallSpan()
{
const float value = 42.5f;
Span<byte> buffer = stackalloc byte[0];
Assert.That(value.TryWriteLittleEndianBytes(buffer), Is.False);
} }
} }

View File

@ -1,43 +1,42 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadDecimalBigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadDecimal_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadDecimalBigEndian());
}
[Test]
public void ReadDecimalLittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadDecimalLittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadDecimalBigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadDecimalBigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadDecimal());
Assert.Throws<ArgumentException>(() => stream.ReadDecimal(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadDecimal(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void ReadDecimal_ShouldThrowArgumentNullException_GivenNullStream()
public void ReadDecimalLittleEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadDecimalLittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadDecimal());
Assert.Throws<ArgumentNullException>(() => stream.ReadDecimal(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadDecimal(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadDecimalBigEndian_ShouldReadBigEndian() public void ReadDecimal_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadDecimal((Endianness)(-1)));
}
[Test]
public void ReadDecimal_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] ReadOnlySpan<byte> bytes = stackalloc byte[]
@ -48,7 +47,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const decimal expected = 420.0m; const decimal expected = 420.0m;
decimal actual = stream.ReadDecimalBigEndian(); decimal actual = stream.ReadDecimal(Endianness.BigEndian);
Assert.Multiple(() => Assert.Multiple(() =>
{ {
@ -58,7 +57,7 @@ internal partial class StreamTests
} }
[Test] [Test]
public void ReadDecimalLittleEndian_ShouldWriteLittleEndian() public void ReadDecimal_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] ReadOnlySpan<byte> bytes = stackalloc byte[]
@ -69,7 +68,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const decimal expected = 420.0m; const decimal expected = 420.0m;
decimal actual = stream.ReadDecimalLittleEndian(); decimal actual = stream.ReadDecimal(Endianness.LittleEndian);
Assert.Multiple(() => Assert.Multiple(() =>
{ {

View File

@ -1,43 +1,42 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadDoubleBigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadDouble_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadDoubleBigEndian());
}
[Test]
public void ReadDoubleLittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadDoubleLittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadDoubleBigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadDoubleBigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadDouble());
Assert.Throws<ArgumentException>(() => stream.ReadDouble(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadDouble(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void ReadDouble_ShouldThrowArgumentNullException_GivenNullStream()
public void ReadDoubleLittleEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadDoubleLittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadDouble());
Assert.Throws<ArgumentNullException>(() => stream.ReadDouble(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadDouble(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadDoubleBigEndian_ShouldReadBigEndian() public void ReadDouble_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadDouble((Endianness)(-1)));
}
[Test]
public void ReadDouble_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x40, 0x7A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x40, 0x7A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -45,14 +44,14 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const double expected = 420.0; const double expected = 420.0;
double actual = stream.ReadDoubleBigEndian(); double actual = stream.ReadDouble(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadDoubleLittleEndian_ShouldWriteLittleEndian() public void ReadDouble_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40};
@ -60,7 +59,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const double expected = 420.0; const double expected = 420.0;
double actual = stream.ReadDoubleLittleEndian(); double actual = stream.ReadDouble(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,42 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadInt16BigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadInt16_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt16BigEndian());
}
[Test]
public void ReadInt16LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt16LittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadInt16BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadInt16BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadInt16());
Assert.Throws<ArgumentException>(() => stream.ReadInt16(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadInt16(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void ReadInt16_ShouldThrowArgumentNullException_GivenNullStream()
public void ReadInt16LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadInt16LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadInt16());
Assert.Throws<ArgumentNullException>(() => stream.ReadInt16(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadInt16(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadInt16BigEndian_ShouldReadBigEndian() public void ReadInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadInt16((Endianness)(-1)));
}
[Test]
public void ReadInt16_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x01, 0xA4};
@ -45,14 +44,14 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const short expected = 420; const short expected = 420;
short actual = stream.ReadInt16BigEndian(); short actual = stream.ReadInt16(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadInt16LittleEndian_ShouldReadLittleEndian() public void ReadInt16_ShouldReadLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01};
@ -60,7 +59,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const short expected = 420; const short expected = 420;
short actual = stream.ReadInt16LittleEndian(); short actual = stream.ReadInt16(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,42 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadInt32BigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadInt32_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt32BigEndian());
}
[Test]
public void ReadInt32LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt32LittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadInt32BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadInt32BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadInt32());
Assert.Throws<ArgumentException>(() => stream.ReadInt32(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadInt32(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void ReadInt32_ShouldThrowArgumentNullException_GivenNullStream()
public void ReadInt32LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadInt32LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadInt32());
Assert.Throws<ArgumentNullException>(() => stream.ReadInt32(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadInt32(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadInt32BigEndian_ShouldReadBigEndian() public void ReadInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadInt32((Endianness)(-1)));
}
[Test]
public void ReadInt32_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4};
@ -45,14 +44,14 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const int expected = 420; const int expected = 420;
int actual = stream.ReadInt32BigEndian(); int actual = stream.ReadInt32(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadInt32LittleEndian_ShouldReadLittleEndian() public void ReadInt32_ShouldReadLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00};
@ -60,7 +59,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const int expected = 420; const int expected = 420;
int actual = stream.ReadInt32LittleEndian(); int actual = stream.ReadInt32(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -3,38 +3,40 @@ using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadInt64BigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadInt64_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt64BigEndian());
}
[Test]
public void ReadInt64LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadInt64LittleEndian());
}
[Test]
public void ReadInt64BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadInt64BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadInt64());
Assert.Throws<ArgumentException>(() => stream.ReadInt64(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadInt64(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadInt64LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream() public void ReadInt64_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadInt64LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadInt64());
Assert.Throws<ArgumentNullException>(() => stream.ReadInt64(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadInt64(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadInt64BigEndian_ShouldReadBigEndian() public void ReadInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadInt64((Endianness)(-1)));
}
[Test]
public void ReadInt64_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4};
@ -42,14 +44,14 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const long expected = 420; const long expected = 420;
long actual = stream.ReadInt64BigEndian(); long actual = stream.ReadInt64(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadInt64LittleEndian_ShouldWriteLittleEndian() public void ReadInt64_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -57,7 +59,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const long expected = 420; const long expected = 420;
long actual = stream.ReadInt64LittleEndian(); long actual = stream.ReadInt64(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,42 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadSingleBigEndian_ShouldThrowArgumentNullException_GivenNullStream() public void ReadSingle_ShouldThrowArgumentException_GivenNonReadableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadSingleBigEndian());
}
[Test]
public void ReadSingleLittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadSingleLittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadSingleBigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadSingleBigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadSingle());
Assert.Throws<ArgumentException>(() => stream.ReadSingle(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadSingle(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void ReadSingle_ShouldThrowArgumentNullException_GivenNullStream()
public void ReadSingleLittleEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadSingleLittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadSingle());
Assert.Throws<ArgumentNullException>(() => stream.ReadSingle(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadSingle(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadSingleBigEndian_ShouldReadBigEndian() public void ReadSingle_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadSingle((Endianness)(-1)));
}
[Test]
public void ReadSingle_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x43, 0xD2, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x43, 0xD2, 0x00, 0x00};
@ -45,14 +44,14 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const float expected = 420.0f; const float expected = 420.0f;
float actual = stream.ReadSingleBigEndian(); float actual = stream.ReadSingle(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadSingleLittleEndian_ShouldReadLittleEndian() public void ReadSingle_ShouldReadLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0xD2, 0x43}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0xD2, 0x43};
@ -60,7 +59,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const float expected = 420.0f; const float expected = 420.0f;
float actual = stream.ReadSingleLittleEndian(); float actual = stream.ReadSingle(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,46 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadUInt16BigEndian_ShouldThrowArgumentNullException_GivenNullStream() [CLSCompliant(false)]
{ public void ReadUInt16_ShouldThrowArgumentException_GivenNonReadableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt16BigEndian());
}
[Test]
public void ReadUInt16LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt16LittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadUInt16BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadUInt16BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadUInt16());
Assert.Throws<ArgumentException>(() => stream.ReadUInt16(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadUInt16(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void ReadUInt16LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream() public void ReadUInt16_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadUInt16LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadUInt16());
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt16(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt16(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadUInt16BigEndian_ShouldReadBigEndian() [CLSCompliant(false)]
public void ReadUInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadUInt16((Endianness)(-1)));
}
[Test]
[CLSCompliant(false)]
public void ReadUInt16_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x01, 0xA4};
@ -45,14 +48,15 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const ushort expected = 420; const ushort expected = 420;
ushort actual = stream.ReadUInt16BigEndian(); ushort actual = stream.ReadUInt16(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadUInt16LittleEndian_ShouldReadLittleEndian() [CLSCompliant(false)]
public void ReadUInt16_ShouldReadLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01};
@ -60,7 +64,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const ushort expected = 420; const ushort expected = 420;
ushort actual = stream.ReadUInt16LittleEndian(); ushort actual = stream.ReadUInt16(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,46 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadUInt32BigEndian_ShouldThrowArgumentNullException_GivenNullStream() [CLSCompliant(false)]
{ public void ReadUInt32_ShouldThrowArgumentException_GivenNonReadableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt32BigEndian());
}
[Test]
public void ReadUInt32LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt32LittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadUInt32BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadUInt32BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadUInt32());
Assert.Throws<ArgumentException>(() => stream.ReadUInt32(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadUInt32(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void ReadUInt32LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream() public void ReadUInt32_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadUInt32LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadUInt32());
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt32(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt32(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadUInt32BigEndian_ShouldReadBigEndian() [CLSCompliant(false)]
public void ReadUInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadUInt32((Endianness)(-1)));
}
[Test]
[CLSCompliant(false)]
public void ReadUInt32_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4};
@ -45,14 +48,15 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const uint expected = 420; const uint expected = 420;
uint actual = stream.ReadUInt32BigEndian(); uint actual = stream.ReadUInt32(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadUInt32LittleEndian_ShouldReadLittleEndian() [CLSCompliant(false)]
public void ReadUInt32_ShouldReadLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00};
@ -60,7 +64,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const uint expected = 420; const uint expected = 420;
uint actual = stream.ReadUInt32LittleEndian(); uint actual = stream.ReadUInt32(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,43 +1,46 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void ReadUInt64BigEndian_ShouldThrowArgumentNullException_GivenNullStream() [CLSCompliant(false)]
{ public void ReadUInt64_ShouldThrowArgumentException_GivenNonReadableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt64BigEndian());
}
[Test]
public void ReadUInt64LittleEndian_ShouldThrowArgumentNullException_GivenNullStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt64LittleEndian());
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void ReadUInt64BigEndian_ShouldThrowArgumentException_GivenNonReadableStream()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.ReadUInt64BigEndian()); Assert.Throws<ArgumentException>(() => stream.ReadUInt64());
Assert.Throws<ArgumentException>(() => stream.ReadUInt64(Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.ReadUInt64(Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void ReadUInt64LittleEndian_ShouldThrowArgumentException_GivenNonReadableStream() public void ReadUInt64_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = new DummyStream(); Stream stream = null!;
Assert.Throws<ArgumentException>(() => stream.ReadUInt64LittleEndian()); Assert.Throws<ArgumentNullException>(() => stream.ReadUInt64());
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt64(Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.ReadUInt64(Endianness.BigEndian));
} }
[Test] [Test]
public void ReadUInt64BigEndian_ShouldReadBigEndian() [CLSCompliant(false)]
public void ReadUInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{
// we don't need to enclose this stream in a using declaration, since disposing a
// null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.ReadUInt64((Endianness)(-1)));
}
[Test]
[CLSCompliant(false)]
public void ReadUInt64_ShouldReadBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4};
@ -45,14 +48,15 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const ulong expected = 420; const ulong expected = 420;
ulong actual = stream.ReadUInt64BigEndian(); ulong actual = stream.ReadUInt64(Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));
} }
[Test] [Test]
public void ReadUInt64LittleEndian_ShouldWriteLittleEndian() [CLSCompliant(false)]
public void ReadUInt64_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ReadOnlySpan<byte> bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -60,7 +64,7 @@ internal partial class StreamTests
stream.Position = 0; stream.Position = 0;
const ulong expected = 420; const ulong expected = 420;
ulong actual = stream.ReadUInt64LittleEndian(); ulong actual = stream.ReadUInt64(Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
Assert.That(actual, Is.EqualTo(expected)); Assert.That(actual, Is.EqualTo(expected));

View File

@ -1,47 +1,45 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using NUnit.Framework; using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndDecimalArgument() public void WriteDecimal_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420.0m));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndDecimalArgument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420.0m)); Assert.Throws<ArgumentException>(() => stream.Write(420.0m, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420.0m, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndDecimalArgument() public void WriteDecimal_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420.0m)); Assert.Throws<ArgumentNullException>(() => stream.Write(420.0m, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420.0m, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteDecimal_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndDecimalArgument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420.0m)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0m, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0m, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenDecimalArgument() public void WriteDecimal_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420.0m); stream.Write(420.0m, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(16)); Assert.That(stream.Position, Is.EqualTo(16));
stream.Position = 0; stream.Position = 0;
@ -51,17 +49,16 @@ internal partial class StreamTests
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x68 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());
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenDecimalArgument() public void WriteDecimal_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420.0m); stream.Write(420.0m, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(16)); Assert.That(stream.Position, Is.EqualTo(16));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,44 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndDoubleArgument() public void WriteDouble_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420.0));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndDoubleArgument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420.0)); Assert.Throws<ArgumentException>(() => stream.Write(420.0, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420.0, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndDoubleArgument() public void WriteDouble_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420.0)); Assert.Throws<ArgumentNullException>(() => stream.Write(420.0, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420.0, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteDouble_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndDoubleArgument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420.0)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenDoubleArgument() public void WriteDouble_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420.0); stream.Write(420.0, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;
@ -53,10 +51,10 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenDoubleArgument() public void WriteDouble_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420.0); stream.Write(420.0, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,44 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt16Argument() public void WriteInt16_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian((short)420));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt16Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian((short)420)); Assert.Throws<ArgumentException>(() => stream.Write((short)420, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write((short)420, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt16Argument() public void WriteInt16_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian((short)420)); Assert.Throws<ArgumentNullException>(() => stream.Write((short)420, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write((short)420, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt16Argument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian((short)420)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write((short)420, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write((short)420, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenInt16Argument() public void WriteInt16_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian((short)420); stream.Write((short)420, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
stream.Position = 0; stream.Position = 0;
@ -53,10 +51,10 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenInt16Argument() public void WriteInt16_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian((short)420); stream.Write((short)420, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,44 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt32Argument() public void WriteInt32_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt32Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420)); Assert.Throws<ArgumentException>(() => stream.Write(420, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt32Argument() public void WriteInt32_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420)); Assert.Throws<ArgumentNullException>(() => stream.Write(420, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt32Argument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenInt32Argument() public void WriteInt32_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420); stream.Write(420, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;
@ -53,10 +51,10 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenInt32Argument() public void WriteInt32_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420); stream.Write(420, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,44 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt64Argument() public void WriteInt64_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420L));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt64Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420L)); Assert.Throws<ArgumentException>(() => stream.Write(420L, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420L, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndInt64Argument() public void WriteInt64_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420L)); Assert.Throws<ArgumentNullException>(() => stream.Write(420L, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420L, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndInt64Argument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420L)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420L, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420L, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenInt64Argument() public void WriteInt64_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420L); stream.Write(420L, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;
@ -53,10 +51,10 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenLittleEndian() public void WriteInt64_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420L); stream.Write(420L, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,44 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndSingleArgument() public void WriteSingle_ShouldThrowArgumentException_GivenNonWriteableStream()
{
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420.0f));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndSingleArgument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420.0f)); Assert.Throws<ArgumentException>(() => stream.Write(420.0f, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420.0f, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndSingleArgument() public void WriteSingle_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420.0f)); Assert.Throws<ArgumentNullException>(() => stream.Write(420.0f, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420.0f, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public void WriteSingle_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndSingleArgument()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420.0f)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0f, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420.0f, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenSingleArgument() public void WriteSingle_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420.0f); stream.Write(420.0f, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;
@ -53,10 +51,10 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenSingleArgument() public void WriteSingle_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420.0f); stream.Write(420.0f, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,48 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt16Argument() [CLSCompliant(false)]
{ public void WriteUInt16_ShouldThrowArgumentException_GivenNonWriteableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian((ushort)420));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt16Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian((ushort)420)); Assert.Throws<ArgumentException>(() => stream.Write((ushort)420, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write((ushort)420, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt16Argument() [CLSCompliant(false)]
public void WriteUInt16_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian((ushort)420)); Assert.Throws<ArgumentNullException>(() => stream.Write((ushort)420, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write((ushort)420, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt16Argument() public void WriteUInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian((ushort)420)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write((ushort)420, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write((ushort)420, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenUInt16Endian() [CLSCompliant(false)]
public void WriteUInt16_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian((ushort)420); stream.Write((ushort)420, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
stream.Position = 0; stream.Position = 0;
@ -53,10 +55,11 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenUInt16tleEndian() [CLSCompliant(false)]
public void WriteUInt16_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian((ushort)420); stream.Write((ushort)420, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(2)); Assert.That(stream.Position, Is.EqualTo(2));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,48 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt32Argument() [CLSCompliant(false)]
{ public void WriteUInt32_ShouldThrowArgumentException_GivenNonWriteableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420U));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt32Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420U)); Assert.Throws<ArgumentException>(() => stream.Write(420U, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420U, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt32Argument() [CLSCompliant(false)]
public void WriteUInt32_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420U)); Assert.Throws<ArgumentNullException>(() => stream.Write(420U, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420U, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt32Argument() public void WriteUInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420U)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420U, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420U, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenUInt32Argument() [CLSCompliant(false)]
public void WriteUInt32_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420U); stream.Write(420U, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;
@ -53,10 +55,11 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenUInt32Argument() [CLSCompliant(false)]
public void WriteUInt32_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420U); stream.Write(420U, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(4)); Assert.That(stream.Position, Is.EqualTo(4));
stream.Position = 0; stream.Position = 0;

View File

@ -1,46 +1,48 @@
using System.Diagnostics.CodeAnalysis; using NUnit.Framework;
using NUnit.Framework;
using X10D.IO; using X10D.IO;
namespace X10D.Tests.IO; namespace X10D.Tests.IO;
internal partial class StreamTests public partial class StreamTests
{ {
[Test] [Test]
public void WriteBigEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt64Argument() [CLSCompliant(false)]
{ public void WriteUInt64_ShouldThrowArgumentException_GivenNonWriteableStream()
Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteBigEndian(420UL));
}
[Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public void WriteBigEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt64Argument()
{ {
Stream stream = new DummyStream(); Stream stream = new DummyStream();
Assert.Throws<ArgumentException>(() => stream.WriteBigEndian(420UL)); Assert.Throws<ArgumentException>(() => stream.Write(420UL, Endianness.LittleEndian));
Assert.Throws<ArgumentException>(() => stream.Write(420UL, Endianness.BigEndian));
} }
[Test] [Test]
public void WriteLittleEndian_ShouldThrowArgumentNullException_GivenNullStream_AndUInt64Argument() [CLSCompliant(false)]
public void WriteUInt64_ShouldThrowArgumentNullException_GivenNullStream()
{ {
Stream stream = null!; Stream stream = null!;
Assert.Throws<ArgumentNullException>(() => stream.WriteLittleEndian(420UL)); Assert.Throws<ArgumentNullException>(() => stream.Write(420UL, Endianness.LittleEndian));
Assert.Throws<ArgumentNullException>(() => stream.Write(420UL, Endianness.BigEndian));
} }
[Test] [Test]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] [CLSCompliant(false)]
public void WriteLittleEndian_ShouldThrowArgumentException_GivenNonWritableStream_AndUInt64Argument() public void WriteUInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue()
{ {
Stream stream = new DummyStream(); // we don't need to enclose this stream in a using declaration, since disposing a
Assert.Throws<ArgumentException>(() => stream.WriteLittleEndian(420UL)); // null stream is meaningless. NullStream.Dispose actually does nothing, anyway.
// that - coupled with the fact that encapsulating the stream in a using declaration causes the
// analyser to trip up and think the stream is disposed by the time the local is captured in
// assertion lambda - means this line is fine as it is. please do not change.
Stream stream = Stream.Null;
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420UL, (Endianness)(-1)));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(420UL, (Endianness)(-1)));
} }
[Test] [Test]
public void WriteBigEndian_ShouldWriteBigEndian_GivenUInt64Argument() [CLSCompliant(false)]
public void WriteUInt64_ShouldWriteBigEndian_GivenBigEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteBigEndian(420UL); stream.Write(420UL, Endianness.BigEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;
@ -53,10 +55,11 @@ internal partial class StreamTests
} }
[Test] [Test]
public void WriteLittleEndian_ShouldWriteLittleEndian_GivenUInt64Argument() [CLSCompliant(false)]
public void WriteUInt64_ShouldWriteLittleEndian_GivenLittleEndian()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
stream.WriteLittleEndian(420UL); stream.Write(420UL, Endianness.LittleEndian);
Assert.That(stream.Position, Is.EqualTo(8)); Assert.That(stream.Position, Is.EqualTo(8));
stream.Position = 0; stream.Position = 0;

Some files were not shown because too many files have changed in this diff Show More